39 using namespace dwarf;
48 auto Begin = Ranges.begin();
49 auto End = Ranges.end();
64 Ranges.insert(Pos,
R);
71 return Children.end();
73 auto End = Children.end();
74 auto Iter = Children.begin();
76 if (Iter->intersects(RI))
81 return Children.end();
85 auto I1 = Ranges.begin(), E1 = Ranges.end();
86 auto I2 =
RHS.Ranges.begin(), E2 =
RHS.Ranges.end();
92 bool Covered =
I1->LowPC <=
R.LowPC;
93 if (
R.LowPC ==
R.HighPC || (Covered &&
R.HighPC <=
I1->HighPC)) {
101 if (
R.LowPC <
I1->HighPC)
102 R.LowPC =
I1->HighPC;
109 auto I1 = Ranges.begin(), E1 = Ranges.end();
110 auto I2 =
RHS.Ranges.begin(), E2 =
RHS.Ranges.end();
111 while (
I1 != E1 && I2 != E2) {
112 if (
I1->intersects(*I2))
114 if (
I1->LowPC < I2->LowPC)
124 uint8_t &
UnitType,
bool &isUnitDWARF64) {
126 uint8_t AddrSize = 0;
130 bool ValidLength =
false;
131 bool ValidVersion =
false;
132 bool ValidAddrSize =
false;
133 bool ValidType =
true;
134 bool ValidAbbrevOffset =
true;
153 if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
154 ValidAbbrevOffset =
false;
156 ValidLength = DebugInfoData.
isValidOffset(OffsetStart + Length + 3);
159 if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
162 error() <<
format(
"Units[%d] - start offset: 0x%08" PRIx64
" \n", UnitIndex,
165 note() <<
"The length for this unit is too "
166 "large for the .debug_info provided.\n";
168 note() <<
"The 16 bit unit header version is not valid.\n";
170 note() <<
"The unit type encoding is not valid.\n";
171 if (!ValidAbbrevOffset)
172 note() <<
"The offset into the .debug_abbrev section is "
175 note() <<
"The address size is unsupported.\n";
177 *
Offset = OffsetStart + Length + (isUnitDWARF64 ? 12 : 4);
181 bool DWARFVerifier::verifyName(
const DWARFDie &Die) {
185 std::string ReconstructedName;
187 std::string OriginalFullName;
190 if (OriginalFullName.empty() || OriginalFullName == ReconstructedName)
193 error() <<
"Simplified template DW_AT_name could not be reconstituted:\n"
195 " reconstituted: {1}\n",
196 OriginalFullName, ReconstructedName);
202 unsigned DWARFVerifier::verifyUnitContents(
DWARFUnit &Unit,
203 ReferenceMap &UnitLocalReferences,
204 ReferenceMap &CrossUnitReferences) {
205 unsigned NumUnitErrors = 0;
206 unsigned NumDies = Unit.getNumDIEs();
207 for (
unsigned I = 0;
I < NumDies; ++
I) {
208 auto Die = Unit.getDIEAtIndex(
I);
210 if (Die.
getTag() == DW_TAG_null)
214 NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
215 NumUnitErrors += verifyDebugInfoForm(Die, AttrValue, UnitLocalReferences,
216 CrossUnitReferences);
219 NumUnitErrors += verifyName(Die);
225 <<
" has DW_CHILDREN_yes but DIE has no children: ";
230 NumUnitErrors += verifyDebugInfoCallSite(Die);
233 DWARFDie Die = Unit.getUnitDIE(
false);
235 error() <<
"Compilation unit without DIE.\n";
237 return NumUnitErrors;
241 error() <<
"Compilation unit root DIE is not a unit DIE: "
246 uint8_t
UnitType = Unit.getUnitType();
250 <<
") do not match.\n";
258 error() <<
"Skeleton compilation unit has children.\n";
263 NumUnitErrors += verifyDieRanges(Die, RI);
265 return NumUnitErrors;
268 unsigned DWARFVerifier::verifyDebugInfoCallSite(
const DWARFDie &Die) {
269 if (Die.
getTag() != DW_TAG_call_site && Die.
getTag() != DW_TAG_GNU_call_site)
274 if (Curr.
getTag() == DW_TAG_inlined_subroutine) {
275 error() <<
"Call site entry nested within inlined subroutine:";
282 error() <<
"Call site entry not nested within a valid subprogram:";
288 Curr.
find({DW_AT_call_all_calls, DW_AT_call_all_source_calls,
289 DW_AT_call_all_tail_calls, DW_AT_GNU_all_call_sites,
290 DW_AT_GNU_all_source_call_sites,
291 DW_AT_GNU_all_tail_call_sites});
293 error() <<
"Subprogram with call site entry has no DW_AT_call attribute:";
302 unsigned DWARFVerifier::verifyAbbrevSection(
const DWARFDebugAbbrev *Abbrev) {
303 unsigned NumErrors = 0;
307 for (
auto AbbrDecl : *AbbrDecls) {
309 for (
auto Attribute : AbbrDecl.attributes()) {
312 error() <<
"Abbreviation declaration contains multiple "
324 OS <<
"Verifying .debug_abbrev...\n";
327 unsigned NumErrors = 0;
329 NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev());
331 NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO());
333 return NumErrors == 0;
337 unsigned NumDebugInfoErrors = 0;
338 ReferenceMap CrossUnitReferences;
341 for (
const auto &Unit : Units) {
342 OS <<
"Verifying unit: " <<
Index <<
" / " << Units.getNumUnits();
343 if (
const char*
Name = Unit->getUnitDIE(
true).getShortName())
344 OS <<
", \"" <<
Name <<
'\"';
347 ReferenceMap UnitLocalReferences;
348 NumDebugInfoErrors +=
349 verifyUnitContents(*Unit, UnitLocalReferences, CrossUnitReferences);
350 NumDebugInfoErrors += verifyDebugInfoReferences(
351 UnitLocalReferences, [&](
uint64_t Offset) {
return Unit.get(); });
355 NumDebugInfoErrors += verifyDebugInfoReferences(
362 return NumDebugInfoErrors;
365 unsigned DWARFVerifier::verifyUnitSection(
const DWARFSection &
S) {
368 unsigned NumDebugInfoErrors = 0;
371 bool isUnitDWARF64 =
false;
372 bool isHeaderChainValid =
true;
379 ReferenceMap CrossUnitReferences;
383 isHeaderChainValid =
false;
390 if (UnitIdx == 0 && !hasDIE) {
391 warn() <<
"Section is empty.\n";
392 isHeaderChainValid =
true;
394 if (!isHeaderChainValid)
395 ++NumDebugInfoErrors;
396 return NumDebugInfoErrors;
402 if (IndexStr.
empty())
404 OS <<
"Verifying " <<
Name <<
"...\n";
411 std::vector<std::unique_ptr<MapType>> Sections(
Index.getColumnKinds().size());
414 if (!
E.getContributions())
416 for (
auto E :
enumerate(InfoColumnKind == DW_SECT_INFO
418 Index.getColumnKinds().size())
425 Sections[Col] = std::make_unique<MapType>(Alloc);
426 auto &
M = *Sections[Col];
427 auto I =
M.find(
SC.Offset);
428 if (
I !=
M.end() &&
I.start() < (
SC.Offset +
SC.Length)) {
430 "overlapping index entries for entries {0:x16} "
431 "and {1:x16} for column {2}\n",
435 M.insert(
SC.Offset,
SC.Offset +
SC.Length - 1, Sig);
443 return verifyIndex(
".debug_cu_index", DWARFSectionKind::DW_SECT_INFO,
444 DCtx.getDWARFObj().getCUIndexSection()) == 0;
449 DCtx.getDWARFObj().getTUIndexSection()) == 0;
454 unsigned NumErrors = 0;
456 OS <<
"Verifying .debug_info Unit Header Chain...\n";
458 NumErrors += verifyUnitSection(
S);
461 OS <<
"Verifying .debug_types Unit Header Chain...\n";
463 NumErrors += verifyUnitSection(
S);
466 OS <<
"Verifying non-dwo Units...\n";
467 NumErrors += verifyUnits(DCtx.getNormalUnitsVector());
469 OS <<
"Verifying dwo Units...\n";
470 NumErrors += verifyUnits(DCtx.getDWOUnitsVector());
471 return NumErrors == 0;
474 unsigned DWARFVerifier::verifyDieRanges(
const DWARFDie &Die,
475 DieRangeInfo &ParentRI) {
476 unsigned NumErrors = 0;
484 if (!RangesOrError) {
486 if (!Unit->isDWOUnit())
495 DieRangeInfo RI(Die);
516 if (!IsObjectFile || IsMachOObject || Die.
getTag() != DW_TAG_compile_unit) {
517 bool DumpDieAfterError =
false;
518 for (
const auto &Range : Ranges) {
519 if (!Range.valid()) {
521 error() <<
"Invalid address range " << Range <<
"\n";
522 DumpDieAfterError =
true;
532 if (
auto PrevRange = RI.insert(Range)) {
534 error() <<
"DIE has overlapping ranges in DW_AT_ranges attribute: "
535 << *PrevRange <<
" and " << Range <<
'\n';
536 DumpDieAfterError =
true;
539 if (DumpDieAfterError)
540 dump(Die, 2) <<
'\n';
544 const auto IntersectingChild = ParentRI.insert(RI);
545 if (IntersectingChild != ParentRI.Children.end()) {
547 error() <<
"DIEs have overlapping address ranges:";
549 dump(IntersectingChild->Die) <<
'\n';
553 bool ShouldBeContained = !RI.Ranges.empty() && !ParentRI.Ranges.empty() &&
554 !(Die.
getTag() == DW_TAG_subprogram &&
555 ParentRI.Die.getTag() == DW_TAG_subprogram);
556 if (ShouldBeContained && !ParentRI.contains(RI)) {
558 error() <<
"DIE address ranges are not contained in its parent's ranges:";
560 dump(Die, 2) <<
'\n';
565 NumErrors += verifyDieRanges(Child, RI);
570 unsigned DWARFVerifier::verifyDebugInfoAttribute(
const DWARFDie &Die,
572 unsigned NumErrors = 0;
573 auto ReportError = [&](
const Twine &TitleMsg) {
575 error() << TitleMsg <<
'\n';
581 const auto Attr = AttrValue.
Attr;
592 if (*SectionOffset >= RangeSection.
Data.
size())
594 "DW_AT_ranges offset is beyond " +
595 StringRef(DwarfVersion < 5 ?
".debug_ranges" :
".debug_rnglists") +
599 ReportError(
"DIE has invalid DW_AT_ranges encoding:");
601 case DW_AT_stmt_list:
605 ReportError(
"DW_AT_stmt_list offset is beyond .debug_line bounds: " +
609 ReportError(
"DIE has invalid DW_AT_stmt_list encoding:");
611 case DW_AT_location: {
622 if (
Expected<std::vector<DWARFLocationExpression>> Loc =
624 for (
const auto &Entry : *Loc) {
633 ReportError(
"DIE contains invalid DWARF expression:");
636 Loc.takeError(), [&](std::unique_ptr<ResolverError>
E) {
637 return U->isDWOUnit() ? Error::success()
638 : Error(std::move(E));
643 case DW_AT_specification:
644 case DW_AT_abstract_origin: {
646 auto DieTag = Die.
getTag();
647 auto RefTag = ReferencedDie.getTag();
648 if (DieTag == RefTag)
650 if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
652 if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
655 if (DieTag == DW_TAG_GNU_call_site && RefTag == DW_TAG_subprogram)
657 ReportError(
"DIE with tag " +
TagString(DieTag) +
" has " +
659 " that points to DIE with "
660 "incompatible tag " +
673 case DW_AT_call_file:
674 case DW_AT_decl_file: {
680 if (!
LT->hasFileAtIndex(*FileIdx)) {
681 bool IsZeroIndexed =
LT->Prologue.getVersion() >= 5;
684 " with an invalid file index " +
686 " (valid values are [" + (IsZeroIndexed ?
"0-" :
"1-") +
690 " with an invalid file index " +
692 " (the file table in the prologue is empty)");
697 " that references a file with index " +
699 " and the compile unit has no line table");
703 " with invalid encoding");
713 unsigned DWARFVerifier::verifyDebugInfoForm(
const DWARFDie &Die,
715 ReferenceMap &LocalReferences,
716 ReferenceMap &CrossUnitReferences) {
718 unsigned NumErrors = 0;
725 case DW_FORM_ref_udata: {
730 auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
732 if (CUOffset >= CUSize) {
735 <<
format(
"0x%08" PRIx64, CUOffset)
736 <<
" is invalid (must be less than CU size of "
737 <<
format(
"0x%08" PRIx64, CUSize) <<
"):\n";
738 Die.
dump(OS, 0, DumpOpts);
743 LocalReferences[*RefVal].insert(Die.
getOffset());
748 case DW_FORM_ref_addr: {
754 if (*RefVal >= DieCU->getInfoSection().Data.size()) {
756 error() <<
"DW_FORM_ref_addr offset beyond .debug_info "
762 CrossUnitReferences[*RefVal].insert(Die.
getOffset());
772 case DW_FORM_strx4: {
786 unsigned DWARFVerifier::verifyDebugInfoReferences(
787 const ReferenceMap &References,
794 unsigned NumErrors = 0;
795 for (
const std::pair<
const uint64_t, std::set<uint64_t>> &Pair :
797 if (GetDIEForOffset(Pair.first))
800 error() <<
"invalid DIE reference " <<
format(
"0x%08" PRIx64, Pair.first)
801 <<
". Offset is in between DIEs:\n";
802 for (
auto Offset : Pair.second)
809 void DWARFVerifier::verifyDebugLineStmtOffsets() {
810 std::map<uint64_t, DWARFDie> StmtListToDie;
811 for (
const auto &
CU : DCtx.compile_units()) {
812 auto Die =
CU->getUnitDIE();
817 if (!StmtSectionOffset)
819 const uint64_t LineTableOffset = *StmtSectionOffset;
820 auto LineTable = DCtx.getLineTableForUnit(
CU.get());
821 if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
823 ++NumDebugLineErrors;
824 error() <<
".debug_line[" <<
format(
"0x%08" PRIx64, LineTableOffset)
825 <<
"] was not able to be parsed for CU:\n";
831 assert(LineTable ==
nullptr);
836 auto Iter = StmtListToDie.find(LineTableOffset);
837 if (Iter != StmtListToDie.end()) {
838 ++NumDebugLineErrors;
839 error() <<
"two compile unit DIEs, "
840 <<
format(
"0x%08" PRIx64, Iter->second.getOffset()) <<
" and "
842 <<
", have the same DW_AT_stmt_list section offset:\n";
848 StmtListToDie[LineTableOffset] = Die;
852 void DWARFVerifier::verifyDebugLineRows() {
853 for (
const auto &
CU : DCtx.compile_units()) {
854 auto Die =
CU->getUnitDIE();
855 auto LineTable = DCtx.getLineTableForUnit(
CU.get());
862 uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
865 for (
const auto &FileName : LineTable->Prologue.FileNames) {
867 if (FileName.DirIdx > MaxDirIndex) {
868 ++NumDebugLineErrors;
869 error() <<
".debug_line["
872 <<
"].prologue.file_names[" << FileIndex
873 <<
"].dir_idx contains an invalid index: " << FileName.DirIdx
878 std::string FullPath;
879 const bool HasFullPath = LineTable->getFileNameByIndex(
880 FileIndex,
CU->getCompilationDir(),
882 assert(HasFullPath &&
"Invalid index?");
884 auto It = FullPathMap.
find(FullPath);
885 if (It == FullPathMap.
end())
886 FullPathMap[FullPath] = FileIndex;
887 else if (It->second != FileIndex) {
888 warn() <<
".debug_line["
891 <<
"].prologue.file_names[" << FileIndex
892 <<
"] is a duplicate of file_names[" << It->second <<
"]\n";
901 for (
const auto &Row : LineTable->Rows) {
903 if (Row.Address.Address < PrevAddress) {
904 ++NumDebugLineErrors;
905 error() <<
".debug_line["
908 <<
"] row[" << RowIndex
909 <<
"] decreases in address from previous row:\n";
913 LineTable->Rows[RowIndex - 1].dump(OS);
919 if (!LineTable->hasFileAtIndex(Row.File)) {
920 ++NumDebugLineErrors;
921 bool isDWARF5 = LineTable->Prologue.getVersion() >= 5;
922 error() <<
".debug_line["
925 <<
"][" << RowIndex <<
"] has invalid file index " << Row.File
926 <<
" (valid values are [" << (isDWARF5 ?
"0," :
"1,")
927 << LineTable->Prologue.FileNames.size()
928 << (isDWARF5 ?
")" :
"]") <<
"):\n";
936 PrevAddress = Row.Address.Address;
944 : OS(
S), DCtx(
D), DumpOpts(
std::
move(DumpOpts)), IsObjectFile(
false),
945 IsMachOObject(
false) {
947 IsObjectFile =
F->isRelocatableObject();
948 IsMachOObject =
F->isMachO();
953 NumDebugLineErrors = 0;
954 OS <<
"Verifying .debug_line...\n";
955 verifyDebugLineStmtOffsets();
956 verifyDebugLineRows();
957 return NumDebugLineErrors == 0;
960 unsigned DWARFVerifier::verifyAppleAccelTable(
const DWARFSection *AccelSection,
963 unsigned NumErrors = 0;
971 if (!AccelSectionData.isValidOffset(
AccelTable.getSizeHdr())) {
972 error() <<
"Section is too small to fit a section header.\n";
988 uint64_t HashesBase = BucketsOffset + NumBuckets * 4;
989 uint64_t OffsetsBase = HashesBase + NumHashes * 4;
990 for (
uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
991 uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
992 if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
993 error() <<
format(
"Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
1000 error() <<
"No atoms: failed to read HashData.\n";
1004 error() <<
"Unsupported form: failed to read HashData.\n";
1008 for (
uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
1009 uint64_t HashOffset = HashesBase + 4 * HashIdx;
1010 uint64_t DataOffset = OffsetsBase + 4 * HashIdx;
1011 uint32_t Hash = AccelSectionData.getU32(&HashOffset);
1012 uint64_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
1013 if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
1015 error() <<
format(
"Hash[%d] has invalid HashData offset: "
1016 "0x%08" PRIx64
".\n",
1017 HashIdx, HashDataOffset);
1026 while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
1027 const uint32_t NumHashDataObjects =
1028 AccelSectionData.getU32(&HashDataOffset);
1029 for (
uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
1035 NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
1036 StringOffset = StrpOffset;
1037 const char *
Name = StrData->
getCStr(&StringOffset);
1042 "%s Bucket[%d] Hash[%d] = 0x%08x "
1043 "Str[%u] = 0x%08" PRIx64
" DIE[%d] = 0x%08" PRIx64
" "
1044 "is not a valid DIE offset for \"%s\".\n",
1045 SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
1051 if ((
Tag != dwarf::DW_TAG_null) && (Die.
getTag() !=
Tag)) {
1053 <<
" in accelerator table does not match Tag "
1074 CUMap[
CU->getOffset()] = NotIndexed;
1076 unsigned NumErrors = 0;
1078 if (NI.getCUCount() == 0) {
1079 error() <<
formatv(
"Name Index @ {0:x} does not index any CU\n",
1080 NI.getUnitOffset());
1088 if (Iter == CUMap.
end()) {
1090 "Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
1091 NI.getUnitOffset(),
Offset);
1096 if (Iter->second != NotIndexed) {
1097 error() <<
formatv(
"Name Index @ {0:x} references a CU @ {1:x}, but "
1098 "this CU is already indexed by Name Index @ {2:x}\n",
1099 NI.getUnitOffset(),
Offset, Iter->second);
1102 Iter->second = NI.getUnitOffset();
1106 for (
const auto &KV : CUMap) {
1107 if (KV.second == NotIndexed)
1108 warn() <<
formatv(
"CU @ {0:x} not covered by any Name Index\n", KV.first);
1128 warn() <<
formatv(
"Name Index @ {0:x} does not contain a hash table.\n",
1135 std::vector<BucketInfo> BucketStarts;
1140 error() <<
formatv(
"Bucket {0} of Name Index @ {1:x} contains invalid "
1141 "value {2}. Valid range is [0, {3}].\n",
1147 BucketStarts.emplace_back(Bucket,
Index);
1167 for (
const BucketInfo &
B : BucketStarts) {
1174 if (
B.Index > NextUncovered) {
1175 error() <<
formatv(
"Name Index @ {0:x}: Name table entries [{1}, {2}] "
1176 "are not covered by the hash table.\n",
1194 "Name Index @ {0:x}: Bucket {1} is not empty but points to a "
1195 "mismatched hash value {2:x} (belonging to bucket {3}).\n",
1211 error() <<
formatv(
"Name Index @ {0:x}: String ({1}) at index {2} "
1212 "hashes to {3:x}, but "
1213 "the Name Index hash is {4:x}\n",
1221 NextUncovered =
std::max(NextUncovered, Idx);
1226 unsigned DWARFVerifier::verifyNameIndexAttribute(
1230 if (FormName.
empty()) {
1231 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1232 "unknown form: {3}.\n",
1238 if (AttrEnc.
Index == DW_IDX_type_hash) {
1239 if (AttrEnc.
Form != dwarf::DW_FORM_data8) {
1241 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
1242 "uses an unexpected form {2} (should be {3}).\n",
1251 struct FormClassTable {
1256 static constexpr FormClassTable Table[] = {
1265 return T.Index == AttrEnc.
Index;
1268 warn() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} contains an "
1269 "unknown index attribute: {2}.\n",
1275 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1276 "unexpected form {3} (expected form class {4}).\n",
1278 AttrEnc.
Form, Iter->ClassName);
1287 warn() <<
formatv(
"Name Index @ {0:x}: Verifying indexes of type units is "
1288 "not currently supported.\n",
1293 unsigned NumErrors = 0;
1296 if (TagName.
empty()) {
1297 warn() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} references an "
1298 "unknown tag: {2}.\n",
1302 for (
const auto &AttrEnc : Abbrev.Attributes) {
1304 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} contains "
1305 "multiple {2} attributes.\n",
1310 NumErrors += verifyNameIndexAttribute(NI, Abbrev, AttrEnc);
1314 error() <<
formatv(
"NameIndex @ {0:x}: Indexing multiple compile units "
1315 "and abbreviation {1:x} has no {2} attribute.\n",
1317 dwarf::DW_IDX_compile_unit);
1320 if (!
Attributes.count(dwarf::DW_IDX_die_offset)) {
1322 "NameIndex @ {0:x}: Abbreviation {1:x} has no {2} attribute.\n",
1331 bool IncludeLinkageName =
true) {
1333 if (
const char *Str =
DIE.getShortName())
1334 Result.emplace_back(Str);
1335 else if (
DIE.
getTag() == dwarf::DW_TAG_namespace)
1336 Result.emplace_back(
"(anonymous namespace)");
1338 if (IncludeLinkageName) {
1339 if (
const char *Str =
DIE.getLinkageName())
1340 Result.emplace_back(Str);
1346 unsigned DWARFVerifier::verifyNameIndexEntries(
1356 "Name Index @ {0:x}: Unable to get string associated with name {1}.\n",
1362 unsigned NumErrors = 0;
1363 unsigned NumEntries = 0;
1367 for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
1368 EntryOr = NI.
getEntry(&NextEntryID)) {
1369 uint32_t CUIndex = *EntryOr->getCUIndex();
1371 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1372 "invalid CU index ({2}).\n",
1378 uint64_t DIEOffset = CUOffset + *EntryOr->getDIEUnitOffset();
1381 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} references a "
1382 "non-existing DIE @ {2:x}.\n",
1388 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "
1389 "DIE @ {2:x}: index - {3:x}; debug_info - {4:x}.\n",
1395 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x}: mismatched Tag of "
1396 "DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1404 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
1405 "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1407 make_range(EntryNames.begin(), EntryNames.end()));
1415 error() << formatv(
"Name Index @ {0:x}: Name {1} ({2}) is "
1416 "not associated with any entries.\n",
1417 NI.getUnitOffset(), NTE.getIndex(), Str);
1422 << formatv(
"Name Index @ {0:x}: Name {1} ({2}): {3}\n",
1423 NI.getUnitOffset(), NTE.getIndex(), Str,
1438 for (
const auto &Entry : *Loc) {
1443 bool IsInteresting =
1445 return !
Op.isError() && (
Op.getCode() == DW_OP_addr ||
1446 Op.getCode() == DW_OP_form_tls_address ||
1447 Op.getCode() == DW_OP_GNU_push_tls_address);
1455 unsigned DWARFVerifier::verifyNameIndexCompleteness(
1463 if (Die.
find(DW_AT_declaration))
1473 auto IncludeLinkageName = Die.
getTag() == DW_TAG_subprogram ||
1474 Die.
getTag() == DW_TAG_inlined_subroutine;
1475 auto EntryNames =
getNames(Die, IncludeLinkageName);
1476 if (EntryNames.empty())
1486 case DW_TAG_compile_unit:
1492 case DW_TAG_formal_parameter:
1493 case DW_TAG_template_value_parameter:
1494 case DW_TAG_template_type_parameter:
1495 case DW_TAG_GNU_template_parameter_pack:
1496 case DW_TAG_GNU_template_template_param:
1506 case DW_TAG_enumerator:
1511 case DW_TAG_imported_declaration:
1517 case DW_TAG_subprogram:
1518 case DW_TAG_inlined_subroutine:
1521 {DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_entry_pc}))
1530 case DW_TAG_variable:
1541 unsigned NumErrors = 0;
1545 return E.getDIEUnitOffset() == DieUnitOffset;
1547 error() <<
formatv(
"Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
1548 "name {3} missing.\n",
1557 unsigned DWARFVerifier::verifyDebugNames(
const DWARFSection &AccelSection,
1559 unsigned NumErrors = 0;
1564 OS <<
"Verifying .debug_names...\n";
1573 NumErrors += verifyDebugNamesCULists(
AccelTable);
1575 NumErrors += verifyNameIndexBuckets(NI, StrData);
1577 NumErrors += verifyNameIndexAbbrevs(NI);
1584 NumErrors += verifyNameIndexEntries(NI, NTE);
1589 for (
const std::unique_ptr<DWARFUnit> &U : DCtx.
compile_units()) {
1592 auto *
CU = cast<DWARFCompileUnit>(U.get());
1594 NumErrors += verifyNameIndexCompleteness(
DWARFDie(
CU, &Die), *NI);
1603 unsigned NumErrors = 0;
1604 if (!
D.getAppleNamesSection().Data.empty())
1605 NumErrors += verifyAppleAccelTable(&
D.getAppleNamesSection(), &StrData,
1607 if (!
D.getAppleTypesSection().Data.empty())
1608 NumErrors += verifyAppleAccelTable(&
D.getAppleTypesSection(), &StrData,
1610 if (!
D.getAppleNamespacesSection().Data.empty())
1611 NumErrors += verifyAppleAccelTable(&
D.getAppleNamespacesSection(), &StrData,
1612 ".apple_namespaces");
1613 if (!
D.getAppleObjCSection().Data.empty())
1614 NumErrors += verifyAppleAccelTable(&
D.getAppleObjCSection(), &StrData,
1617 if (!
D.getNamesSection().Data.empty())
1618 NumErrors += verifyDebugNames(
D.getNamesSection(), StrData);
1619 return NumErrors == 0;
1629 Die.
dump(OS, indent, DumpOpts);