44using namespace object;
50std::optional<DWARFAddressRange>
52 auto Begin =
Ranges.begin();
54 auto Pos = std::lower_bound(Begin,
End, R);
57 if (Pos !=
End && *Pos == R) {
80 return Children.end();
82 auto End = Children.end();
83 auto Iter = Children.begin();
85 if (Iter->intersects(RI))
90 return Children.end();
94 auto I1 = Ranges.begin(), E1 = Ranges.end();
95 auto I2 =
RHS.Ranges.begin(), E2 =
RHS.Ranges.end();
101 bool Covered = I1->LowPC <= R.LowPC;
102 if (R.LowPC == R.HighPC || (Covered && R.HighPC <= I1->HighPC)) {
110 if (R.LowPC < I1->HighPC)
111 R.LowPC = I1->HighPC;
118 auto I1 = Ranges.begin(), E1 = Ranges.end();
119 auto I2 =
RHS.Ranges.begin(), E2 =
RHS.Ranges.end();
120 while (I1 != E1 && I2 != E2) {
121 if (I1->intersects(*I2)) {
126 if (I1->LowPC < I2->LowPC)
142 bool ValidLength =
false;
143 bool ValidVersion =
false;
144 bool ValidAddrSize =
false;
145 bool ValidType =
true;
146 bool ValidAbbrevOffset =
true;
167 if (!AbbrevSetOrErr) {
168 ValidAbbrevOffset =
false;
178 if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
181 bool HeaderShown =
false;
182 auto ShowHeaderOnce = [&]() {
184 error() <<
format(
"Units[%d] - start offset: 0x%08" PRIx64
" \n",
185 UnitIndex, OffsetStart);
191 "Unit Header Length: Unit too large for .debug_info provided", [&]() {
193 note() <<
"The length for this unit is too "
194 "large for the .debug_info provided.\n";
198 "Unit Header Length: 16 bit unit header version is not valid", [&]() {
200 note() <<
"The 16 bit unit header version is not valid.\n";
204 "Unit Header Length: Unit type encoding is not valid", [&]() {
206 note() <<
"The unit type encoding is not valid.\n";
208 if (!ValidAbbrevOffset)
210 "Unit Header Length: Offset into the .debug_abbrev section is not "
214 note() <<
"The offset into the .debug_abbrev section is "
218 ErrorCategory.
Report(
"Unit Header Length: Address size is unsupported",
221 note() <<
"The address size is unsupported.\n";
224 *
Offset = OffsetStart +
Length + (isUnitDWARF64 ? 12 : 4);
228bool DWARFVerifier::verifyName(
const DWARFDie &Die) {
232 std::string ReconstructedName;
234 std::string OriginalFullName;
237 if (OriginalFullName.empty() || OriginalFullName == ReconstructedName)
241 "Simplified template DW_AT_name could not be reconstituted", [&]() {
243 <<
"Simplified template DW_AT_name could not be reconstituted:\n"
245 " reconstituted: {1}\n",
246 OriginalFullName, ReconstructedName);
253unsigned DWARFVerifier::verifyUnitContents(
DWARFUnit &Unit,
254 ReferenceMap &UnitLocalReferences,
255 ReferenceMap &CrossUnitReferences) {
256 unsigned NumUnitErrors = 0;
257 unsigned NumDies = Unit.getNumDIEs();
258 for (
unsigned I = 0;
I < NumDies; ++
I) {
259 auto Die = Unit.getDIEAtIndex(
I);
261 if (Die.
getTag() == DW_TAG_null)
265 NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
266 NumUnitErrors += verifyDebugInfoForm(Die, AttrValue, UnitLocalReferences,
267 CrossUnitReferences);
270 NumUnitErrors += verifyName(Die);
276 <<
" has DW_CHILDREN_yes but DIE has no children: ";
281 NumUnitErrors += verifyDebugInfoCallSite(Die);
284 DWARFDie Die = Unit.getUnitDIE(
false);
286 ErrorCategory.
Report(
"Compilation unit missing DIE", [&]() {
287 error() <<
"Compilation unit without DIE.\n";
290 return NumUnitErrors;
294 ErrorCategory.
Report(
"Compilation unit root DIE is not a unit DIE", [&]() {
295 error() <<
"Compilation unit root DIE is not a unit DIE: "
303 ErrorCategory.
Report(
"Mismatched unit type", [&]() {
306 <<
") do not match.\n";
315 ErrorCategory.
Report(
"Skeleton CU has children", [&]() {
316 error() <<
"Skeleton compilation unit has children.\n";
322 NumUnitErrors += verifyDieRanges(Die, RI);
324 return NumUnitErrors;
327unsigned DWARFVerifier::verifyDebugInfoCallSite(
const DWARFDie &Die) {
328 if (Die.
getTag() != DW_TAG_call_site && Die.
getTag() != DW_TAG_GNU_call_site)
333 if (Curr.
getTag() == DW_TAG_inlined_subroutine) {
335 "Call site nested entry within inlined subroutine", [&]() {
336 error() <<
"Call site entry nested within inlined subroutine:";
345 "Call site entry not nested within valid subprogram", [&]() {
346 error() <<
"Call site entry not nested within a valid subprogram:";
352 std::optional<DWARFFormValue> CallAttr = Curr.
find(
353 {DW_AT_call_all_calls, DW_AT_call_all_source_calls,
354 DW_AT_call_all_tail_calls, DW_AT_GNU_all_call_sites,
355 DW_AT_GNU_all_source_call_sites, DW_AT_GNU_all_tail_call_sites});
358 "Subprogram with call site entry has no DW_AT_call attribute", [&]() {
360 <<
"Subprogram with call site entry has no DW_AT_call attribute:";
370unsigned DWARFVerifier::verifyAbbrevSection(
const DWARFDebugAbbrev *Abbrev) {
376 if (!AbbrDeclsOrErr) {
378 ErrorCategory.
Report(
"Abbreviation Declaration error",
379 [&]() {
error() << ErrMsg <<
"\n"; });
383 const auto *AbbrDecls = *AbbrDeclsOrErr;
384 unsigned NumErrors = 0;
385 for (
auto AbbrDecl : *AbbrDecls) {
387 for (
auto Attribute : AbbrDecl.attributes()) {
391 "Abbreviation declartion contains multiple attributes", [&]() {
392 error() <<
"Abbreviation declaration contains multiple "
404 OS <<
"Verifying .debug_abbrev...\n";
407 unsigned NumErrors = 0;
413 return NumErrors == 0;
417 unsigned NumDebugInfoErrors = 0;
418 ReferenceMap CrossUnitReferences;
421 for (
const auto &Unit : Units) {
422 OS <<
"Verifying unit: " <<
Index <<
" / " << Units.getNumUnits();
423 if (
const char*
Name = Unit->getUnitDIE(
true).getShortName())
424 OS <<
", \"" <<
Name <<
'\"';
427 ReferenceMap UnitLocalReferences;
428 NumDebugInfoErrors +=
429 verifyUnitContents(*Unit, UnitLocalReferences, CrossUnitReferences);
430 NumDebugInfoErrors += verifyDebugInfoReferences(
431 UnitLocalReferences, [&](
uint64_t Offset) {
return Unit.get(); });
435 NumDebugInfoErrors += verifyDebugInfoReferences(
442 return NumDebugInfoErrors;
445unsigned DWARFVerifier::verifyUnitSection(
const DWARFSection &S) {
448 unsigned NumDebugInfoErrors = 0;
451 bool isUnitDWARF64 =
false;
452 bool isHeaderChainValid =
true;
459 ReferenceMap CrossUnitReferences;
463 isHeaderChainValid =
false;
470 if (UnitIdx == 0 && !hasDIE) {
471 warn() <<
"Section is empty.\n";
472 isHeaderChainValid =
true;
474 if (!isHeaderChainValid)
475 ++NumDebugInfoErrors;
476 return NumDebugInfoErrors;
482 if (IndexStr.
empty())
484 OS <<
"Verifying " <<
Name <<
"...\n";
490 MapType::Allocator
Alloc;
491 std::vector<std::unique_ptr<MapType>> Sections(
Index.getColumnKinds().size());
494 if (!
E.getContributions())
497 InfoColumnKind == DW_SECT_INFO
502 if (
SC.getLength() == 0)
505 Sections[Col] = std::make_unique<MapType>(
Alloc);
506 auto &
M = *Sections[Col];
507 auto I =
M.find(
SC.getOffset());
508 if (
I !=
M.end() &&
I.start() < (
SC.getOffset() +
SC.getLength())) {
509 StringRef Category = InfoColumnKind == DWARFSectionKind::DW_SECT_INFO
510 ?
"Overlapping CU index entries"
511 :
"Overlapping TU index entries";
512 ErrorCategory.
Report(Category, [&]() {
514 "overlapping index entries for entries {0:x16} "
515 "and {1:x16} for column {2}\n",
520 M.insert(
SC.getOffset(),
SC.getOffset() +
SC.getLength() - 1, Sig);
528 return verifyIndex(
".debug_cu_index", DWARFSectionKind::DW_SECT_INFO,
539 unsigned NumErrors = 0;
541 OS <<
"Verifying .debug_info Unit Header Chain...\n";
543 NumErrors += verifyUnitSection(S);
546 OS <<
"Verifying .debug_types Unit Header Chain...\n";
548 NumErrors += verifyUnitSection(S);
551 OS <<
"Verifying non-dwo Units...\n";
554 OS <<
"Verifying dwo Units...\n";
556 return NumErrors == 0;
559unsigned DWARFVerifier::verifyDieRanges(
const DWARFDie &Die,
560 DieRangeInfo &ParentRI) {
561 unsigned NumErrors = 0;
569 if (!RangesOrError) {
571 if (!Unit->isDWOUnit())
580 DieRangeInfo RI(Die);
601 if (!IsObjectFile || IsMachOObject || Die.
getTag() != DW_TAG_compile_unit) {
602 bool DumpDieAfterError =
false;
603 for (
const auto &
Range : Ranges) {
604 if (!
Range.valid()) {
606 ErrorCategory.
Report(
"Invalid address range", [&]() {
607 error() <<
"Invalid address range " <<
Range <<
"\n";
608 DumpDieAfterError =
true;
619 if (
auto PrevRange = RI.insert(
Range)) {
621 ErrorCategory.
Report(
"DIE has overlapping DW_AT_ranges", [&]() {
622 error() <<
"DIE has overlapping ranges in DW_AT_ranges attribute: "
623 << *PrevRange <<
" and " <<
Range <<
'\n';
624 DumpDieAfterError =
true;
628 if (DumpDieAfterError)
629 dump(Die, 2) <<
'\n';
633 const auto IntersectingChild = ParentRI.insert(RI);
634 if (IntersectingChild != ParentRI.Children.end()) {
636 ErrorCategory.
Report(
"DIEs have overlapping address ranges", [&]() {
637 error() <<
"DIEs have overlapping address ranges:";
639 dump(IntersectingChild->Die) <<
'\n';
644 bool ShouldBeContained = !RI.Ranges.empty() && !ParentRI.Ranges.empty() &&
645 !(Die.
getTag() == DW_TAG_subprogram &&
646 ParentRI.Die.getTag() == DW_TAG_subprogram);
647 if (ShouldBeContained && !ParentRI.contains(RI)) {
650 "DIE address ranges are not contained by parent ranges", [&]() {
652 <<
"DIE address ranges are not contained in its parent's ranges:";
654 dump(Die, 2) <<
'\n';
660 NumErrors += verifyDieRanges(Child, RI);
665unsigned DWARFVerifier::verifyDebugInfoAttribute(
const DWARFDie &Die,
667 unsigned NumErrors = 0;
668 auto ReportError = [&](
StringRef category,
const Twine &TitleMsg) {
670 ErrorCategory.
Report(category, [&]() {
671 error() << TitleMsg <<
'\n';
678 const auto Attr = AttrValue.
Attr;
683 unsigned DwarfVersion =
U->getVersion();
687 if (
U->isDWOUnit() && RangeSection.
Data.
empty())
689 if (*SectionOffset >= RangeSection.
Data.
size())
690 ReportError(
"DW_AT_ranges offset out of bounds",
691 "DW_AT_ranges offset is beyond " +
692 StringRef(DwarfVersion < 5 ?
".debug_ranges"
693 :
".debug_rnglists") +
697 ReportError(
"Invalid DW_AT_ranges encoding",
698 "DIE has invalid DW_AT_ranges encoding:");
700 case DW_AT_stmt_list:
703 if (*SectionOffset >=
U->getLineSection().Data.size())
704 ReportError(
"DW_AT_stmt_list offset out of bounds",
705 "DW_AT_stmt_list offset is beyond .debug_line bounds: " +
709 ReportError(
"Invalid DW_AT_stmt_list encoding",
710 "DIE has invalid DW_AT_stmt_list encoding:");
712 case DW_AT_location: {
723 if (
Expected<std::vector<DWARFLocationExpression>> Loc =
725 for (
const auto &Entry : *Loc) {
728 U->getFormParams().Format);
734 ReportError(
"Invalid DWARF expressions",
735 "DIE contains invalid DWARF expression:");
738 Loc.takeError(), [&](std::unique_ptr<ResolverError>
E) {
739 return U->isDWOUnit() ? Error::success()
740 : Error(std::move(E));
742 ReportError(
"Invalid DW_AT_location",
toString(std::move(Err)));
745 case DW_AT_specification:
746 case DW_AT_abstract_origin: {
748 auto DieTag = Die.
getTag();
749 auto RefTag = ReferencedDie.getTag();
750 if (DieTag == RefTag)
752 if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
754 if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
757 if (DieTag == DW_TAG_GNU_call_site && RefTag == DW_TAG_subprogram)
759 ReportError(
"Incompatible DW_AT_abstract_origin tag reference",
760 "DIE with tag " +
TagString(DieTag) +
" has " +
762 " that points to DIE with "
763 "incompatible tag " +
771 ReportError(
"Incompatible DW_AT_type attribute tag",
777 case DW_AT_call_file:
778 case DW_AT_decl_file: {
780 if (
U->isDWOUnit() && !
U->isTypeUnit())
782 const auto *
LT =
U->getContext().getLineTableForUnit(U);
784 if (!
LT->hasFileAtIndex(*FileIdx)) {
785 bool IsZeroIndexed =
LT->Prologue.getVersion() >= 5;
786 if (std::optional<uint64_t> LastFileIdx =
787 LT->getLastValidFileIndex()) {
788 ReportError(
"Invalid file index in DW_AT_decl_file",
790 " with an invalid file index " +
792 " (valid values are [" +
793 (IsZeroIndexed ?
"0-" :
"1-") +
796 ReportError(
"Invalid file index in DW_AT_decl_file",
798 " with an invalid file index " +
800 " (the file table in the prologue is empty)");
805 "File index in DW_AT_decl_file reference CU with no line table",
807 " that references a file with index " +
809 " and the compile unit has no line table");
812 ReportError(
"Invalid encoding in DW_AT_decl_file",
814 " with invalid encoding");
818 case DW_AT_call_line:
819 case DW_AT_decl_line: {
822 Attr == DW_AT_call_line ?
"Invalid file index in DW_AT_decl_line"
823 :
"Invalid file index in DW_AT_call_line",
834unsigned DWARFVerifier::verifyDebugInfoForm(
const DWARFDie &Die,
836 ReferenceMap &LocalReferences,
837 ReferenceMap &CrossUnitReferences) {
839 unsigned NumErrors = 0;
846 case DW_FORM_ref_udata: {
851 auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
853 if (CUOffset >= CUSize) {
855 ErrorCategory.
Report(
"Invalid CU offset", [&]() {
857 <<
format(
"0x%08" PRIx64, CUOffset)
858 <<
" is invalid (must be less than CU size of "
859 <<
format(
"0x%08" PRIx64, CUSize) <<
"):\n";
860 Die.
dump(
OS, 0, DumpOpts);
872 case DW_FORM_ref_addr: {
878 if (*RefVal >= DieCU->getInfoSection().Data.size()) {
880 ErrorCategory.
Report(
"DW_FORM_ref_addr offset out of bounds", [&]() {
881 error() <<
"DW_FORM_ref_addr offset beyond .debug_info "
888 CrossUnitReferences[*RefVal].insert(Die.
getOffset());
899 case DW_FORM_line_strp: {
902 std::string ErrMsg =
toString(std::move(
E));
903 ErrorCategory.
Report(
"Invalid DW_FORM attribute", [&]() {
904 error() << ErrMsg <<
":\n";
916unsigned DWARFVerifier::verifyDebugInfoReferences(
917 const ReferenceMap &References,
921 return U->getDIEForOffset(
Offset);
924 unsigned NumErrors = 0;
925 for (
const std::pair<
const uint64_t, std::set<uint64_t>> &Pair :
927 if (GetDIEForOffset(Pair.first))
930 ErrorCategory.
Report(
"Invalid DIE reference", [&]() {
931 error() <<
"invalid DIE reference " <<
format(
"0x%08" PRIx64, Pair.first)
932 <<
". Offset is in between DIEs:\n";
933 for (
auto Offset : Pair.second)
941void DWARFVerifier::verifyDebugLineStmtOffsets() {
942 std::map<uint64_t, DWARFDie> StmtListToDie;
944 auto Die =
CU->getUnitDIE();
949 if (!StmtSectionOffset)
951 const uint64_t LineTableOffset = *StmtSectionOffset;
955 ++NumDebugLineErrors;
956 ErrorCategory.
Report(
"Unparsable .debug_line entry", [&]() {
957 error() <<
".debug_line[" <<
format(
"0x%08" PRIx64, LineTableOffset)
958 <<
"] was not able to be parsed for CU:\n";
965 assert(LineTable ==
nullptr);
970 auto Iter = StmtListToDie.find(LineTableOffset);
971 if (Iter != StmtListToDie.end()) {
972 ++NumDebugLineErrors;
973 ErrorCategory.
Report(
"Identical DW_AT_stmt_list section offset", [&]() {
974 error() <<
"two compile unit DIEs, "
975 <<
format(
"0x%08" PRIx64, Iter->second.getOffset()) <<
" and "
977 <<
", have the same DW_AT_stmt_list section offset:\n";
984 StmtListToDie[LineTableOffset] = Die;
988void DWARFVerifier::verifyDebugLineRows() {
990 auto Die =
CU->getUnitDIE();
999 uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
1000 uint32_t MinFileIndex = isDWARF5 ? 0 : 1;
1003 for (
const auto &FileName : LineTable->Prologue.FileNames) {
1005 if (FileName.DirIdx > MaxDirIndex) {
1006 ++NumDebugLineErrors;
1008 "Invalid index in .debug_line->prologue.file_names->dir_idx",
1010 error() <<
".debug_line["
1011 <<
format(
"0x%08" PRIx64,
1013 <<
"].prologue.file_names[" << FileIndex
1014 <<
"].dir_idx contains an invalid index: "
1015 << FileName.DirIdx <<
"\n";
1020 std::string FullPath;
1021 const bool HasFullPath = LineTable->getFileNameByIndex(
1022 FileIndex,
CU->getCompilationDir(),
1023 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FullPath);
1024 assert(HasFullPath &&
"Invalid index?");
1027 if (!Inserted && It->second != FileIndex && DumpOpts.
Verbose) {
1028 warn() <<
".debug_line["
1029 <<
format(
"0x%08" PRIx64,
1031 <<
"].prologue.file_names[" << FileIndex
1032 <<
"] is a duplicate of file_names[" << It->second <<
"]\n";
1040 if (LineTable->Rows.size() == 1 && LineTable->Rows.front().EndSequence)
1046 for (
const auto &Row : LineTable->Rows) {
1048 if (Row.Address.Address < PrevAddress) {
1049 ++NumDebugLineErrors;
1051 "decreasing address between debug_line rows", [&]() {
1052 error() <<
".debug_line["
1053 <<
format(
"0x%08" PRIx64,
1055 <<
"] row[" << RowIndex
1056 <<
"] decreases in address from previous row:\n";
1060 LineTable->Rows[RowIndex - 1].dump(
OS);
1066 if (!LineTable->hasFileAtIndex(Row.File)) {
1067 ++NumDebugLineErrors;
1068 ErrorCategory.
Report(
"Invalid file index in debug_line", [&]() {
1069 error() <<
".debug_line["
1070 <<
format(
"0x%08" PRIx64,
1072 <<
"][" << RowIndex <<
"] has invalid file index " << Row.File
1073 <<
" (valid values are [" << MinFileIndex <<
','
1074 << LineTable->Prologue.FileNames.size()
1075 << (isDWARF5 ?
")" :
"]") <<
"):\n";
1081 if (Row.EndSequence)
1084 PrevAddress = Row.Address.Address;
1093 IsMachOObject(
false) {
1095 !this->DumpOpts.ShowAggregateErrors);
1097 IsObjectFile =
F->isRelocatableObject();
1098 IsMachOObject =
F->isMachO();
1103 NumDebugLineErrors = 0;
1104 OS <<
"Verifying .debug_line...\n";
1105 verifyDebugLineStmtOffsets();
1106 verifyDebugLineRows();
1107 return NumDebugLineErrors == 0;
1110unsigned DWARFVerifier::verifyAppleAccelTable(
const DWARFSection *AccelSection,
1113 unsigned NumErrors = 0;
1121 if (!AccelSectionData.isValidOffset(
AccelTable.getSizeHdr())) {
1122 ErrorCategory.
Report(
"Section is too small to fit a section header", [&]() {
1123 error() <<
"Section is too small to fit a section header.\n";
1130 std::string Msg =
toString(std::move(
E));
1131 ErrorCategory.
Report(
"Section is too small to fit a section header",
1132 [&]() {
error() << Msg <<
'\n'; });
1142 uint64_t HashesBase = BucketsOffset + NumBuckets * 4;
1143 uint64_t OffsetsBase = HashesBase + NumHashes * 4;
1144 for (
uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
1145 uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
1146 if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
1147 ErrorCategory.
Report(
"Invalid hash index", [&]() {
1148 error() <<
format(
"Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
1155 if (NumAtoms == 0) {
1156 ErrorCategory.
Report(
"No atoms", [&]() {
1157 error() <<
"No atoms: failed to read HashData.\n";
1162 ErrorCategory.
Report(
"Unsupported form", [&]() {
1163 error() <<
"Unsupported form: failed to read HashData.\n";
1168 for (
uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
1169 uint64_t HashOffset = HashesBase + 4 * HashIdx;
1170 uint64_t DataOffset = OffsetsBase + 4 * HashIdx;
1171 uint32_t Hash = AccelSectionData.getU32(&HashOffset);
1172 uint64_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
1173 if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
1175 ErrorCategory.
Report(
"Invalid HashData offset", [&]() {
1176 error() <<
format(
"Hash[%d] has invalid HashData offset: "
1177 "0x%08" PRIx64
".\n",
1178 HashIdx, HashDataOffset);
1188 while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
1189 const uint32_t NumHashDataObjects =
1190 AccelSectionData.getU32(&HashDataOffset);
1191 for (
uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
1197 NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
1198 StringOffset = StrpOffset;
1199 const char *
Name = StrData->
getCStr(&StringOffset);
1203 ErrorCategory.
Report(
"Invalid DIE offset", [&]() {
1205 "%s Bucket[%d] Hash[%d] = 0x%08x "
1206 "Str[%u] = 0x%08" PRIx64
" DIE[%d] = 0x%08" PRIx64
" "
1207 "is not a valid DIE offset for \"%s\".\n",
1208 SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
1215 if ((
Tag != dwarf::DW_TAG_null) && (Die.
getTag() !=
Tag)) {
1216 ErrorCategory.
Report(
"Mismatched Tag in accellerator table", [&]() {
1218 <<
" in accelerator table does not match Tag "
1220 << HashDataIdx <<
"].\n";
1236 const uint64_t NotIndexed = std::numeric_limits<uint64_t>::max();
1240 CUMap[
CU->getOffset()] = NotIndexed;
1242 unsigned NumErrors = 0;
1244 if (NI.getCUCount() == 0) {
1245 ErrorCategory.
Report(
"Name Index doesn't index any CU", [&]() {
1246 error() <<
formatv(
"Name Index @ {0:x} does not index any CU\n",
1247 NI.getUnitOffset());
1256 if (Iter == CUMap.
end()) {
1257 ErrorCategory.
Report(
"Name Index references non-existing CU", [&]() {
1259 "Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
1260 NI.getUnitOffset(),
Offset);
1266 if (Iter->second != NotIndexed) {
1267 ErrorCategory.
Report(
"Duplicate Name Index", [&]() {
1269 "Name Index @ {0:x} references a CU @ {1:x}, but "
1270 "this CU is already indexed by Name Index @ {2:x}\n",
1271 NI.getUnitOffset(),
Offset, Iter->second);
1275 Iter->second = NI.getUnitOffset();
1279 for (
const auto &KV : CUMap) {
1280 if (KV.second == NotIndexed)
1281 warn() <<
formatv(
"CU @ {0:x} not covered by any Name Index\n", KV.first);
1301 warn() <<
formatv(
"Name Index @ {0:x} does not contain a hash table.\n",
1308 std::vector<BucketInfo> BucketStarts;
1313 ErrorCategory.
Report(
"Name Index Bucket contains invalid value", [&]() {
1314 error() <<
formatv(
"Bucket {0} of Name Index @ {1:x} contains invalid "
1315 "value {2}. Valid range is [0, {3}].\n",
1323 BucketStarts.emplace_back(Bucket,
Index);
1343 for (
const BucketInfo &
B : BucketStarts) {
1350 if (
B.Index > NextUncovered) {
1351 ErrorCategory.
Report(
"Name table entries uncovered by hash table", [&]() {
1352 error() <<
formatv(
"Name Index @ {0:x}: Name table entries [{1}, {2}] "
1353 "are not covered by the hash table.\n",
1371 ErrorCategory.
Report(
"Name Index point to mismatched hash value", [&]() {
1373 "Name Index @ {0:x}: Bucket {1} is not empty but points to a "
1374 "mismatched hash value {2:x} (belonging to bucket {3}).\n",
1392 "String hash doesn't match Name Index hash", [&]() {
1394 "Name Index @ {0:x}: String ({1}) at index {2} "
1395 "hashes to {3:x}, but "
1396 "the Name Index hash is {4:x}\n",
1404 NextUncovered = std::max(NextUncovered,
Idx);
1409unsigned DWARFVerifier::verifyNameIndexAttribute(
1413 if (FormName.
empty()) {
1414 ErrorCategory.
Report(
"Unknown NameIndex Abbreviation", [&]() {
1415 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1416 "unknown form: {3}.\n",
1423 if (AttrEnc.
Index == DW_IDX_type_hash) {
1424 if (AttrEnc.
Form != dwarf::DW_FORM_data8) {
1425 ErrorCategory.
Report(
"Unexpected NameIndex Abbreviation", [&]() {
1427 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
1428 "uses an unexpected form {2} (should be {3}).\n",
1436 if (AttrEnc.
Index == dwarf::DW_IDX_parent) {
1437 constexpr static auto AllowedForms = {dwarf::Form::DW_FORM_flag_present,
1438 dwarf::Form::DW_FORM_ref4};
1440 ErrorCategory.
Report(
"Unexpected NameIndex Abbreviation", [&]() {
1442 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_parent "
1443 "uses an unexpected form {2} (should be "
1444 "DW_FORM_ref4 or DW_FORM_flag_present).\n",
1455 struct FormClassTable {
1460 static constexpr FormClassTable Table[] = {
1468 return T.Index == AttrEnc.
Index;
1471 warn() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} contains an "
1472 "unknown index attribute: {2}.\n",
1478 ErrorCategory.
Report(
"Unexpected NameIndex Abbreviation", [&]() {
1479 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1480 "unexpected form {3} (expected form class {4}).\n",
1482 AttrEnc.
Form, Iter->ClassName);
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",
1525 if (!
Attributes.count(dwarf::DW_IDX_die_offset)) {
1526 ErrorCategory.
Report(
"Abbreviate in NameIndex missing attribute", [&]() {
1528 "NameIndex @ {0:x}: Abbreviation {1:x} has no {2} attribute.\n",
1538 bool IncludeStrippedTemplateNames,
1539 bool IncludeObjCNames =
true,
1540 bool IncludeLinkageName =
true) {
1542 if (
const char *Str =
DIE.getShortName()) {
1544 Result.emplace_back(
Name);
1545 if (IncludeStrippedTemplateNames) {
1546 if (std::optional<StringRef> StrippedName =
1550 Result.push_back(StrippedName->str());
1553 if (IncludeObjCNames) {
1554 if (std::optional<ObjCSelectorNames> ObjCNames =
1556 Result.emplace_back(ObjCNames->ClassName);
1557 Result.emplace_back(ObjCNames->Selector);
1558 if (ObjCNames->ClassNameNoCategory)
1559 Result.emplace_back(*ObjCNames->ClassNameNoCategory);
1560 if (ObjCNames->MethodNameNoCategory)
1561 Result.push_back(std::move(*ObjCNames->MethodNameNoCategory));
1564 }
else if (
DIE.
getTag() == dwarf::DW_TAG_namespace)
1565 Result.emplace_back(
"(anonymous namespace)");
1567 if (IncludeLinkageName) {
1568 if (
const char *Str =
DIE.getLinkageName())
1569 Result.emplace_back(Str);
1575unsigned DWARFVerifier::verifyNameIndexEntries(
1580 ErrorCategory.
Report(
"Unable to get string associated with name", [&]() {
1581 error() <<
formatv(
"Name Index @ {0:x}: Unable to get string associated "
1589 unsigned NumErrors = 0;
1594 for (; EntryOr; ++
NumEntries, EntryID = NextEntryID,
1595 EntryOr = NI.
getEntry(&NextEntryID)) {
1597 std::optional<uint64_t> CUIndex = EntryOr->getRelatedCUIndex();
1598 std::optional<uint64_t> TUIndex = EntryOr->getTUIndex();
1599 if (CUIndex && *CUIndex >= NI.
getCUCount()) {
1600 ErrorCategory.
Report(
"Name Index entry contains invalid CU index", [&]() {
1601 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1602 "invalid CU index ({2}).\n",
1610 if (TUIndex && *TUIndex >= (NumLocalTUs + NumForeignTUs)) {
1611 ErrorCategory.
Report(
"Name Index entry contains invalid TU index", [&]() {
1612 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1613 "invalid TU index ({2}).\n",
1619 std::optional<uint64_t> UnitOffset;
1622 if (*TUIndex >= NumLocalTUs) {
1636 "Name Index entry contains foreign TU index with invalid CU "
1640 "Name Index @ {0:x}: Entry @ {1:x} contains an "
1641 "foreign TU index ({2}) with no CU index.\n",
1651 }
else if (CUIndex) {
1657 if (!UnitOffset || UnitOffset == UINT32_MAX)
1663 if (DU ==
nullptr || DU->
getOffset() != *UnitOffset) {
1667 "Name Index entry contains invalid CU or TU offset", [&]() {
1668 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1669 "invalid CU or TU offset {2:x}.\n",
1688 if (DU->
getDWOId() && UnitDie == NonSkeletonUnitDie) {
1689 ErrorCategory.
Report(
"Unable to get load .dwo file", [&]() {
1691 "Name Index @ {0:x}: Entry @ {1:x} unable to load "
1692 ".dwo file \"{2}\" for DWARF unit @ {3:x}.\n",
1701 if (TUIndex && *TUIndex >= NumLocalTUs) {
1709 const uint32_t ForeignTUIdx = *TUIndex - NumLocalTUs;
1717 NonSkeletonUnitDie = NonSkeletonUnit->
getUnitDIE(
true);
1721 if (SkeletonDCtx.
isDWP()) {
1723 UnitDie.
find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1725 NonSkeletonUnitDie.
find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1726 if (DUDwoName != TUDwoName)
1733 NonSkeletonUnit->
getOffset() + *EntryOr->getDIEUnitOffset();
1737 if (DIEOffset >= NextUnitOffset) {
1738 ErrorCategory.
Report(
"NameIndex relative DIE offset too large", [&]() {
1739 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} references a "
1740 "DIE @ {2:x} when CU or TU ends at {3:x}.\n",
1749 ErrorCategory.
Report(
"NameIndex references nonexistent DIE", [&]() {
1750 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} references a "
1751 "non-existing DIE @ {2:x}.\n",
1761 if (
DIE.getDwarfUnit() == DU &&
1763 ErrorCategory.
Report(
"Name index contains mismatched CU of DIE", [&]() {
1765 "Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "
1766 "DIE @ {2:x}: index - {3:x}; debug_info - {4:x}.\n",
1773 ErrorCategory.
Report(
"Name Index contains mismatched Tag of DIE", [&]() {
1775 "Name Index @ {0:x}: Entry @ {1:x}: mismatched Tag of "
1776 "DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1785 auto IncludeStrippedTemplateNames =
1787 DIE.
getTag() == DW_TAG_inlined_subroutine;
1788 auto EntryNames =
getNames(
DIE, IncludeStrippedTemplateNames);
1790 ErrorCategory.
Report(
"Name Index contains mismatched name of DIE", [&]() {
1791 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
1792 "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1794 make_range(EntryNames.begin(), EntryNames.end()));
1800 EntryOr.takeError(),
1804 ErrorCategory.Report(
1805 "NameIndex Name is not associated with any entries", [&]() {
1806 error() << formatv(
"Name Index @ {0:x}: Name {1} ({2}) is "
1807 "not associated with any entries.\n",
1808 NI.getUnitOffset(), NTE.getIndex(), Str);
1813 ErrorCategory.Report(
"Uncategorized NameIndex error", [&]() {
1814 error() <<
formatv(
"Name Index @ {0:x}: Name {1} ({2}): {3}\n",
1831 for (
const auto &Entry : *Loc) {
1833 U->getAddressByteSize());
1835 U->getFormParams().Format);
1836 bool IsInteresting =
1839 Op.
getCode() == DW_OP_form_tls_address ||
1840 Op.
getCode() == DW_OP_GNU_push_tls_address);
1848unsigned DWARFVerifier::verifyNameIndexCompleteness(
1856 if (Die.
find(DW_AT_declaration))
1866 auto IncludeLinkageName = Die.
getTag() == DW_TAG_subprogram ||
1867 Die.
getTag() == DW_TAG_inlined_subroutine;
1870 auto IncludeStrippedTemplateNames =
false;
1871 auto IncludeObjCNames =
false;
1872 auto EntryNames =
getNames(Die, IncludeStrippedTemplateNames,
1873 IncludeObjCNames, IncludeLinkageName);
1874 if (EntryNames.empty())
1884 case DW_TAG_compile_unit:
1890 case DW_TAG_formal_parameter:
1891 case DW_TAG_template_value_parameter:
1892 case DW_TAG_template_type_parameter:
1893 case DW_TAG_GNU_template_parameter_pack:
1894 case DW_TAG_GNU_template_template_param:
1904 case DW_TAG_enumerator:
1909 case DW_TAG_imported_declaration:
1915 case DW_TAG_subprogram:
1916 case DW_TAG_inlined_subroutine:
1919 {DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_entry_pc}))
1928 case DW_TAG_variable:
1939 unsigned NumErrors = 0;
1943 return E.getDIEUnitOffset() == DieUnitOffset;
1945 ErrorCategory.
Report(
"Name Index DIE entry missing name", [&]() {
1947 "Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
1948 "name {3} missing.\n",
1957unsigned DWARFVerifier::verifyDebugNames(
const DWARFSection &AccelSection,
1959 unsigned NumErrors = 0;
1964 OS <<
"Verifying .debug_names...\n";
1969 std::string Msg =
toString(std::move(E));
1970 ErrorCategory.
Report(
"Accelerator Table Error",
1971 [&]() { error() << Msg <<
'\n'; });
1975 NumErrors += verifyDebugNamesCULists(
AccelTable);
1977 NumErrors += verifyNameIndexBuckets(NI, StrData);
1979 NumErrors += verifyNameIndexAbbrevs(NI);
1986 NumErrors += verifyNameIndexEntries(NI, NTE);
1993 if (
CU->getDWOId()) {
1997 if (CUDie != NonSkeletonUnitDie) {
2000 NumErrors += verifyNameIndexCompleteness(
2005 NumErrors += verifyNameIndexCompleteness(
DWARFDie(
CU, &Die), *NI);
2016 unsigned NumErrors = 0;
2017 if (!
D.getAppleNamesSection().Data.empty())
2018 NumErrors += verifyAppleAccelTable(&
D.getAppleNamesSection(), &StrData,
2020 if (!
D.getAppleTypesSection().Data.empty())
2021 NumErrors += verifyAppleAccelTable(&
D.getAppleTypesSection(), &StrData,
2023 if (!
D.getAppleNamespacesSection().Data.empty())
2024 NumErrors += verifyAppleAccelTable(&
D.getAppleNamespacesSection(), &StrData,
2025 ".apple_namespaces");
2026 if (!
D.getAppleObjCSection().Data.empty())
2027 NumErrors += verifyAppleAccelTable(&
D.getAppleObjCSection(), &StrData,
2030 if (!
D.getNamesSection().Data.empty())
2031 NumErrors += verifyDebugNames(
D.getNamesSection(), StrData);
2032 return NumErrors == 0;
2036 OS <<
"Verifying .debug_str_offsets...\n";
2045 std::optional<DwarfFormat> DwoLegacyDwarf4Format;
2047 if (DwoLegacyDwarf4Format)
2053 DwoLegacyDwarf4Format = InfoFormat;
2057 DwoLegacyDwarf4Format,
".debug_str_offsets.dwo",
2060 std::nullopt,
".debug_str_offsets",
2074 while (
C.seek(NextUnit),
C.tell() < DA.getData().size()) {
2080 Length = DA.getData().size();
2086 if (
C.tell() +
Length > DA.getData().size()) {
2088 "Section contribution length exceeds available space", [&]() {
2090 "{0}: contribution {1:X}: length exceeds available space "
2092 "offset ({1:X}) + length field space ({2:X}) + length "
2094 "{4:X} > section size {5:X})\n",
2096 C.tell() +
Length, DA.getData().size());
2105 ErrorCategory.
Report(
"Invalid Section version", [&]() {
2106 error() <<
formatv(
"{0}: contribution {1:X}: invalid version {2}\n",
2117 DA.setAddressSize(OffsetByteSize);
2119 if (Remainder != 0) {
2120 ErrorCategory.
Report(
"Invalid section contribution length", [&]() {
2122 "{0}: contribution {1:X}: invalid length ((length ({2:X}) "
2123 "- header (0x4)) % offset size {3:X} == {4:X} != 0)\n",
2134 if (StrData.
size() <= StrOff) {
2136 "String offset out of bounds of string section", [&]() {
2138 "{0}: contribution {1:X}: index {2:X}: invalid string "
2139 "offset *{3:X} == {4:X}, is beyond the bounds of the string "
2140 "section of length {5:X}\n",
2146 if (StrData[StrOff - 1] ==
'\0')
2149 "Section contribution contains invalid string offset", [&]() {
2151 "{0}: contribution {1:X}: index {2:X}: invalid string "
2152 "offset *{3:X} == {4:X}, is neither zero nor "
2153 "immediately following a null character\n",
2160 if (
Error E =
C.takeError()) {
2161 std::string Msg =
toString(std::move(E));
2162 ErrorCategory.
Report(
"String offset error", [&]() {
2171 StringRef s, std::function<
void(
void)> detailCallback) {
2172 Aggregation[std::string(s)]++;
2178 std::function<
void(
StringRef,
unsigned)> handleCounts) {
2179 for (
auto &&[
name,
count] : Aggregation) {
2186 error() <<
"Aggregated error counts:\n";
2188 error() << s <<
" occurred " <<
count <<
" time(s).\n";
2196 error() <<
"unable to open json summary file '"
2198 <<
"' for writing: " << EC.message() <<
'\n';
2208 ErrorCount += Count;
2211 RootNode.
try_emplace(
"error-categories", std::move(Categories));
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 isDWP() const
Return true of this DWARF context is a DWP file.
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()
DWARFTypeUnit * getTypeUnitForHash(uint64_t Hash, bool IsDWO)
unit_iterator_range info_section_units()
Get units from .debug_info in this context.
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
uint64_t getForeignTUSignature(uint32_t TU) const
Reads signature of foreign type unit TU. TU is 0-based.
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)
DWARFContext & getContext() const
DWARFDie getDIEForOffset(uint64_t Offset)
Return the DIE object for a given offset Offset inside the unit's DIE vector.
die_iterator_range dies()
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",...
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
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.
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.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
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.
const char * toString(DWARFSectionKind Kind)
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.