43using namespace object;
49std::optional<DWARFAddressRange>
51 auto Begin =
Ranges.begin();
53 auto Pos = std::lower_bound(Begin,
End, R);
74 return Children.end();
76 auto End = Children.end();
77 auto Iter = Children.begin();
79 if (Iter->intersects(RI))
84 return Children.end();
88 auto I1 = Ranges.begin(), E1 = Ranges.end();
89 auto I2 =
RHS.Ranges.begin(), E2 =
RHS.Ranges.end();
95 bool Covered = I1->LowPC <= R.LowPC;
96 if (R.LowPC == R.HighPC || (Covered && R.HighPC <= I1->HighPC)) {
104 if (R.LowPC < I1->HighPC)
105 R.LowPC = I1->HighPC;
112 auto I1 = Ranges.begin(), E1 = Ranges.end();
113 auto I2 =
RHS.Ranges.begin(), E2 =
RHS.Ranges.end();
114 while (I1 != E1 && I2 != E2) {
115 if (I1->intersects(*I2))
117 if (I1->LowPC < I2->LowPC)
127 uint8_t &
UnitType,
bool &isUnitDWARF64) {
129 uint8_t AddrSize = 0;
133 bool ValidLength =
false;
134 bool ValidVersion =
false;
135 bool ValidAddrSize =
false;
136 bool ValidType =
true;
137 bool ValidAbbrevOffset =
true;
158 if (!AbbrevSetOrErr) {
159 ValidAbbrevOffset =
false;
169 if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
172 bool HeaderShown =
false;
173 auto ShowHeaderOnce = [&]() {
175 error() <<
format(
"Units[%d] - start offset: 0x%08" PRIx64
" \n",
176 UnitIndex, OffsetStart);
182 "Unit Header Length: Unit too large for .debug_info provided", [&]() {
184 note() <<
"The length for this unit is too "
185 "large for the .debug_info provided.\n";
189 "Unit Header Length: 16 bit unit header version is not valid", [&]() {
191 note() <<
"The 16 bit unit header version is not valid.\n";
195 "Unit Header Length: Unit type encoding is not valid", [&]() {
197 note() <<
"The unit type encoding is not valid.\n";
199 if (!ValidAbbrevOffset)
201 "Unit Header Length: Offset into the .debug_abbrev section is not "
205 note() <<
"The offset into the .debug_abbrev section is "
209 ErrorCategory.
Report(
"Unit Header Length: Address size is unsupported",
212 note() <<
"The address size is unsupported.\n";
215 *
Offset = OffsetStart +
Length + (isUnitDWARF64 ? 12 : 4);
219bool DWARFVerifier::verifyName(
const DWARFDie &Die) {
223 std::string ReconstructedName;
225 std::string OriginalFullName;
228 if (OriginalFullName.empty() || OriginalFullName == ReconstructedName)
232 "Simplified template DW_AT_name could not be reconstituted", [&]() {
234 <<
"Simplified template DW_AT_name could not be reconstituted:\n"
236 " reconstituted: {1}\n",
237 OriginalFullName, ReconstructedName);
244unsigned DWARFVerifier::verifyUnitContents(
DWARFUnit &Unit,
245 ReferenceMap &UnitLocalReferences,
246 ReferenceMap &CrossUnitReferences) {
247 unsigned NumUnitErrors = 0;
248 unsigned NumDies = Unit.getNumDIEs();
249 for (
unsigned I = 0;
I < NumDies; ++
I) {
250 auto Die = Unit.getDIEAtIndex(
I);
252 if (Die.
getTag() == DW_TAG_null)
256 NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
257 NumUnitErrors += verifyDebugInfoForm(Die, AttrValue, UnitLocalReferences,
258 CrossUnitReferences);
261 NumUnitErrors += verifyName(Die);
267 <<
" has DW_CHILDREN_yes but DIE has no children: ";
272 NumUnitErrors += verifyDebugInfoCallSite(Die);
275 DWARFDie Die = Unit.getUnitDIE(
false);
277 ErrorCategory.
Report(
"Compilation unit missing DIE", [&]() {
278 error() <<
"Compilation unit without DIE.\n";
281 return NumUnitErrors;
285 ErrorCategory.
Report(
"Compilation unit root DIE is not a unit DIE", [&]() {
286 error() <<
"Compilation unit root DIE is not a unit DIE: "
292 uint8_t
UnitType = Unit.getUnitType();
294 ErrorCategory.
Report(
"Mismatched unit type", [&]() {
297 <<
") do not match.\n";
306 ErrorCategory.
Report(
"Skeleton CU has children", [&]() {
307 error() <<
"Skeleton compilation unit has children.\n";
313 NumUnitErrors += verifyDieRanges(Die, RI);
315 return NumUnitErrors;
318unsigned DWARFVerifier::verifyDebugInfoCallSite(
const DWARFDie &Die) {
319 if (Die.
getTag() != DW_TAG_call_site && Die.
getTag() != DW_TAG_GNU_call_site)
324 if (Curr.
getTag() == DW_TAG_inlined_subroutine) {
326 "Call site nested entry within inlined subroutine", [&]() {
327 error() <<
"Call site entry nested within inlined subroutine:";
336 "Call site entry not nested within valid subprogram", [&]() {
337 error() <<
"Call site entry not nested within a valid subprogram:";
343 std::optional<DWARFFormValue> CallAttr = Curr.
find(
344 {DW_AT_call_all_calls, DW_AT_call_all_source_calls,
345 DW_AT_call_all_tail_calls, DW_AT_GNU_all_call_sites,
346 DW_AT_GNU_all_source_call_sites, DW_AT_GNU_all_tail_call_sites});
349 "Subprogram with call site entry has no DW_AT_call attribute", [&]() {
351 <<
"Subprogram with call site entry has no DW_AT_call attribute:";
361unsigned DWARFVerifier::verifyAbbrevSection(
const DWARFDebugAbbrev *Abbrev) {
367 if (!AbbrDeclsOrErr) {
369 ErrorCategory.
Report(
"Abbreviation Declaration error",
370 [&]() {
error() << ErrMsg <<
"\n"; });
374 const auto *AbbrDecls = *AbbrDeclsOrErr;
375 unsigned NumErrors = 0;
376 for (
auto AbbrDecl : *AbbrDecls) {
378 for (
auto Attribute : AbbrDecl.attributes()) {
382 "Abbreviation declartion contains multiple attributes", [&]() {
383 error() <<
"Abbreviation declaration contains multiple "
395 OS <<
"Verifying .debug_abbrev...\n";
398 unsigned NumErrors = 0;
404 return NumErrors == 0;
408 unsigned NumDebugInfoErrors = 0;
409 ReferenceMap CrossUnitReferences;
412 for (
const auto &Unit : Units) {
413 OS <<
"Verifying unit: " <<
Index <<
" / " << Units.getNumUnits();
414 if (
const char*
Name = Unit->getUnitDIE(
true).getShortName())
415 OS <<
", \"" <<
Name <<
'\"';
418 ReferenceMap UnitLocalReferences;
419 NumDebugInfoErrors +=
420 verifyUnitContents(*Unit, UnitLocalReferences, CrossUnitReferences);
421 NumDebugInfoErrors += verifyDebugInfoReferences(
422 UnitLocalReferences, [&](
uint64_t Offset) {
return Unit.get(); });
426 NumDebugInfoErrors += verifyDebugInfoReferences(
433 return NumDebugInfoErrors;
436unsigned DWARFVerifier::verifyUnitSection(
const DWARFSection &S) {
439 unsigned NumDebugInfoErrors = 0;
442 bool isUnitDWARF64 =
false;
443 bool isHeaderChainValid =
true;
450 ReferenceMap CrossUnitReferences;
454 isHeaderChainValid =
false;
461 if (UnitIdx == 0 && !hasDIE) {
462 warn() <<
"Section is empty.\n";
463 isHeaderChainValid =
true;
465 if (!isHeaderChainValid)
466 ++NumDebugInfoErrors;
467 return NumDebugInfoErrors;
473 if (IndexStr.
empty())
475 OS <<
"Verifying " <<
Name <<
"...\n";
481 MapType::Allocator
Alloc;
482 std::vector<std::unique_ptr<MapType>> Sections(
Index.getColumnKinds().size());
485 if (!
E.getContributions())
488 InfoColumnKind == DW_SECT_INFO
493 if (
SC.getLength() == 0)
496 Sections[Col] = std::make_unique<MapType>(
Alloc);
497 auto &
M = *Sections[Col];
498 auto I =
M.find(
SC.getOffset());
499 if (
I !=
M.end() &&
I.start() < (
SC.getOffset() +
SC.getLength())) {
500 StringRef Category = InfoColumnKind == DWARFSectionKind::DW_SECT_INFO
501 ?
"Overlapping CU index entries"
502 :
"Overlapping TU index entries";
503 ErrorCategory.
Report(Category, [&]() {
505 "overlapping index entries for entries {0:x16} "
506 "and {1:x16} for column {2}\n",
511 M.insert(
SC.getOffset(),
SC.getOffset() +
SC.getLength() - 1, Sig);
519 return verifyIndex(
".debug_cu_index", DWARFSectionKind::DW_SECT_INFO,
530 unsigned NumErrors = 0;
532 OS <<
"Verifying .debug_info Unit Header Chain...\n";
534 NumErrors += verifyUnitSection(S);
537 OS <<
"Verifying .debug_types Unit Header Chain...\n";
539 NumErrors += verifyUnitSection(S);
542 OS <<
"Verifying non-dwo Units...\n";
545 OS <<
"Verifying dwo Units...\n";
547 return NumErrors == 0;
550unsigned DWARFVerifier::verifyDieRanges(
const DWARFDie &Die,
551 DieRangeInfo &ParentRI) {
552 unsigned NumErrors = 0;
560 if (!RangesOrError) {
562 if (!Unit->isDWOUnit())
571 DieRangeInfo RI(Die);
592 if (!IsObjectFile || IsMachOObject || Die.
getTag() != DW_TAG_compile_unit) {
593 bool DumpDieAfterError =
false;
594 for (
const auto &
Range : Ranges) {
595 if (!
Range.valid()) {
597 ErrorCategory.
Report(
"Invalid address range", [&]() {
598 error() <<
"Invalid address range " <<
Range <<
"\n";
599 DumpDieAfterError =
true;
610 if (
auto PrevRange = RI.insert(
Range)) {
612 ErrorCategory.
Report(
"DIE has overlapping DW_AT_ranges", [&]() {
613 error() <<
"DIE has overlapping ranges in DW_AT_ranges attribute: "
614 << *PrevRange <<
" and " <<
Range <<
'\n';
615 DumpDieAfterError =
true;
619 if (DumpDieAfterError)
620 dump(Die, 2) <<
'\n';
624 const auto IntersectingChild = ParentRI.insert(RI);
625 if (IntersectingChild != ParentRI.Children.end()) {
627 ErrorCategory.
Report(
"DIEs have overlapping address ranges", [&]() {
628 error() <<
"DIEs have overlapping address ranges:";
630 dump(IntersectingChild->Die) <<
'\n';
635 bool ShouldBeContained = !RI.Ranges.empty() && !ParentRI.Ranges.empty() &&
636 !(Die.
getTag() == DW_TAG_subprogram &&
637 ParentRI.Die.getTag() == DW_TAG_subprogram);
638 if (ShouldBeContained && !ParentRI.contains(RI)) {
641 "DIE address ranges are not contained by parent ranges", [&]() {
643 <<
"DIE address ranges are not contained in its parent's ranges:";
645 dump(Die, 2) <<
'\n';
651 NumErrors += verifyDieRanges(Child, RI);
656unsigned DWARFVerifier::verifyDebugInfoAttribute(
const DWARFDie &Die,
658 unsigned NumErrors = 0;
659 auto ReportError = [&](
StringRef category,
const Twine &TitleMsg) {
661 ErrorCategory.
Report(category, [&]() {
662 error() << TitleMsg <<
'\n';
669 const auto Attr = AttrValue.
Attr;
674 unsigned DwarfVersion =
U->getVersion();
678 if (
U->isDWOUnit() && RangeSection.
Data.
empty())
680 if (*SectionOffset >= RangeSection.
Data.
size())
681 ReportError(
"DW_AT_ranges offset out of bounds",
682 "DW_AT_ranges offset is beyond " +
683 StringRef(DwarfVersion < 5 ?
".debug_ranges"
684 :
".debug_rnglists") +
688 ReportError(
"Invalid DW_AT_ranges encoding",
689 "DIE has invalid DW_AT_ranges encoding:");
691 case DW_AT_stmt_list:
694 if (*SectionOffset >=
U->getLineSection().Data.size())
695 ReportError(
"DW_AT_stmt_list offset out of bounds",
696 "DW_AT_stmt_list offset is beyond .debug_line bounds: " +
700 ReportError(
"Invalid DW_AT_stmt_list encoding",
701 "DIE has invalid DW_AT_stmt_list encoding:");
703 case DW_AT_location: {
714 if (
Expected<std::vector<DWARFLocationExpression>> Loc =
716 for (
const auto &Entry : *Loc) {
719 U->getFormParams().Format);
725 ReportError(
"Invalid DWARF expressions",
726 "DIE contains invalid DWARF expression:");
729 Loc.takeError(), [&](std::unique_ptr<ResolverError>
E) {
730 return U->isDWOUnit() ? Error::success()
731 : Error(std::move(E));
733 ReportError(
"Invalid DW_AT_location",
toString(std::move(Err)));
736 case DW_AT_specification:
737 case DW_AT_abstract_origin: {
739 auto DieTag = Die.
getTag();
740 auto RefTag = ReferencedDie.getTag();
741 if (DieTag == RefTag)
743 if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
745 if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
748 if (DieTag == DW_TAG_GNU_call_site && RefTag == DW_TAG_subprogram)
750 ReportError(
"Incompatible DW_AT_abstract_origin tag reference",
751 "DIE with tag " +
TagString(DieTag) +
" has " +
753 " that points to DIE with "
754 "incompatible tag " +
762 ReportError(
"Incompatible DW_AT_type attribute tag",
768 case DW_AT_call_file:
769 case DW_AT_decl_file: {
771 if (
U->isDWOUnit() && !
U->isTypeUnit())
773 const auto *
LT =
U->getContext().getLineTableForUnit(U);
775 if (!
LT->hasFileAtIndex(*FileIdx)) {
776 bool IsZeroIndexed =
LT->Prologue.getVersion() >= 5;
777 if (std::optional<uint64_t> LastFileIdx =
778 LT->getLastValidFileIndex()) {
779 ReportError(
"Invalid file index in DW_AT_decl_file",
781 " with an invalid file index " +
783 " (valid values are [" +
784 (IsZeroIndexed ?
"0-" :
"1-") +
787 ReportError(
"Invalid file index in DW_AT_decl_file",
789 " with an invalid file index " +
791 " (the file table in the prologue is empty)");
796 "File index in DW_AT_decl_file reference CU with no line table",
798 " that references a file with index " +
800 " and the compile unit has no line table");
803 ReportError(
"Invalid encoding in DW_AT_decl_file",
805 " with invalid encoding");
809 case DW_AT_call_line:
810 case DW_AT_decl_line: {
813 Attr == DW_AT_call_line ?
"Invalid file index in DW_AT_decl_line"
814 :
"Invalid file index in DW_AT_call_line",
825unsigned DWARFVerifier::verifyDebugInfoForm(
const DWARFDie &Die,
827 ReferenceMap &LocalReferences,
828 ReferenceMap &CrossUnitReferences) {
830 unsigned NumErrors = 0;
837 case DW_FORM_ref_udata: {
842 auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
844 if (CUOffset >= CUSize) {
846 ErrorCategory.
Report(
"Invalid CU offset", [&]() {
848 <<
format(
"0x%08" PRIx64, CUOffset)
849 <<
" is invalid (must be less than CU size of "
850 <<
format(
"0x%08" PRIx64, CUSize) <<
"):\n";
851 Die.
dump(
OS, 0, DumpOpts);
863 case DW_FORM_ref_addr: {
869 if (*RefVal >= DieCU->getInfoSection().Data.size()) {
871 ErrorCategory.
Report(
"DW_FORM_ref_addr offset out of bounds", [&]() {
872 error() <<
"DW_FORM_ref_addr offset beyond .debug_info "
879 CrossUnitReferences[*RefVal].insert(Die.
getOffset());
890 case DW_FORM_line_strp: {
893 std::string ErrMsg =
toString(std::move(
E));
894 ErrorCategory.
Report(
"Invalid DW_FORM attribute", [&]() {
895 error() << ErrMsg <<
":\n";
907unsigned DWARFVerifier::verifyDebugInfoReferences(
908 const ReferenceMap &References,
912 return U->getDIEForOffset(
Offset);
915 unsigned NumErrors = 0;
916 for (
const std::pair<
const uint64_t, std::set<uint64_t>> &Pair :
918 if (GetDIEForOffset(Pair.first))
921 ErrorCategory.
Report(
"Invalid DIE reference", [&]() {
922 error() <<
"invalid DIE reference " <<
format(
"0x%08" PRIx64, Pair.first)
923 <<
". Offset is in between DIEs:\n";
924 for (
auto Offset : Pair.second)
932void DWARFVerifier::verifyDebugLineStmtOffsets() {
933 std::map<uint64_t, DWARFDie> StmtListToDie;
935 auto Die =
CU->getUnitDIE();
940 if (!StmtSectionOffset)
942 const uint64_t LineTableOffset = *StmtSectionOffset;
946 ++NumDebugLineErrors;
947 ErrorCategory.
Report(
"Unparsable .debug_line entry", [&]() {
948 error() <<
".debug_line[" <<
format(
"0x%08" PRIx64, LineTableOffset)
949 <<
"] was not able to be parsed for CU:\n";
956 assert(LineTable ==
nullptr);
961 auto Iter = StmtListToDie.find(LineTableOffset);
962 if (Iter != StmtListToDie.end()) {
963 ++NumDebugLineErrors;
964 ErrorCategory.
Report(
"Identical DW_AT_stmt_list section offset", [&]() {
965 error() <<
"two compile unit DIEs, "
966 <<
format(
"0x%08" PRIx64, Iter->second.getOffset()) <<
" and "
968 <<
", have the same DW_AT_stmt_list section offset:\n";
975 StmtListToDie[LineTableOffset] = Die;
979void DWARFVerifier::verifyDebugLineRows() {
981 auto Die =
CU->getUnitDIE();
990 uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
991 uint32_t MinFileIndex = isDWARF5 ? 0 : 1;
994 for (
const auto &FileName : LineTable->Prologue.FileNames) {
996 if (FileName.DirIdx > MaxDirIndex) {
997 ++NumDebugLineErrors;
999 "Invalid index in .debug_line->prologue.file_names->dir_idx",
1001 error() <<
".debug_line["
1002 <<
format(
"0x%08" PRIx64,
1004 <<
"].prologue.file_names[" << FileIndex
1005 <<
"].dir_idx contains an invalid index: "
1006 << FileName.DirIdx <<
"\n";
1011 std::string FullPath;
1012 const bool HasFullPath = LineTable->getFileNameByIndex(
1013 FileIndex,
CU->getCompilationDir(),
1014 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FullPath);
1015 assert(HasFullPath &&
"Invalid index?");
1017 auto It = FullPathMap.
find(FullPath);
1018 if (It == FullPathMap.
end())
1019 FullPathMap[FullPath] = FileIndex;
1020 else if (It->second != FileIndex && DumpOpts.
Verbose) {
1021 warn() <<
".debug_line["
1022 <<
format(
"0x%08" PRIx64,
1024 <<
"].prologue.file_names[" << FileIndex
1025 <<
"] is a duplicate of file_names[" << It->second <<
"]\n";
1033 if (LineTable->Rows.size() == 1 && LineTable->Rows.front().EndSequence)
1039 for (
const auto &Row : LineTable->Rows) {
1041 if (Row.Address.Address < PrevAddress) {
1042 ++NumDebugLineErrors;
1044 "decreasing address between debug_line rows", [&]() {
1045 error() <<
".debug_line["
1046 <<
format(
"0x%08" PRIx64,
1048 <<
"] row[" << RowIndex
1049 <<
"] decreases in address from previous row:\n";
1053 LineTable->Rows[RowIndex - 1].dump(
OS);
1059 if (!LineTable->hasFileAtIndex(Row.File)) {
1060 ++NumDebugLineErrors;
1061 ErrorCategory.
Report(
"Invalid file index in debug_line", [&]() {
1062 error() <<
".debug_line["
1063 <<
format(
"0x%08" PRIx64,
1065 <<
"][" << RowIndex <<
"] has invalid file index " << Row.File
1066 <<
" (valid values are [" << MinFileIndex <<
','
1067 << LineTable->Prologue.FileNames.size()
1068 << (isDWARF5 ?
")" :
"]") <<
"):\n";
1074 if (Row.EndSequence)
1077 PrevAddress = Row.Address.Address;
1086 IsMachOObject(
false) {
1088 !this->DumpOpts.ShowAggregateErrors);
1090 IsObjectFile =
F->isRelocatableObject();
1091 IsMachOObject =
F->isMachO();
1096 NumDebugLineErrors = 0;
1097 OS <<
"Verifying .debug_line...\n";
1098 verifyDebugLineStmtOffsets();
1099 verifyDebugLineRows();
1100 return NumDebugLineErrors == 0;
1103unsigned DWARFVerifier::verifyAppleAccelTable(
const DWARFSection *AccelSection,
1106 unsigned NumErrors = 0;
1114 if (!AccelSectionData.isValidOffset(
AccelTable.getSizeHdr())) {
1115 ErrorCategory.
Report(
"Section is too small to fit a section header", [&]() {
1116 error() <<
"Section is too small to fit a section header.\n";
1123 std::string Msg =
toString(std::move(
E));
1124 ErrorCategory.
Report(
"Section is too small to fit a section header",
1125 [&]() {
error() << Msg <<
'\n'; });
1135 uint64_t HashesBase = BucketsOffset + NumBuckets * 4;
1136 uint64_t OffsetsBase = HashesBase + NumHashes * 4;
1137 for (
uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
1138 uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
1139 if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
1140 ErrorCategory.
Report(
"Invalid hash index", [&]() {
1141 error() <<
format(
"Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
1148 if (NumAtoms == 0) {
1149 ErrorCategory.
Report(
"No atoms", [&]() {
1150 error() <<
"No atoms: failed to read HashData.\n";
1155 ErrorCategory.
Report(
"Unsupported form", [&]() {
1156 error() <<
"Unsupported form: failed to read HashData.\n";
1161 for (
uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
1162 uint64_t HashOffset = HashesBase + 4 * HashIdx;
1163 uint64_t DataOffset = OffsetsBase + 4 * HashIdx;
1164 uint32_t Hash = AccelSectionData.getU32(&HashOffset);
1165 uint64_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
1166 if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
1168 ErrorCategory.
Report(
"Invalid HashData offset", [&]() {
1169 error() <<
format(
"Hash[%d] has invalid HashData offset: "
1170 "0x%08" PRIx64
".\n",
1171 HashIdx, HashDataOffset);
1181 while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
1182 const uint32_t NumHashDataObjects =
1183 AccelSectionData.getU32(&HashDataOffset);
1184 for (
uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
1190 NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
1191 StringOffset = StrpOffset;
1192 const char *
Name = StrData->
getCStr(&StringOffset);
1196 ErrorCategory.
Report(
"Invalid DIE offset", [&]() {
1198 "%s Bucket[%d] Hash[%d] = 0x%08x "
1199 "Str[%u] = 0x%08" PRIx64
" DIE[%d] = 0x%08" PRIx64
" "
1200 "is not a valid DIE offset for \"%s\".\n",
1201 SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
1208 if ((
Tag != dwarf::DW_TAG_null) && (Die.
getTag() !=
Tag)) {
1209 ErrorCategory.
Report(
"Mismatched Tag in accellerator table", [&]() {
1211 <<
" in accelerator table does not match Tag "
1213 << HashDataIdx <<
"].\n";
1229 const uint64_t NotIndexed = std::numeric_limits<uint64_t>::max();
1233 CUMap[
CU->getOffset()] = NotIndexed;
1235 unsigned NumErrors = 0;
1237 if (NI.getCUCount() == 0) {
1238 ErrorCategory.
Report(
"Name Index doesn't index any CU", [&]() {
1239 error() <<
formatv(
"Name Index @ {0:x} does not index any CU\n",
1240 NI.getUnitOffset());
1249 if (Iter == CUMap.
end()) {
1250 ErrorCategory.
Report(
"Name Index references non-existing CU", [&]() {
1252 "Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
1253 NI.getUnitOffset(),
Offset);
1259 if (Iter->second != NotIndexed) {
1260 ErrorCategory.
Report(
"Duplicate Name Index", [&]() {
1262 "Name Index @ {0:x} references a CU @ {1:x}, but "
1263 "this CU is already indexed by Name Index @ {2:x}\n",
1264 NI.getUnitOffset(),
Offset, Iter->second);
1268 Iter->second = NI.getUnitOffset();
1272 for (
const auto &KV : CUMap) {
1273 if (KV.second == NotIndexed)
1274 warn() <<
formatv(
"CU @ {0:x} not covered by any Name Index\n", KV.first);
1294 warn() <<
formatv(
"Name Index @ {0:x} does not contain a hash table.\n",
1301 std::vector<BucketInfo> BucketStarts;
1306 ErrorCategory.
Report(
"Name Index Bucket contains invalid value", [&]() {
1307 error() <<
formatv(
"Bucket {0} of Name Index @ {1:x} contains invalid "
1308 "value {2}. Valid range is [0, {3}].\n",
1316 BucketStarts.emplace_back(Bucket,
Index);
1336 for (
const BucketInfo &
B : BucketStarts) {
1343 if (
B.Index > NextUncovered) {
1344 ErrorCategory.
Report(
"Name table entries uncovered by hash table", [&]() {
1345 error() <<
formatv(
"Name Index @ {0:x}: Name table entries [{1}, {2}] "
1346 "are not covered by the hash table.\n",
1364 ErrorCategory.
Report(
"Name Index point to mismatched hash value", [&]() {
1366 "Name Index @ {0:x}: Bucket {1} is not empty but points to a "
1367 "mismatched hash value {2:x} (belonging to bucket {3}).\n",
1385 "String hash doesn't match Name Index hash", [&]() {
1387 "Name Index @ {0:x}: String ({1}) at index {2} "
1388 "hashes to {3:x}, but "
1389 "the Name Index hash is {4:x}\n",
1397 NextUncovered = std::max(NextUncovered,
Idx);
1402unsigned DWARFVerifier::verifyNameIndexAttribute(
1406 if (FormName.
empty()) {
1407 ErrorCategory.
Report(
"Unknown NameIndex Abbreviation", [&]() {
1408 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1409 "unknown form: {3}.\n",
1416 if (AttrEnc.
Index == DW_IDX_type_hash) {
1417 if (AttrEnc.
Form != dwarf::DW_FORM_data8) {
1418 ErrorCategory.
Report(
"Unexpected NameIndex Abbreviation", [&]() {
1420 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
1421 "uses an unexpected form {2} (should be {3}).\n",
1429 if (AttrEnc.
Index == dwarf::DW_IDX_parent) {
1430 constexpr static auto AllowedForms = {dwarf::Form::DW_FORM_flag_present,
1431 dwarf::Form::DW_FORM_ref4};
1433 ErrorCategory.
Report(
"Unexpected NameIndex Abbreviation", [&]() {
1435 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_parent "
1436 "uses an unexpected form {2} (should be "
1437 "DW_FORM_ref4 or DW_FORM_flag_present).\n",
1448 struct FormClassTable {
1453 static constexpr FormClassTable Table[] = {
1461 return T.Index == AttrEnc.
Index;
1464 warn() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} contains an "
1465 "unknown index attribute: {2}.\n",
1471 ErrorCategory.
Report(
"Unexpected NameIndex Abbreviation", [&]() {
1472 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1473 "unexpected form {3} (expected form class {4}).\n",
1475 AttrEnc.
Form, Iter->ClassName);
1485 warn() <<
formatv(
"Name Index @ {0:x}: Verifying indexes of foreign type "
1486 "units is not currently supported.\n",
1491 unsigned NumErrors = 0;
1494 if (TagName.
empty()) {
1495 warn() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} references an "
1496 "unknown tag: {2}.\n",
1500 for (
const auto &AttrEnc : Abbrev.Attributes) {
1503 "NameIndex Abbreviateion contains multiple attributes", [&]() {
1505 "NameIndex @ {0:x}: Abbreviation {1:x} contains "
1506 "multiple {2} attributes.\n",
1512 NumErrors += verifyNameIndexAttribute(NI, Abbrev, AttrEnc);
1516 !
Attributes.count(dwarf::DW_IDX_type_unit)) {
1517 ErrorCategory.
Report(
"Abbreviation contains no attribute", [&]() {
1518 error() <<
formatv(
"NameIndex @ {0:x}: Indexing multiple compile units "
1519 "and abbreviation {1:x} has no DW_IDX_compile_unit "
1520 "or DW_IDX_type_unit attribute.\n",
1522 dwarf::DW_IDX_compile_unit);
1526 if (!
Attributes.count(dwarf::DW_IDX_die_offset)) {
1527 ErrorCategory.
Report(
"Abbreviate in NameIndex missing attribute", [&]() {
1529 "NameIndex @ {0:x}: Abbreviation {1:x} has no {2} attribute.\n",
1539 bool IncludeStrippedTemplateNames,
1540 bool IncludeObjCNames =
true,
1541 bool IncludeLinkageName =
true) {
1543 if (
const char *Str =
DIE.getShortName()) {
1545 Result.emplace_back(
Name);
1546 if (IncludeStrippedTemplateNames) {
1547 if (std::optional<StringRef> StrippedName =
1551 Result.push_back(StrippedName->str());
1554 if (IncludeObjCNames) {
1555 if (std::optional<ObjCSelectorNames> ObjCNames =
1557 Result.emplace_back(ObjCNames->ClassName);
1558 Result.emplace_back(ObjCNames->Selector);
1559 if (ObjCNames->ClassNameNoCategory)
1560 Result.emplace_back(*ObjCNames->ClassNameNoCategory);
1561 if (ObjCNames->MethodNameNoCategory)
1562 Result.push_back(std::move(*ObjCNames->MethodNameNoCategory));
1565 }
else if (
DIE.
getTag() == dwarf::DW_TAG_namespace)
1566 Result.emplace_back(
"(anonymous namespace)");
1568 if (IncludeLinkageName) {
1569 if (
const char *Str =
DIE.getLinkageName())
1570 Result.emplace_back(Str);
1576unsigned DWARFVerifier::verifyNameIndexEntries(
1585 ErrorCategory.
Report(
"Unable to get string associated with name", [&]() {
1586 error() <<
formatv(
"Name Index @ {0:x}: Unable to get string associated "
1594 unsigned NumErrors = 0;
1599 for (; EntryOr; ++
NumEntries, EntryID = NextEntryID,
1600 EntryOr = NI.
getEntry(&NextEntryID)) {
1602 std::optional<uint64_t> CUIndex = EntryOr->getCUIndex();
1603 std::optional<uint64_t> TUIndex = EntryOr->getLocalTUIndex();
1604 if (CUIndex && *CUIndex >= NI.
getCUCount()) {
1605 ErrorCategory.
Report(
"Name Index entry contains invalid CU index", [&]() {
1606 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1607 "invalid CU index ({2}).\n",
1614 ErrorCategory.
Report(
"Name Index entry contains invalid TU index", [&]() {
1615 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1616 "invalid TU index ({2}).\n",
1622 std::optional<uint64_t> UnitOffset;
1633 if (DU ==
nullptr || DU->
getOffset() != *UnitOffset) {
1637 "Name Index entry contains invalid CU or TU offset", [&]() {
1638 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1639 "invalid CU or TU offset {1:x}.\n",
1658 ErrorCategory.
Report(
"Unable to get load .dwo file", [&]() {
1659 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} unable to load "
1660 ".dwo file \"{2}\" for DWARF unit @ {3:x}.\n",
1663 {DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
1671 NonSkeletonUnit->
getOffset() + *EntryOr->getDIEUnitOffset();
1675 if (DIEOffset >= NextUnitOffset) {
1676 ErrorCategory.
Report(
"NameIndex relative DIE offset too large", [&]() {
1677 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} references a "
1678 "DIE @ {2:x} when CU or TU ends at {3:x}.\n",
1687 ErrorCategory.
Report(
"NameIndex references nonexistent DIE", [&]() {
1688 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} references a "
1689 "non-existing DIE @ {2:x}.\n",
1699 if (
DIE.getDwarfUnit() == DU &&
1701 ErrorCategory.
Report(
"Name index contains mismatched CU of DIE", [&]() {
1703 "Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "
1704 "DIE @ {2:x}: index - {3:x}; debug_info - {4:x}.\n",
1711 ErrorCategory.
Report(
"Name Index contains mismatched Tag of DIE", [&]() {
1713 "Name Index @ {0:x}: Entry @ {1:x}: mismatched Tag of "
1714 "DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1723 auto IncludeStrippedTemplateNames =
1725 DIE.
getTag() == DW_TAG_inlined_subroutine;
1726 auto EntryNames =
getNames(
DIE, IncludeStrippedTemplateNames);
1728 ErrorCategory.
Report(
"Name Index contains mismatched name of DIE", [&]() {
1729 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
1730 "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1732 make_range(EntryNames.begin(), EntryNames.end()));
1738 EntryOr.takeError(),
1742 ErrorCategory.Report(
1743 "NameIndex Name is not associated with any entries", [&]() {
1744 error() << formatv(
"Name Index @ {0:x}: Name {1} ({2}) is "
1745 "not associated with any entries.\n",
1746 NI.getUnitOffset(), NTE.getIndex(), Str);
1751 ErrorCategory.Report(
"Uncategorized NameIndex error", [&]() {
1752 error() <<
formatv(
"Name Index @ {0:x}: Name {1} ({2}): {3}\n",
1769 for (
const auto &Entry : *Loc) {
1771 U->getAddressByteSize());
1773 U->getFormParams().Format);
1774 bool IsInteresting =
1777 Op.
getCode() == DW_OP_form_tls_address ||
1778 Op.
getCode() == DW_OP_GNU_push_tls_address);
1786unsigned DWARFVerifier::verifyNameIndexCompleteness(
1794 if (Die.
find(DW_AT_declaration))
1804 auto IncludeLinkageName = Die.
getTag() == DW_TAG_subprogram ||
1805 Die.
getTag() == DW_TAG_inlined_subroutine;
1808 auto IncludeStrippedTemplateNames =
false;
1809 auto IncludeObjCNames =
false;
1810 auto EntryNames =
getNames(Die, IncludeStrippedTemplateNames,
1811 IncludeObjCNames, IncludeLinkageName);
1812 if (EntryNames.empty())
1822 case DW_TAG_compile_unit:
1828 case DW_TAG_formal_parameter:
1829 case DW_TAG_template_value_parameter:
1830 case DW_TAG_template_type_parameter:
1831 case DW_TAG_GNU_template_parameter_pack:
1832 case DW_TAG_GNU_template_template_param:
1842 case DW_TAG_enumerator:
1847 case DW_TAG_imported_declaration:
1853 case DW_TAG_subprogram:
1854 case DW_TAG_inlined_subroutine:
1857 {DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_entry_pc}))
1866 case DW_TAG_variable:
1877 unsigned NumErrors = 0;
1881 return E.getDIEUnitOffset() == DieUnitOffset;
1883 ErrorCategory.
Report(
"Name Index DIE entry missing name", [&]() {
1885 "Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
1886 "name {3} missing.\n",
1895unsigned DWARFVerifier::verifyDebugNames(
const DWARFSection &AccelSection,
1897 unsigned NumErrors = 0;
1902 OS <<
"Verifying .debug_names...\n";
1907 std::string Msg =
toString(std::move(E));
1908 ErrorCategory.
Report(
"Accelerator Table Error",
1909 [&]() { error() << Msg <<
'\n'; });
1913 NumErrors += verifyDebugNamesCULists(
AccelTable);
1915 NumErrors += verifyNameIndexBuckets(NI, StrData);
1917 NumErrors += verifyNameIndexAbbrevs(NI);
1924 NumErrors += verifyNameIndexEntries(NI, NTE);
1929 for (
const std::unique_ptr<DWARFUnit> &U : DCtx.
compile_units()) {
1932 auto *
CU = cast<DWARFCompileUnit>(
U.get());
1934 NumErrors += verifyNameIndexCompleteness(
DWARFDie(
CU, &Die), *NI);
1943 unsigned NumErrors = 0;
1944 if (!
D.getAppleNamesSection().Data.empty())
1945 NumErrors += verifyAppleAccelTable(&
D.getAppleNamesSection(), &StrData,
1947 if (!
D.getAppleTypesSection().Data.empty())
1948 NumErrors += verifyAppleAccelTable(&
D.getAppleTypesSection(), &StrData,
1950 if (!
D.getAppleNamespacesSection().Data.empty())
1951 NumErrors += verifyAppleAccelTable(&
D.getAppleNamespacesSection(), &StrData,
1952 ".apple_namespaces");
1953 if (!
D.getAppleObjCSection().Data.empty())
1954 NumErrors += verifyAppleAccelTable(&
D.getAppleObjCSection(), &StrData,
1957 if (!
D.getNamesSection().Data.empty())
1958 NumErrors += verifyDebugNames(
D.getNamesSection(), StrData);
1959 return NumErrors == 0;
1963 OS <<
"Verifying .debug_str_offsets...\n";
1972 std::optional<DwarfFormat> DwoLegacyDwarf4Format;
1974 if (DwoLegacyDwarf4Format)
1980 DwoLegacyDwarf4Format = InfoFormat;
1984 DwoLegacyDwarf4Format,
".debug_str_offsets.dwo",
1987 std::nullopt,
".debug_str_offsets",
2001 while (
C.seek(NextUnit),
C.tell() < DA.getData().size()) {
2007 Length = DA.getData().size();
2013 if (
C.tell() +
Length > DA.getData().size()) {
2015 "Section contribution length exceeds available space", [&]() {
2017 "{0}: contribution {1:X}: length exceeds available space "
2019 "offset ({1:X}) + length field space ({2:X}) + length "
2021 "{4:X} > section size {5:X})\n",
2023 C.tell() +
Length, DA.getData().size());
2032 ErrorCategory.
Report(
"Invalid Section version", [&]() {
2033 error() <<
formatv(
"{0}: contribution {1:X}: invalid version {2}\n",
2044 DA.setAddressSize(OffsetByteSize);
2046 if (Remainder != 0) {
2047 ErrorCategory.
Report(
"Invalid section contribution length", [&]() {
2049 "{0}: contribution {1:X}: invalid length ((length ({2:X}) "
2050 "- header (0x4)) % offset size {3:X} == {4:X} != 0)\n",
2061 if (StrData.
size() <= StrOff) {
2063 "String offset out of bounds of string section", [&]() {
2065 "{0}: contribution {1:X}: index {2:X}: invalid string "
2066 "offset *{3:X} == {4:X}, is beyond the bounds of the string "
2067 "section of length {5:X}\n",
2073 if (StrData[StrOff - 1] ==
'\0')
2076 "Section contribution contains invalid string offset", [&]() {
2078 "{0}: contribution {1:X}: index {2:X}: invalid string "
2079 "offset *{3:X} == {4:X}, is neither zero nor "
2080 "immediately following a null character\n",
2087 if (
Error E =
C.takeError()) {
2088 std::string Msg =
toString(std::move(E));
2089 ErrorCategory.
Report(
"String offset error", [&]() {
2098 StringRef s, std::function<
void(
void)> detailCallback) {
2099 Aggregation[std::string(s)]++;
2105 std::function<
void(
StringRef,
unsigned)> handleCounts) {
2106 for (
auto &&[
name,
count] : Aggregation) {
2113 error() <<
"Aggregated error counts:\n";
2115 error() << s <<
" occurred " <<
count <<
" time(s).\n";
2123 error() <<
"unable to open json summary file '"
2125 <<
"' for writing: " << EC.message() <<
'\n';
2135 ErrorCount += Count;
2138 RootNode.
try_emplace(
"error-categories", std::move(Categories));
2152 Die.
dump(OS, indent, DumpOpts);
ArrayRef< TableEntry > TableRef
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx)
static SmallVector< std::string, 3 > getNames(const DWARFDie &DIE, bool IncludeStrippedTemplateNames, bool IncludeObjCNames=true, bool IncludeLinkageName=true)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file contains constants used for implementing Dwarf debug support.
This file implements a coalescing interval map for small objects.
This file supports working with JSON data.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
A structured debug information entry.
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
dwarf::Tag getTag() const
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
static bool isSupportedVersion(unsigned version)
unsigned getNumCompileUnits()
Get the number of compile units in this context.
DWARFDie getDIEForOffset(uint64_t Offset)
Get a DIE given an exact offset.
const DWARFDebugAbbrev * getDebugAbbrevDWO()
Get a pointer to the parsed dwo abbreviations object.
compile_unit_range compile_units()
Get compile units in this context.
const DWARFDebugAbbrev * getDebugAbbrev()
Get a pointer to the parsed DebugAbbrev object.
bool isLittleEndian() const
const DWARFDebugLine::LineTable * getLineTableForUnit(DWARFUnit *U)
Get a pointer to a parsed line table corresponding to a compile unit.
DWARFUnit * getUnitForOffset(uint64_t Offset)
Return the DWARF unit that includes an offset (relative to .debug_info).
const DWARFUnitVector & getNormalUnitsVector()
static bool isAddressSizeSupported(unsigned AddressSize)
const DWARFUnitVector & getDWOUnitsVector()
const DWARFObject & getDWARFObj() const
Expected< const DWARFAbbreviationDeclarationSet * > getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const
DWARFDebugInfoEntry - A DIE with only the minimum required data.
DWARF v5-specific implementation of an Accelerator Entry.
Represents a single accelerator table within the DWARF v5 .debug_names section.
uint32_t getHashArrayEntry(uint32_t Index) const
Reads an entry in the Hash Array for the given Index.
uint64_t getLocalTUOffset(uint32_t TU) const
Reads offset of local type unit TU, TU is 0-based.
uint32_t getBucketArrayEntry(uint32_t Bucket) const
Reads an entry in the Bucket Array for the given Bucket.
uint64_t getUnitOffset() const
uint32_t getCUCount() const
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in this Name Index matching Key.
uint64_t getCUOffset(uint32_t CU) const
Reads offset of compilation unit CU. CU is 0-based.
Expected< Entry > getEntry(uint64_t *Offset) const
NameTableEntry getNameTableEntry(uint32_t Index) const
Reads an entry in the Name Table for the given Index.
uint32_t getNameCount() const
const DenseSet< Abbrev, AbbrevMapInfo > & getAbbrevs() const
uint32_t getForeignTUCount() const
uint32_t getBucketCount() const
uint32_t getLocalTUCount() const
A single entry in the Name Table (DWARF v5 sect.
uint64_t getEntryOffset() const
Returns the offset of the first Entry in the list.
const char * getString() const
Return the string referenced by this name table entry or nullptr if the string offset is not valid.
uint32_t getIndex() const
Return the index of this name in the parent Name Index.
Error returned by NameIndex::getEntry to report it has reached the end of the entry list.
.debug_names section consists of one or more units.
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
void getFullName(raw_string_ostream &, std::string *OriginalFullName=nullptr) const
uint64_t getOffset() const
Get the absolute offset into the debug info or types section.
Expected< DWARFAddressRangesVector > getAddressRanges() const
Get the address ranges for this DIE.
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as the referenced DIE.
DWARFDie getParent() const
Get the parent of this DIE object.
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
DWARFUnit * getDwarfUnit() const
bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
std::optional< DWARFFormValue > findRecursively(ArrayRef< dwarf::Attribute > Attrs) const
Extract the first value of any attribute in Attrs from this DIE and recurse into any DW_AT_specificat...
DWARFDie getFirstChild() const
Get the first child of this DIE object.
dwarf::Tag getTag() const
Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
iterator_range< attribute_iterator > attributes() const
Get an iterator range to all attributes in the current DIE only.
void dump(raw_ostream &OS, unsigned indent=0, DIDumpOptions DumpOpts=DIDumpOptions()) const
Dump the DIE and all of its attributes to the supplied stream.
This class represents an Operation in the Expression.
virtual StringRef getStrDWOSection() const
virtual StringRef getAbbrevDWOSection() const
virtual StringRef getAbbrevSection() const
virtual const DWARFSection & getStrOffsetsDWOSection() const
virtual void forEachInfoDWOSections(function_ref< void(const DWARFSection &)> F) const
virtual void forEachInfoSections(function_ref< void(const DWARFSection &)> F) const
virtual const DWARFSection & getRangesSection() const
virtual StringRef getTUIndexSection() const
virtual void forEachTypesSections(function_ref< void(const DWARFSection &)> F) const
virtual const DWARFSection & getStrOffsetsSection() const
virtual const DWARFSection & getLineSection() const
virtual const DWARFSection & getRnglistsSection() const
virtual StringRef getCUIndexSection() const
virtual StringRef getStrSection() const
virtual const object::ObjectFile * getFile() const
Describe a collection of units.
std::optional< uint64_t > getDWOId()
DWARFDie getNonSkeletonUnitDIE(bool ExtractUnitDIEOnly=true, StringRef DWOAlternativeLocation={})
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
DWARFDie getDIEForOffset(uint64_t Offset)
Return the DIE object for a given offset Offset inside the unit's DIE vector.
static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag)
uint64_t getNextUnitOffset() const
uint64_t getOffset() const
bool handleAccelTables()
Verify the information in accelerator tables, if they exist.
bool verifyDebugStrOffsets(std::optional< dwarf::DwarfFormat > LegacyFormat, StringRef SectionName, const DWARFSection &Section, StringRef StrData)
bool handleDebugTUIndex()
Verify the information in the .debug_tu_index section.
bool handleDebugStrOffsets()
Verify the information in the .debug_str_offsets[.dwo].
bool handleDebugCUIndex()
Verify the information in the .debug_cu_index section.
DWARFVerifier(raw_ostream &S, DWARFContext &D, DIDumpOptions DumpOpts=DIDumpOptions::getForSingleDIE())
bool handleDebugInfo()
Verify the information in the .debug_info and .debug_types sections.
bool handleDebugLine()
Verify the information in the .debug_line section.
void summarize()
Emits any aggregate information collected, depending on the dump options.
bool handleDebugAbbrev()
Verify the information in any of the following sections, if available: .debug_abbrev,...
iterator find(const_arg_type_t< KeyT > Val)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Base class for error info classes.
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
Class representing an expression and its matching format.
void ShowDetail(bool showDetail)
void Report(StringRef s, std::function< void()> detailCallback)
void EnumerateResults(std::function< void(StringRef, unsigned)> handleCounts)
size_t GetNumCategories() const
Implements a dense probed hash-table based set with some number of buckets stored inline.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
static raw_ostream & note()
Convenience method for printing "note: " to stderr.
An efficient, type-erasing, non-owning reference to a callable.
An Object is a JSON object, which maps strings to heterogenous JSON values.
std::pair< iterator, bool > try_emplace(const ObjectKey &K, Ts &&... Args)
A Value is an JSON value of unknown type.
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
StringRef AttributeString(unsigned Attribute)
StringRef FormEncodingString(unsigned Encoding)
StringRef UnitTypeString(unsigned)
StringRef TagString(unsigned Tag)
@ C
The default llvm calling convention, compatible with C.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
bool isUnitType(uint8_t UnitType)
UnitType
Constants for unit types in DWARF v5.
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
DWARFSectionKind
The enum of section identifiers to be used in internal interfaces.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
std::optional< StringRef > StripTemplateParameters(StringRef Name)
If Name is the name of a templated function that includes template parameters, returns a substring of...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
uint32_t caseFoldingDjbHash(StringRef Buffer, uint32_t H=5381)
Computes the Bernstein hash after folding the input according to the Dwarf 5 standard case folding ru...
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
std::optional< ObjCSelectorNames > getObjCNamesIfSelector(StringRef Name)
If Name is the AT_name of a DIE which refers to an Objective-C selector, returns an instance of ObjCS...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
Container for dump options that control which debug information will be dumped.
std::string JsonErrSummaryFile
Encapsulates a DWARF attribute value and all of the data required to describe the attribute value.
DWARFFormValue Value
The form and value for this attribute.
dwarf::Attribute Attr
The attribute enumeration of this attribute.
uint16_t getVersion() const
static void dumpTableHeader(raw_ostream &OS, unsigned Indent)
Abbreviation describing the encoding of Name Index entries.
uint32_t Code
< Abbreviation offset in the .debug_names section
Index attribute and its encoding.
A class that keeps the address range information for a single DIE.
std::vector< DWARFAddressRange > Ranges
Sorted DWARFAddressRanges.
bool contains(const DieRangeInfo &RHS) const
Return true if ranges in this object contains all ranges within RHS.
std::set< DieRangeInfo >::const_iterator die_range_info_iterator
bool intersects(const DieRangeInfo &RHS) const
Return true if any range in this object intersects with any range in RHS.
std::optional< DWARFAddressRange > insert(const DWARFAddressRange &R)
Inserts the address range.