52std::optional<DWARFAddressRange>
54 auto Begin =
Ranges.begin();
56 auto Pos = std::lower_bound(Begin,
End, R);
59 if (Pos !=
End && *Pos == R) {
92 auto Prev = std::prev(It);
93 if (Prev->intersects(RI))
104 if (It->intersects(RI))
114 auto I2 = RHS.Ranges.begin(), E2 = RHS.Ranges.end();
120 bool Covered = I1->LowPC <= R.LowPC;
121 if (R.LowPC == R.HighPC || (Covered && R.HighPC <= I1->HighPC)) {
129 if (R.LowPC < I1->HighPC)
130 R.LowPC = I1->HighPC;
138 auto I2 = RHS.Ranges.begin(), E2 = RHS.Ranges.end();
139 while (I1 != E1 && I2 != E2) {
140 if (I1->intersects(*I2)) {
145 if (I1->LowPC < I2->LowPC)
154 uint64_t *
Offset,
unsigned UnitIndex,
156 uint64_t AbbrOffset,
Length;
161 bool ValidLength =
false;
162 bool ValidVersion =
false;
163 bool ValidAddrSize =
false;
164 bool ValidType =
true;
165 bool ValidAbbrevOffset =
true;
167 uint64_t OffsetStart = *
Offset;
176 AbbrOffset = isUnitDWARF64 ? DebugInfoData.
getU64(
Offset)
181 AbbrOffset = isUnitDWARF64 ? DebugInfoData.
getU64(
Offset)
188 if (!AbbrevSetOrErr) {
189 ValidAbbrevOffset =
false;
199 if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
202 bool HeaderShown =
false;
203 auto ShowHeaderOnce = [&]() {
205 error() <<
formatv(
"Units[{0}] - start offset: {1:x+8}\n", UnitIndex,
211 ErrorCategory.Report(
212 "Unit Header Length: Unit too large for .debug_info provided", [&]() {
214 note() <<
"The length for this unit is too "
215 "large for the .debug_info provided.\n";
218 ErrorCategory.Report(
219 "Unit Header Length: 16 bit unit header version is not valid", [&]() {
221 note() <<
"The 16 bit unit header version is not valid.\n";
224 ErrorCategory.Report(
225 "Unit Header Length: Unit type encoding is not valid", [&]() {
227 note() <<
"The unit type encoding is not valid.\n";
229 if (!ValidAbbrevOffset)
230 ErrorCategory.Report(
231 "Unit Header Length: Offset into the .debug_abbrev section is not "
235 note() <<
"The offset into the .debug_abbrev section is "
239 ErrorCategory.Report(
"Unit Header Length: Address size is unsupported",
242 note() <<
"The address size is unsupported.\n";
245 *
Offset = OffsetStart +
Length + (isUnitDWARF64 ? 12 : 4);
249bool DWARFVerifier::verifyName(
const DWARFDie &Die) {
253 std::string ReconstructedName;
254 raw_string_ostream OS(ReconstructedName);
255 std::string OriginalFullName;
257 if (OriginalFullName.empty() || OriginalFullName == ReconstructedName)
260 ErrorCategory.Report(
261 "Simplified template DW_AT_name could not be reconstituted", [&]() {
263 <<
"Simplified template DW_AT_name could not be reconstituted:\n"
265 " reconstituted: {1}\n",
266 OriginalFullName, ReconstructedName);
273unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit,
274 ReferenceMap &UnitLocalReferences,
275 ReferenceMap &CrossUnitReferences) {
276 unsigned NumUnitErrors = 0;
277 unsigned NumDies =
Unit.getNumDIEs();
278 for (
unsigned I = 0;
I < NumDies; ++
I) {
279 auto Die =
Unit.getDIEAtIndex(
I);
281 if (Die.
getTag() == DW_TAG_null)
285 NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
286 NumUnitErrors += verifyDebugInfoForm(Die, AttrValue, UnitLocalReferences,
287 CrossUnitReferences);
290 NumUnitErrors += verifyName(Die);
295 warn() <<
formatv(
"{0} has DW_CHILDREN_yes but DIE has no children: ",
301 NumUnitErrors += verifyDebugInfoCallSite(Die);
302 NumUnitErrors += verifyDebugInfoSubprogram(Die);
303 verifyDebugInfoLocalEntities(Die);
306 DWARFDie Die =
Unit.getUnitDIE(
false);
308 ErrorCategory.Report(
"Compilation unit missing DIE", [&]() {
309 error() <<
"Compilation unit without DIE.\n";
312 return NumUnitErrors;
316 ErrorCategory.Report(
"Compilation unit root DIE is not a unit DIE", [&]() {
317 error() <<
formatv(
"Compilation unit root DIE is not a unit DIE: {0}.\n",
325 ErrorCategory.Report(
"Mismatched unit type", [&]() {
327 "Compilation unit type ({0}) and root DIE ({1}) do not match.\n",
337 ErrorCategory.Report(
"Skeleton CU has children", [&]() {
338 error() <<
"Skeleton compilation unit has children.\n";
344 NumUnitErrors += verifyDieRanges(Die, RI);
346 return NumUnitErrors;
349unsigned DWARFVerifier::verifyDebugInfoCallSite(
const DWARFDie &Die) {
350 if (Die.
getTag() != DW_TAG_call_site && Die.
getTag() != DW_TAG_GNU_call_site)
355 if (Curr.
getTag() == DW_TAG_inlined_subroutine) {
356 ErrorCategory.Report(
357 "Call site nested entry within inlined subroutine", [&]() {
358 error() <<
"Call site entry nested within inlined subroutine:";
366 ErrorCategory.Report(
367 "Call site entry not nested within valid subprogram", [&]() {
368 error() <<
"Call site entry not nested within a valid subprogram:";
374 std::optional<DWARFFormValue> CallAttr = Curr.
find(
375 {DW_AT_call_all_calls, DW_AT_call_all_source_calls,
376 DW_AT_call_all_tail_calls, DW_AT_GNU_all_call_sites,
377 DW_AT_GNU_all_source_call_sites, DW_AT_GNU_all_tail_call_sites});
379 ErrorCategory.Report(
380 "Subprogram with call site entry has no DW_AT_call attribute", [&]() {
382 <<
"Subprogram with call site entry has no DW_AT_call attribute:";
392unsigned DWARFVerifier::verifyDebugInfoSubprogram(
const DWARFDie &Die) {
393 if (Die.
getTag() != DW_TAG_subprogram)
398 auto DumpWithChildren = [&]() {
399 DIDumpOptions ChildDumpOpts = DumpOpts;
402 Die.
dump(OS, 0, ChildDumpOpts);
408 return AttrValue.Attr == DW_AT_sibling;
410 ErrorCategory.Report(
"Subprogram DIE has no attributes", [&]() {
411 error() <<
"Subprogram DIE has no attributes:\n";
419 if (!Die.
find({DW_AT_name, DW_AT_linkage_name, DW_AT_MIPS_linkage_name,
420 DW_AT_abstract_origin, DW_AT_specification, DW_AT_low_pc,
421 DW_AT_ranges, DW_AT_entry_pc})) {
422 warn() <<
"Subprogram DIE has no name, abstract origin, specification or "
433 switch (Child.getTag()) {
434 case DW_TAG_lexical_block:
437 case DW_TAG_class_type:
438 case DW_TAG_structure_type:
439 case DW_TAG_union_type:
440 case DW_TAG_enumeration_type:
442 case DW_TAG_imported_module:
443 case DW_TAG_imported_declaration:
455void DWARFVerifier::verifyDebugInfoLocalEntities(
const DWARFDie &Die) {
456 if (Die.
getTag() != DW_TAG_subprogram &&
457 Die.
getTag() != DW_TAG_inlined_subroutine)
468 if (Entity.
find(DW_AT_abstract_origin))
470 warn() <<
formatv(
"{0} in concrete instance {1:x+8} of a subprogram should "
471 "only be in its abstract origin {2:x+8}:\n",
474 dump(Entity) <<
'\n';
478unsigned DWARFVerifier::verifyAbbrevSection(
const DWARFDebugAbbrev *Abbrev) {
482 Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclsOrErr =
484 if (!AbbrDeclsOrErr) {
486 ErrorCategory.Report(
"Abbreviation Declaration error",
487 [&]() {
error() << ErrMsg <<
"\n"; });
491 const auto *AbbrDecls = *AbbrDeclsOrErr;
492 unsigned NumErrors = 0;
493 for (
auto AbbrDecl : *AbbrDecls) {
494 SmallDenseSet<uint16_t> AttributeSet;
495 for (
auto Attribute : AbbrDecl.attributes()) {
498 ErrorCategory.Report(
499 "Abbreviation declartion contains multiple attributes", [&]() {
500 error() <<
formatv(
"Abbreviation declaration contains multiple "
513 OS <<
"Verifying .debug_abbrev...\n";
516 unsigned NumErrors = 0;
518 NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev());
520 NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO());
522 return NumErrors == 0;
526 unsigned NumDebugInfoErrors = 0;
527 ReferenceMap CrossUnitReferences;
531 for (
const auto &Unit : Units) {
532 OS <<
formatv(
"Verifying unit: {0} / {1}",
Index, Units.getNumUnits());
533 if (
const char *Name = Unit->getUnitDIE(
true).getShortName())
534 OS <<
formatv(
", \"{0}\"", Name);
537 ReferenceMap UnitLocalReferences;
538 NumDebugInfoErrors +=
539 verifyUnitContents(*Unit, UnitLocalReferences, CrossUnitReferences);
540 NumDebugInfoErrors += verifyDebugInfoReferences(
541 UnitLocalReferences, [&](uint64_t
Offset) {
return Unit.get(); });
545 NumDebugInfoErrors += verifyDebugInfoReferences(
547 if (DWARFUnit *U = Units.getUnitForOffset(
Offset))
552 return NumDebugInfoErrors;
555unsigned DWARFVerifier::verifyUnitSection(
const DWARFSection &S) {
556 const DWARFObject &DObj = DCtx.getDWARFObj();
557 DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0);
558 unsigned NumDebugInfoErrors = 0;
561 bool isUnitDWARF64 =
false;
562 bool isHeaderChainValid =
true;
567 isHeaderChainValid =
false;
574 if (UnitIdx == 0 && !hasDIE) {
575 warn() <<
"Section is empty.\n";
576 isHeaderChainValid =
true;
578 if (!isHeaderChainValid)
579 ++NumDebugInfoErrors;
580 return NumDebugInfoErrors;
583unsigned DWARFVerifier::verifyIndex(StringRef Name,
585 StringRef IndexStr) {
586 if (IndexStr.
empty())
588 OS <<
"Verifying " <<
Name <<
"...\n";
589 DWARFUnitIndex
Index(InfoColumnKind);
590 DataExtractor
D(IndexStr, DCtx.isLittleEndian());
593 using MapType = IntervalMap<uint64_t, uint64_t>;
594 MapType::Allocator
Alloc;
595 std::vector<std::unique_ptr<MapType>> Sections(
Index.getColumnKinds().size());
596 for (
const DWARFUnitIndex::Entry &
E :
Index.getRows()) {
598 if (!
E.getContributions())
601 InfoColumnKind == DW_SECT_INFO
604 const DWARFUnitIndex::Entry::SectionContribution &SC =
E.value();
609 Sections[Col] = std::make_unique<MapType>(
Alloc);
610 auto &
M = *Sections[Col];
613 StringRef Category = InfoColumnKind == DWARFSectionKind::DW_SECT_INFO
614 ?
"Overlapping CU index entries"
615 :
"Overlapping TU index entries";
616 ErrorCategory.Report(Category, [&]() {
618 "overlapping index entries for entries {0:x16} "
619 "and {1:x16} for column {2}\n",
632 return verifyIndex(
".debug_cu_index", DWARFSectionKind::DW_SECT_INFO,
633 DCtx.getDWARFObj().getCUIndexSection()) == 0;
638 DCtx.getDWARFObj().getTUIndexSection()) == 0;
643 unsigned NumErrors = 0;
645 OS <<
"Verifying .debug_info Unit Header Chain...\n";
647 [&](
const DWARFSection &S) { NumErrors += verifyUnitSection(S); });
649 OS <<
"Verifying .debug_types Unit Header Chain...\n";
651 [&](
const DWARFSection &S) { NumErrors += verifyUnitSection(S); });
653 OS <<
"Verifying non-dwo Units...\n";
654 NumErrors += verifyUnits(DCtx.getNormalUnitsVector());
656 OS <<
"Verifying dwo Units...\n";
657 NumErrors += verifyUnits(DCtx.getDWOUnitsVector());
658 return NumErrors == 0;
661unsigned DWARFVerifier::verifyDieRanges(
const DWARFDie &Die,
662 DieRangeInfo &ParentRI) {
663 unsigned NumErrors = 0;
671 if (!RangesOrError) {
673 if (!Unit->isDWOUnit())
682 DieRangeInfo RI(Die);
703 if (!IsObjectFile || IsMachOObject || Die.
getTag() != DW_TAG_compile_unit) {
704 bool DumpDieAfterError =
false;
705 for (
const auto &
Range : Ranges) {
706 if (!
Range.valid()) {
708 ErrorCategory.
Report(
"Invalid address range", [&]() {
710 DumpDieAfterError =
true;
721 if (
auto PrevRange = RI.insert(
Range)) {
723 ErrorCategory.Report(
"DIE has overlapping DW_AT_ranges", [&]() {
724 error() <<
formatv(
"DIE has overlapping ranges in DW_AT_ranges "
725 "attribute: {0} and {1}\n",
727 DumpDieAfterError =
true;
731 if (DumpDieAfterError)
732 dump(Die, 2) <<
'\n';
736 const auto IntersectingChild = ParentRI.insert(RI);
737 if (IntersectingChild != ParentRI.Children.end()) {
739 ErrorCategory.Report(
"DIEs have overlapping address ranges", [&]() {
740 error() <<
"DIEs have overlapping address ranges:";
742 dump(IntersectingChild->Die) <<
'\n';
747 bool ShouldBeContained = !RI.Ranges.empty() && !ParentRI.Ranges.empty() &&
748 !(Die.
getTag() == DW_TAG_subprogram &&
749 ParentRI.Die.getTag() == DW_TAG_subprogram);
750 if (ShouldBeContained && !ParentRI.contains(RI)) {
752 ErrorCategory.Report(
753 "DIE address ranges are not contained by parent ranges", [&]() {
755 <<
"DIE address ranges are not contained in its parent's ranges:";
757 dump(Die, 2) <<
'\n';
762 for (DWARFDie Child : Die)
763 NumErrors += verifyDieRanges(Child, RI);
768bool DWARFVerifier::verifyExpressionOp(
const DWARFExpression::Operation &
Op,
770 for (
unsigned Operand = 0; Operand <
Op.Desc.
Op.
size(); ++Operand) {
771 unsigned Size =
Op.Desc.
Op[Operand];
778 if (
Op.Opcode == DW_OP_convert &&
Op.Operands[Operand] == 0)
780 auto Die =
U->getDIEForOffset(
U->getOffset() +
Op.Operands[Operand]);
781 if (!Die || Die.
getTag() != dwarf::DW_TAG_base_type)
789bool DWARFVerifier::verifyExpression(
const DWARFExpression &
E, DWARFUnit *U) {
791 if (!verifyExpressionOp(
Op, U))
797unsigned DWARFVerifier::verifyDebugInfoAttribute(
const DWARFDie &Die,
798 DWARFAttribute &AttrValue) {
799 unsigned NumErrors = 0;
800 auto ReportError = [&](StringRef category,
const Twine &TitleMsg) {
802 ErrorCategory.Report(category, [&]() {
808 const DWARFObject &DObj = DCtx.getDWARFObj();
810 const auto Attr = AttrValue.
Attr;
815 unsigned DwarfVersion =
U->getVersion();
816 const DWARFSection &RangeSection = DwarfVersion < 5
819 if (
U->isDWOUnit() && RangeSection.
Data.
empty())
821 if (*SectionOffset >= RangeSection.
Data.
size())
823 "DW_AT_ranges offset out of bounds",
824 llvm::formatv(
"DW_AT_ranges offset is beyond {0} bounds: {1:x8}",
825 StringRef(DwarfVersion < 5 ?
".debug_ranges"
826 :
".debug_rnglists"),
830 ReportError(
"Invalid DW_AT_ranges encoding",
831 "DIE has invalid DW_AT_ranges encoding:");
833 case DW_AT_stmt_list:
836 if (*SectionOffset >=
U->getLineSection().Data.size())
838 "DW_AT_stmt_list offset out of bounds",
840 "DW_AT_stmt_list offset is beyond .debug_line bounds: {0:x8}",
844 ReportError(
"Invalid DW_AT_stmt_list encoding",
845 "DIE has invalid DW_AT_stmt_list encoding:");
847 case DW_AT_location: {
858 if (Expected<std::vector<DWARFLocationExpression>> Loc =
860 for (
const auto &Entry : *Loc) {
861 DataExtractor
Data(
Entry.Expr, DCtx.isLittleEndian());
862 DWARFExpression Expression(
Data,
U->getAddressByteSize(),
863 U->getFormParams().Format);
865 any_of(Expression, [](
const DWARFExpression::Operation &
Op) {
868 if (
Error || !verifyExpression(Expression, U))
869 ReportError(
"Invalid DWARF expressions",
870 "DIE contains invalid DWARF expression:");
873 Loc.takeError(), [&](std::unique_ptr<ResolverError>
E) {
874 return U->isDWOUnit() ? Error::success()
875 : Error(std::move(E));
877 ReportError(
"Invalid DW_AT_location",
toString(std::move(Err)));
880 case DW_AT_specification:
881 case DW_AT_abstract_origin: {
883 auto DieTag = Die.
getTag();
884 auto RefTag = ReferencedDie.getTag();
885 if (DieTag == RefTag)
887 if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
889 if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
892 if (DieTag == DW_TAG_GNU_call_site && RefTag == DW_TAG_subprogram)
894 ReportError(
"Incompatible DW_AT_abstract_origin tag reference",
895 formatv(
"DIE with tag {0} has {1} that points to DIE with "
896 "incompatible tag {2}",
905 ReportError(
"Incompatible DW_AT_type attribute tag",
906 formatv(
"DIE has {0} with incompatible tag {1}",
911 case DW_AT_call_file:
912 case DW_AT_decl_file: {
914 if (
U->isDWOUnit() && !
U->isTypeUnit())
916 const auto *
LT =
U->getContext().getLineTableForUnit(U);
918 if (!
LT->hasFileAtIndex(*FileIdx)) {
919 bool IsZeroIndexed =
LT->Prologue.getVersion() >= 5;
920 if (std::optional<uint64_t> LastFileIdx =
921 LT->getLastValidFileIndex()) {
922 ReportError(
"Invalid file index in DW_AT_decl_file",
924 "{1} (valid values are [{2}-{3}])",
926 (IsZeroIndexed ?
"0" :
"1"),
930 "Invalid file index in DW_AT_decl_file",
931 llvm::formatv(
"DIE has {0} with an invalid file index {1} (the "
932 "file table in the prologue is empty)",
938 "File index in DW_AT_decl_file reference CU with no line table",
939 llvm::formatv(
"DIE has {0} that references a file with index {1} "
940 "and the compile unit has no line table",
944 ReportError(
"Invalid encoding in DW_AT_decl_file",
950 case DW_AT_call_line:
951 case DW_AT_decl_line: {
954 Attr == DW_AT_call_line ?
"Invalid file index in DW_AT_decl_line"
955 :
"Invalid file index in DW_AT_call_line",
960 case DW_AT_LLVM_stmt_sequence: {
964 if (!SectionOffset) {
965 ReportError(
"Invalid DW_AT_LLVM_stmt_sequence encoding",
966 "DIE has invalid DW_AT_LLVM_stmt_sequence encoding");
969 if (*SectionOffset >=
U->getLineSection().Data.size()) {
971 "DW_AT_LLVM_stmt_sequence offset out of bounds",
972 "DW_AT_LLVM_stmt_sequence offset is beyond .debug_line bounds: " +
978 const auto *LineTable = DCtx.getLineTableForUnit(U);
980 ReportError(
"DW_AT_LLVM_stmt_sequence without line table",
981 "DIE has DW_AT_LLVM_stmt_sequence but compile unit has no "
987 DWARFDie CUDie =
U->getUnitDIE();
989 if (!StmtListOffset) {
990 ReportError(
"DW_AT_LLVM_stmt_sequence without DW_AT_stmt_list",
991 "DIE has DW_AT_LLVM_stmt_sequence but compile unit has no "
996 const int8_t DwarfOffset =
997 LineTable->Prologue.getFormParams().getDwarfOffsetByteSize();
999 uint64_t LineTableStart = *StmtListOffset;
1000 uint64_t PrologueLength = LineTable->Prologue.PrologueLength;
1001 uint64_t TotalLength = LineTable->Prologue.TotalLength;
1002 uint64_t LineTableEnd = LineTableStart + TotalLength + DwarfOffset;
1007 uint64_t InitialLengthSize = DwarfOffset;
1010 uint64_t PrologueLengthSize = DwarfOffset;
1011 uint64_t SequencesStart = LineTableStart + InitialLengthSize + VersionSize +
1012 PrologueLengthSize + PrologueLength;
1015 if (*SectionOffset < SequencesStart || *SectionOffset >= LineTableEnd) {
1016 ReportError(
"DW_AT_LLVM_stmt_sequence offset out of line table bounds",
1017 llvm::formatv(
"DW_AT_LLVM_stmt_sequence offset {0:x8} is not "
1018 "within the line table bounds [{1:x8}, {2:x8})",
1019 *SectionOffset, SequencesStart, LineTableEnd));
1025 [SectionOffset](
const auto &Sequence) {
1026 return Sequence.StmtSeqOffset == *SectionOffset;
1029 if (It == LineTable->Sequences.end())
1031 "Invalid DW_AT_LLVM_stmt_sequence offset",
1032 llvm::formatv(
"DW_AT_LLVM_stmt_sequence offset {0:x8} does not point "
1033 "to a valid sequence offset in the line table",
1043unsigned DWARFVerifier::verifyDebugInfoForm(
const DWARFDie &Die,
1044 DWARFAttribute &AttrValue,
1045 ReferenceMap &LocalReferences,
1046 ReferenceMap &CrossUnitReferences) {
1048 unsigned NumErrors = 0;
1055 case DW_FORM_ref_udata: {
1060 auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
1062 if (CUOffset >= CUSize) {
1064 ErrorCategory.Report(
"Invalid CU offset", [&]() {
1065 error() <<
formatv(
"{0} CU offset {1:x+8} is invalid (must be less "
1066 "than CU size of {2:x+8}):\n",
1068 Die.
dump(OS, 0, DumpOpts);
1080 case DW_FORM_ref_addr: {
1086 if (*RefVal >= DieCU->getInfoSection().Data.size()) {
1088 ErrorCategory.Report(
"DW_FORM_ref_addr offset out of bounds", [&]() {
1089 error() <<
"DW_FORM_ref_addr offset beyond .debug_info "
1096 CrossUnitReferences[*RefVal].insert(Die.
getOffset());
1107 case DW_FORM_line_strp: {
1110 std::string ErrMsg =
toString(std::move(
E));
1111 ErrorCategory.Report(
"Invalid DW_FORM attribute", [&]() {
1124unsigned DWARFVerifier::verifyDebugInfoReferences(
1125 const ReferenceMap &References,
1126 llvm::function_ref<DWARFUnit *(
uint64_t)> GetUnitForOffset) {
1128 if (DWARFUnit *U = GetUnitForOffset(
Offset))
1129 return U->getDIEForOffset(
Offset);
1132 unsigned NumErrors = 0;
1133 for (
const std::pair<
const uint64_t, std::set<uint64_t>> &Pair : References) {
1134 if (GetDIEForOffset(Pair.first))
1137 ErrorCategory.Report(
"Invalid DIE reference", [&]() {
1139 "invalid DIE reference {0:x+8}. Offset is in between DIEs:\n",
1141 for (
auto Offset : Pair.second)
1149void DWARFVerifier::verifyDebugLineStmtOffsets() {
1150 std::map<uint64_t, DWARFDie> StmtListToDie;
1151 for (
const auto &CU : DCtx.compile_units()) {
1152 auto Die = CU->getUnitDIE();
1157 if (!StmtSectionOffset)
1159 const uint64_t LineTableOffset = *StmtSectionOffset;
1160 auto LineTable = DCtx.getLineTableForUnit(CU.get());
1161 if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
1163 ++NumDebugLineErrors;
1164 ErrorCategory.Report(
"Unparsable .debug_line entry", [&]() {
1166 ".debug_line[{0:x+8}] was not able to be parsed for CU:\n",
1174 assert(LineTable ==
nullptr);
1179 auto [Iter,
Inserted] = StmtListToDie.try_emplace(LineTableOffset, Die);
1181 ++NumDebugLineErrors;
1182 const auto &OldDie = Iter->second;
1183 ErrorCategory.Report(
"Identical DW_AT_stmt_list section offset", [&]() {
1184 error() <<
formatv(
"two compile unit DIEs, {0:x+8} and {1:x+8}, have "
1185 "the same DW_AT_stmt_list section offset:\n",
1195void DWARFVerifier::verifyDebugLineRows() {
1196 for (
const auto &CU : DCtx.compile_units()) {
1197 auto Die = CU->getUnitDIE();
1198 auto LineTable = DCtx.getLineTableForUnit(CU.get());
1205 bool isDWARF5 = LineTable->Prologue.getVersion() >= 5;
1206 uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
1207 uint32_t MinFileIndex = isDWARF5 ? 0 : 1;
1208 uint32_t FileIndex = MinFileIndex;
1209 StringMap<uint16_t> FullPathMap;
1210 for (
const auto &FileName : LineTable->Prologue.FileNames) {
1212 if (FileName.DirIdx > MaxDirIndex) {
1213 ++NumDebugLineErrors;
1214 ErrorCategory.Report(
1215 "Invalid index in .debug_line->prologue.file_names->dir_idx",
1217 error() <<
formatv(
".debug_line[{0:x+8}].prologue.file_names[{1}]"
1218 ".dir_idx contains an invalid index: {2}\n",
1220 FileIndex, FileName.DirIdx);
1225 std::string FullPath;
1226 const bool HasFullPath = LineTable->getFileNameByIndex(
1227 FileIndex, CU->getCompilationDir(),
1229 assert(HasFullPath &&
"Invalid index?");
1232 if (!Inserted && It->second != FileIndex && DumpOpts.ShowErrorDetails) {
1233 warn() <<
formatv(
".debug_line[{0:x+8}].prologue.file_names[{1}] is a "
1234 "duplicate of file_names[{2}]\n",
1236 FileIndex, It->second);
1244 if (LineTable->Rows.size() == 1 && LineTable->Rows.front().EndSequence)
1249 uint32_t RowIndex = 0;
1250 for (
const auto &Row : LineTable->Rows) {
1252 if (Row.Address.Address < PrevAddress) {
1253 ++NumDebugLineErrors;
1254 ErrorCategory.Report(
1255 "decreasing address between debug_line rows", [&]() {
1256 error() <<
formatv(
".debug_line[{0:x+8}] row[{1}] decreases in "
1257 "address from previous row:\n",
1263 LineTable->Rows[RowIndex - 1].dump(OS);
1269 if (!LineTable->hasFileAtIndex(Row.File)) {
1270 ++NumDebugLineErrors;
1271 ErrorCategory.Report(
"Invalid file index in debug_line", [&]() {
1272 error() <<
formatv(
".debug_line[{0:x+8}][{1}] has invalid file index "
1273 "{2} (valid values are [{3},{4}{5}):\n",
1275 RowIndex, Row.File, MinFileIndex,
1276 LineTable->Prologue.FileNames.size(),
1277 (isDWARF5 ?
")" :
"]"));
1283 if (Row.EndSequence)
1286 PrevAddress = Row.Address.Address;
1294 : OS(S), DCtx(
D), DumpOpts(
std::
move(DumpOpts)), IsObjectFile(
false),
1295 IsMachOObject(
false) {
1297 if (
const auto *
F = DCtx.getDWARFObj().getFile()) {
1298 IsObjectFile = F->isRelocatableObject();
1299 IsMachOObject = F->isMachO();
1304 NumDebugLineErrors = 0;
1305 OS <<
"Verifying .debug_line...\n";
1306 verifyDebugLineStmtOffsets();
1307 verifyDebugLineRows();
1308 return NumDebugLineErrors == 0;
1311void DWARFVerifier::verifyAppleAccelTable(
const DWARFSection *AccelSection,
1321 if (!AccelSectionData.isValidOffset(
AccelTable.getSizeHdr())) {
1322 ErrorCategory.
Report(
"Section is too small to fit a section header", [&]() {
1323 error() <<
"Section is too small to fit a section header.\n";
1329 if (
Error E = AccelTable.extract()) {
1331 ErrorCategory.Report(
"Section is too small to fit a section header",
1332 [&]() {
error() <<
Msg <<
'\n'; });
1337 uint32_t NumBuckets = AccelTable.getNumBuckets();
1338 uint32_t NumHashes = AccelTable.getNumHashes();
1341 AccelTable.getSizeHdr() + AccelTable.getHeaderDataLength();
1342 uint64_t HashesBase = BucketsOffset + NumBuckets * 4;
1343 uint64_t OffsetsBase = HashesBase + NumHashes * 4;
1344 for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
1345 uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
1346 if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
1347 ErrorCategory.Report(
"Invalid hash index", [&]() {
1348 error() <<
formatv(
"Bucket[{0}] has invalid hash index: {1}.\n",
1349 BucketIdx, HashIdx);
1353 uint32_t NumAtoms = AccelTable.getAtomsDesc().size();
1354 if (NumAtoms == 0) {
1355 ErrorCategory.Report(
"No atoms", [&]() {
1356 error() <<
"No atoms: failed to read HashData.\n";
1360 if (!AccelTable.validateForms()) {
1361 ErrorCategory.Report(
"Unsupported form", [&]() {
1362 error() <<
"Unsupported form: failed to read HashData.\n";
1367 for (uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
1368 uint64_t HashOffset = HashesBase + 4 * HashIdx;
1369 uint64_t DataOffset = OffsetsBase + 4 * HashIdx;
1370 uint32_t Hash = AccelSectionData.getU32(&HashOffset);
1371 uint64_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
1372 if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
1374 ErrorCategory.Report(
"Invalid HashData offset", [&]() {
1375 error() <<
formatv(
"Hash[{0}] has invalid HashData offset: {1:x+8}.\n",
1376 HashIdx, HashDataOffset);
1382 uint32_t StringCount = 0;
1385 while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
1386 const uint32_t NumHashDataObjects =
1387 AccelSectionData.getU32(&HashDataOffset);
1388 for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
1390 std::tie(
Offset,
Tag) = AccelTable.readAtoms(&HashDataOffset);
1391 auto Die = DCtx.getDIEForOffset(
Offset);
1393 const uint32_t BucketIdx =
1394 NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
1395 StringOffset = StrpOffset;
1396 const char *
Name = StrData->
getCStr(&StringOffset);
1400 ErrorCategory.Report(
"Invalid DIE offset", [&]() {
1401 error() <<
formatv(
"{0} Bucket[{1}] Hash[{2}] = {3:x+8} "
1402 "Str[{4}] = {5:x+8} DIE[{6}] = {7:x+8} "
1403 "is not a valid DIE offset for \"{8}\".\n",
1404 SectionName, BucketIdx, HashIdx, Hash,
1405 StringCount, StrpOffset, HashDataIdx,
Offset,
1410 if ((
Tag != dwarf::DW_TAG_null) && (Die.
getTag() !=
Tag)) {
1411 ErrorCategory.Report(
"Mismatched Tag in accellerator table", [&]() {
1412 error() <<
formatv(
"Tag {0} in accelerator table does not match "
1413 "Tag {1} of DIE[{2}].\n",
1426 DenseMap<uint64_t, uint64_t> CUMap;
1427 CUMap.
reserve(DCtx.getNumCompileUnits());
1429 DenseSet<uint64_t> CUOffsets;
1430 for (
const auto &CU : DCtx.compile_units())
1431 CUOffsets.
insert(CU->getOffset());
1433 parallelForEach(AccelTable, [&](
const DWARFDebugNames::NameIndex &NI) {
1435 ErrorCategory.Report(
"Name Index doesn't index any CU", [&]() {
1436 error() <<
formatv(
"Name Index @ {0:x} does not index any CU\n",
1444 ErrorCategory.Report(
"Name Index references non-existing CU", [&]() {
1446 "Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
1453 std::lock_guard<std::mutex> Lock(AccessMutex);
1455 if (Iter != CUMap.
end())
1456 DuplicateCUOffset = Iter->second;
1460 if (DuplicateCUOffset) {
1461 ErrorCategory.Report(
"Duplicate Name Index", [&]() {
1463 "Name Index @ {0:x} references a CU @ {1:x}, but "
1464 "this CU is already indexed by Name Index @ {2:x}\n",
1472 for (
const auto &CU : DCtx.compile_units()) {
1473 if (CUMap.
count(CU->getOffset()) == 0)
1474 warn() <<
formatv(
"CU @ {0:x} not covered by any Name Index\n",
1485 constexpr BucketInfo(uint32_t Bucket, uint32_t
Index)
1491 warn() <<
formatv(
"Name Index @ {0:x} does not contain a hash table.\n",
1498 std::vector<BucketInfo> BucketStarts;
1500 const uint64_t OrigNumberOfErrors = ErrorCategory.GetNumErrors();
1504 ErrorCategory.Report(
"Name Index Bucket contains invalid value", [&]() {
1505 error() <<
formatv(
"Bucket {0} of Name Index @ {1:x} contains invalid "
1506 "value {2}. Valid range is [0, {3}].\n",
1513 BucketStarts.emplace_back(Bucket,
Index);
1519 if (OrigNumberOfErrors != ErrorCategory.GetNumErrors())
1532 uint32_t NextUncovered = 1;
1533 for (
const BucketInfo &
B : BucketStarts) {
1540 if (
B.Index > NextUncovered) {
1541 ErrorCategory.Report(
"Name table entries uncovered by hash table", [&]() {
1542 error() <<
formatv(
"Name Index @ {0:x}: Name table entries [{1}, {2}] "
1543 "are not covered by the hash table.\n",
1547 uint32_t
Idx =
B.Index;
1560 ErrorCategory.Report(
"Name Index point to mismatched hash value", [&]() {
1562 "Name Index @ {0:x}: Bucket {1} is not empty but points to a "
1563 "mismatched hash value {2:x} (belonging to bucket {3}).\n",
1579 ErrorCategory.Report(
1580 "String hash doesn't match Name Index hash", [&]() {
1582 "Name Index @ {0:x}: String ({1}) at index {2} "
1583 "hashes to {3:x}, but "
1584 "the Name Index hash is {4:x}\n",
1590 NextUncovered = std::max(NextUncovered, Idx);
1594void DWARFVerifier::verifyNameIndexAttribute(
1598 if (FormName.
empty()) {
1599 ErrorCategory.Report(
"Unknown NameIndex Abbreviation", [&]() {
1600 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1601 "unknown form: {3}.\n",
1608 if (AttrEnc.
Index == DW_IDX_type_hash) {
1609 if (AttrEnc.
Form != dwarf::DW_FORM_data8) {
1610 ErrorCategory.Report(
"Unexpected NameIndex Abbreviation", [&]() {
1612 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
1613 "uses an unexpected form {2} (should be {3}).\n",
1621 if (AttrEnc.
Index == dwarf::DW_IDX_parent) {
1622 constexpr static auto AllowedForms = {dwarf::Form::DW_FORM_flag_present,
1623 dwarf::Form::DW_FORM_ref4};
1625 ErrorCategory.Report(
"Unexpected NameIndex Abbreviation", [&]() {
1627 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_parent "
1628 "uses an unexpected form {2} (should be "
1629 "DW_FORM_ref4 or DW_FORM_flag_present).\n",
1640 struct FormClassTable {
1643 StringLiteral ClassName;
1645 static constexpr FormClassTable
Table[] = {
1653 return T.Index == AttrEnc.
Index;
1656 warn() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} contains an "
1657 "unknown index attribute: {2}.\n",
1662 if (!DWARFFormValue(AttrEnc.
Form).isFormClass(Iter->Class)) {
1663 ErrorCategory.Report(
"Unexpected NameIndex Abbreviation", [&]() {
1664 error() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1665 "unexpected form {3} (expected form class {4}).\n",
1667 AttrEnc.
Form, Iter->ClassName);
1673void DWARFVerifier::verifyNameIndexAbbrevs(
1677 if (TagName.
empty()) {
1678 warn() <<
formatv(
"NameIndex @ {0:x}: Abbreviation {1:x} references an "
1679 "unknown tag: {2}.\n",
1683 for (
const auto &AttrEnc : Abbrev.Attributes) {
1685 ErrorCategory.Report(
1686 "NameIndex Abbreviateion contains multiple attributes", [&]() {
1688 "NameIndex @ {0:x}: Abbreviation {1:x} contains "
1689 "multiple {2} attributes.\n",
1694 verifyNameIndexAttribute(NI, Abbrev, AttrEnc);
1698 !
Attributes.count(dwarf::DW_IDX_type_unit)) {
1699 ErrorCategory.Report(
"Abbreviation contains no attribute", [&]() {
1700 error() <<
formatv(
"NameIndex @ {0:x}: Indexing multiple compile units "
1701 "and abbreviation {1:x} has no DW_IDX_compile_unit "
1702 "or DW_IDX_type_unit attribute.\n",
1706 if (!
Attributes.count(dwarf::DW_IDX_die_offset)) {
1707 ErrorCategory.Report(
"Abbreviate in NameIndex missing attribute", [&]() {
1709 "NameIndex @ {0:x}: Abbreviation {1:x} has no {2} attribute.\n",
1719 bool IncludeStrippedTemplateNames,
1720 bool IncludeObjCNames =
true,
1721 bool IncludeLinkageName =
true) {
1723 if (
const char *Str =
DIE.getShortName()) {
1725 Result.emplace_back(Name);
1726 if (IncludeStrippedTemplateNames) {
1727 if (std::optional<StringRef> StrippedName =
1731 Result.push_back(StrippedName->str());
1734 if (IncludeObjCNames) {
1735 if (std::optional<ObjCSelectorNames> ObjCNames =
1737 Result.emplace_back(ObjCNames->ClassName);
1738 Result.emplace_back(ObjCNames->Selector);
1739 if (ObjCNames->ClassNameNoCategory)
1740 Result.emplace_back(*ObjCNames->ClassNameNoCategory);
1741 if (ObjCNames->MethodNameNoCategory)
1742 Result.push_back(std::move(*ObjCNames->MethodNameNoCategory));
1745 }
else if (
DIE.
getTag() == dwarf::DW_TAG_namespace)
1746 Result.emplace_back(
"(anonymous namespace)");
1748 if (IncludeLinkageName) {
1749 if (
const char *Str =
DIE.getLinkageName())
1750 Result.emplace_back(Str);
1756void DWARFVerifier::verifyNameIndexEntries(
1762 ErrorCategory.Report(
"Unable to get string associated with name", [&]() {
1763 error() <<
formatv(
"Name Index @ {0:x}: Unable to get string associated "
1769 StringRef Str(CStr);
1773 Expected<DWARFDebugNames::Entry> EntryOr = NI.
getEntry(&NextEntryID);
1774 for (; EntryOr; ++
NumEntries, EntryID = NextEntryID,
1775 EntryOr = NI.
getEntry(&NextEntryID)) {
1777 std::optional<uint64_t> CUIndex = EntryOr->getRelatedCUIndex();
1778 std::optional<uint64_t> TUIndex = EntryOr->getTUIndex();
1779 if (CUIndex && *CUIndex >= NI.
getCUCount()) {
1780 ErrorCategory.Report(
"Name Index entry contains invalid CU index", [&]() {
1781 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1782 "invalid CU index ({2}).\n",
1789 if (TUIndex && *TUIndex >= (NumLocalTUs + NumForeignTUs)) {
1790 ErrorCategory.Report(
"Name Index entry contains invalid TU index", [&]() {
1791 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1792 "invalid TU index ({2}).\n",
1797 std::optional<uint64_t> UnitOffset;
1800 if (*TUIndex >= NumLocalTUs) {
1813 ErrorCategory.Report(
1814 "Name Index entry contains foreign TU index with invalid CU "
1818 "Name Index @ {0:x}: Entry @ {1:x} contains an "
1819 "foreign TU index ({2}) with no CU index.\n",
1828 }
else if (CUIndex) {
1834 if (!UnitOffset || UnitOffset == UINT32_MAX)
1839 DWARFUnit *DU = DCtx.getUnitForOffset(*UnitOffset);
1840 if (DU ==
nullptr || DU->
getOffset() != *UnitOffset) {
1843 ErrorCategory.Report(
1844 "Name Index entry contains invalid CU or TU offset", [&]() {
1845 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
1846 "invalid CU or TU offset {2:x}.\n",
1865 auto IsSkeletonCU = [&]() {
1867 return UnitDie.
getTag() == dwarf::DW_TAG_skeleton_unit;
1870 bool IsSkeleton = DU->
getDWOId() && IsSkeletonCU();
1871 DWARFUnit *NonSkeletonUnit =
nullptr;
1874 NonSkeletonUnit = Iter->second;
1876 NonSkeletonUnit = DU;
1878 if (IsSkeleton && !NonSkeletonUnit->
isDWOUnit()) {
1879 ErrorCategory.Report(
"Unable to get load .dwo file", [&]() {
1881 "Name Index @ {0:x}: Entry @ {1:x} unable to load "
1882 ".dwo file \"{2}\" for DWARF unit @ {3:x}.\n",
1890 if (TUIndex && *TUIndex >= NumLocalTUs) {
1898 const uint32_t ForeignTUIdx = *TUIndex - NumLocalTUs;
1900 llvm::DWARFContext &NonSkeletonDCtx = NonSkeletonUnit->
getContext();
1908 if (NonSkeletonDCtx.
isDWP()) {
1909 DWARFDie NonSkeletonUnitDie = NonSkeletonUnit->
getUnitDIE(
true);
1911 UnitDie.
find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1913 NonSkeletonUnitDie.
find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1914 if (DUDwoName != TUDwoName)
1919 NonSkeletonUnit->
getOffset() + *EntryOr->getDIEUnitOffset();
1923 if (DIEOffset >= NextUnitOffset) {
1924 ErrorCategory.Report(
"NameIndex relative DIE offset too large", [&]() {
1925 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} references a "
1926 "DIE @ {2:x} when CU or TU ends at {3:x}.\n",
1934 ErrorCategory.Report(
"NameIndex references nonexistent DIE", [&]() {
1935 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x} references a "
1936 "non-existing DIE @ {2:x}.\n",
1947 ErrorCategory.Report(
"Name index contains mismatched CU of DIE", [&]() {
1949 "Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "
1950 "DIE @ {2:x}: index - {3:x}; debug_info - {4:x}.\n",
1955 if (DIE.
getTag() != EntryOr->tag()) {
1956 ErrorCategory.Report(
"Name Index contains mismatched Tag of DIE", [&]() {
1958 "Name Index @ {0:x}: Entry @ {1:x}: mismatched Tag of "
1959 "DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1967 auto IncludeStrippedTemplateNames =
1968 DIE.
getTag() == DW_TAG_subprogram ||
1969 DIE.
getTag() == DW_TAG_inlined_subroutine;
1970 auto EntryNames =
getNames(DIE, IncludeStrippedTemplateNames);
1972 ErrorCategory.Report(
"Name Index contains mismatched name of DIE", [&]() {
1973 error() <<
formatv(
"Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
1974 "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1976 make_range(EntryNames.begin(), EntryNames.end()));
1981 EntryOr.takeError(),
1982 [&](
const DWARFDebugNames::SentinelError &) {
1985 ErrorCategory.Report(
1986 "NameIndex Name is not associated with any entries", [&]() {
1987 error() << formatv(
"Name Index @ {0:x}: Name {1} ({2}) is "
1988 "not associated with any entries.\n",
1989 NI.getUnitOffset(), NTE.getIndex(), Str);
1993 ErrorCategory.Report(
"Uncategorized NameIndex error", [&]() {
1994 error() <<
formatv(
"Name Index @ {0:x}: Name {1} ({2}): {3}\n",
2009 for (
const auto &Entry : *
Loc) {
2012 U->getFormParams().Format);
2013 bool IsInteresting =
2016 return !
Op.isError() && (
Op.getCode() == DW_OP_addr ||
2017 Op.getCode() == DW_OP_form_tls_address ||
2018 Op.getCode() == DW_OP_GNU_push_tls_address);
2026void DWARFVerifier::verifyNameIndexCompleteness(
2035 if (Die.
find(DW_AT_declaration))
2045 auto IncludeLinkageName = Die.
getTag() == DW_TAG_subprogram ||
2046 Die.
getTag() == DW_TAG_inlined_subroutine;
2049 auto IncludeStrippedTemplateNames =
false;
2050 auto IncludeObjCNames =
false;
2051 auto EntryNames =
getNames(Die, IncludeStrippedTemplateNames,
2052 IncludeObjCNames, IncludeLinkageName);
2053 if (EntryNames.empty())
2063 case DW_TAG_compile_unit:
2069 case DW_TAG_formal_parameter:
2070 case DW_TAG_template_value_parameter:
2071 case DW_TAG_template_type_parameter:
2072 case DW_TAG_GNU_template_parameter_pack:
2073 case DW_TAG_GNU_template_template_param:
2080 case DW_TAG_property:
2086 case DW_TAG_LLVM_annotation:
2092 case DW_TAG_enumerator:
2097 case DW_TAG_imported_declaration:
2103 case DW_TAG_subprogram:
2104 case DW_TAG_inlined_subroutine:
2107 {DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_entry_pc}))
2116 case DW_TAG_variable:
2128 for (StringRef Name : EntryNames) {
2129 auto iter = NamesToDieOffsets.find(Name);
2130 if (iter == NamesToDieOffsets.end() || !iter->second.count(DieUnitOffset)) {
2131 ErrorCategory.Report(
2132 "Name Index DIE entry missing name",
2135 "Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
2136 "name {3} missing.\n",
2137 NI.getUnitOffset(), Die.getOffset(), Die.getTag(), Name);
2149 CUTU->getBaseAddress();
2152 if (Error E = CUTU->tryExtractDIEsIfNeeded(false))
2153 DCtx.getRecoverableErrorHandler()(std::move(E));
2159 if (!
CU->getDWOId())
2162 CU->getNonSkeletonUnitDIE().getDwarfUnit()->getContext();
2164 for (
auto &CUTU : NonSkeletonContext.
dwo_units()) {
2166 CUTU->getBaseAddress();
2169 if (Error E = CUTU->tryExtractDIEsIfNeeded(false))
2170 DCtx.getRecoverableErrorHandler()(std::move(E));
2173 if (NonSkeletonContext.
isDWP())
2178void DWARFVerifier::verifyDebugNames(
const DWARFSection &AccelSection,
2180 DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), AccelSection,
2181 DCtx.isLittleEndian(), 0);
2182 DWARFDebugNames AccelTable(AccelSectionData, StrData);
2184 OS <<
"Verifying .debug_names...\n";
2190 ErrorCategory.Report(
"Accelerator Table Error",
2191 [&]() {
error() <<
Msg <<
'\n'; });
2194 const uint64_t OriginalNumErrors = ErrorCategory.GetNumErrors();
2195 verifyDebugNamesCULists(AccelTable);
2196 for (
const auto &NI : AccelTable)
2197 verifyNameIndexBuckets(NI, StrData);
2198 parallelForEach(AccelTable, [&](
const DWARFDebugNames::NameIndex &NI) {
2199 verifyNameIndexAbbrevs(NI);
2203 if (OriginalNumErrors != ErrorCategory.GetNumErrors())
2205 DenseMap<uint64_t, DWARFUnit *> CUOffsetsToDUMap;
2206 for (
const auto &CU : DCtx.compile_units()) {
2207 if (!(CU->getVersion() >= 5 && CU->getDWOId()))
2209 CUOffsetsToDUMap[CU->getOffset()] =
2210 CU->getNonSkeletonUnitDIE().getDwarfUnit();
2213 for (
const DWARFDebugNames::NameIndex &NI : AccelTable) {
2215 verifyNameIndexEntries(NI, NTE, CUOffsetsToDUMap);
2219 auto populateNameToOffset =
2220 [&](
const DWARFDebugNames::NameIndex &NI,
2221 StringMap<DenseSet<uint64_t>> &NamesToDieOffsets) {
2222 for (
const DWARFDebugNames::NameTableEntry &NTE : NI) {
2224 const std::string
Name = tName ? std::string(tName) :
"";
2226 Expected<DWARFDebugNames::Entry> EntryOr = NI.getEntry(&EntryID);
2227 auto Iter = NamesToDieOffsets.insert({
Name, DenseSet<uint64_t>(3)});
2228 for (; EntryOr; EntryOr = NI.getEntry(&EntryID)) {
2229 if (std::optional<uint64_t> DieOffset = EntryOr->getDIEUnitOffset())
2230 Iter.first->second.insert(*DieOffset);
2234 [&](
const DWARFDebugNames::SentinelError &) {
2235 if (!NamesToDieOffsets.empty())
2237 ErrorCategory.Report(
2238 "NameIndex Name is not associated with any entries", [&]() {
2240 << formatv(
"Name Index @ {0:x}: Name {1} ({2}) is "
2241 "not associated with any entries.\n",
2242 NI.getUnitOffset(), NTE.getIndex(), Name);
2245 [&](
const ErrorInfoBase &
Info) {
2246 ErrorCategory.Report(
"Uncategorized NameIndex error", [&]() {
2248 "Name Index @ {0:x}: Name {1} ({2}): {3}\n",
2249 NI.getUnitOffset(), NTE.
getIndex(), Name,
Info.message());
2258 populateNameToOffset(NI, NamesToDieOffsets);
2259 for (uint32_t i = 0, iEnd = NI.getCUCount(); i < iEnd; ++i) {
2260 const uint64_t CUOffset = NI.getCUOffset(i);
2261 DWARFUnit *
U = DCtx.getUnitForOffset(CUOffset);
2268 if (CUDie != NonSkeletonUnitDie) {
2272 verifyNameIndexCompleteness(
2273 DWARFDie(NonSkeletonUnitDie.getDwarfUnit(), &Die), NI,
2279 verifyNameIndexCompleteness(DWARFDie(CU, &Die), NI,
2291 if (!
D.getAppleNamesSection().Data.empty())
2292 verifyAppleAccelTable(&
D.getAppleNamesSection(), &StrData,
".apple_names");
2293 if (!
D.getAppleTypesSection().Data.empty())
2294 verifyAppleAccelTable(&
D.getAppleTypesSection(), &StrData,
".apple_types");
2295 if (!
D.getAppleNamespacesSection().Data.empty())
2296 verifyAppleAccelTable(&
D.getAppleNamespacesSection(), &StrData,
2297 ".apple_namespaces");
2298 if (!
D.getAppleObjCSection().Data.empty())
2299 verifyAppleAccelTable(&
D.getAppleObjCSection(), &StrData,
".apple_objc");
2301 if (!
D.getNamesSection().Data.empty())
2302 verifyDebugNames(
D.getNamesSection(), StrData);
2303 return ErrorCategory.GetNumErrors() == 0;
2307 OS <<
"Verifying .debug_str_offsets...\n";
2316 std::optional<DwarfFormat> DwoLegacyDwarf4Format;
2318 if (DwoLegacyDwarf4Format)
2323 if (uint16_t InfoVersion = DebugInfoData.
getU16(&
Offset); InfoVersion <= 4)
2324 DwoLegacyDwarf4Format = InfoFormat;
2328 DwoLegacyDwarf4Format,
".debug_str_offsets.dwo",
2331 std::nullopt,
".debug_str_offsets",
2343 uint64_t NextUnit = 0;
2345 while (
C.seek(NextUnit),
C.tell() < DA.getData().size()) {
2348 uint64_t StartOffset =
C.tell();
2351 Length = DA.getData().size();
2357 if (
C.tell() +
Length > DA.getData().size()) {
2358 ErrorCategory.Report(
2359 "Section contribution length exceeds available space", [&]() {
2361 "{0}: contribution {1:X}: length exceeds available space "
2363 "offset ({1:X}) + length field space ({2:X}) + length "
2365 "{4:X} > section size {5:X})\n",
2367 C.tell() +
Length, DA.getData().size());
2376 ErrorCategory.Report(
"Invalid Section version", [&]() {
2377 error() <<
formatv(
"{0}: contribution {1:X}: invalid version {2}\n",
2388 DA.setAddressSize(OffsetByteSize);
2389 uint64_t Remainder = (
Length - 4) % OffsetByteSize;
2390 if (Remainder != 0) {
2391 ErrorCategory.Report(
"Invalid section contribution length", [&]() {
2393 "{0}: contribution {1:X}: invalid length ((length ({2:X}) "
2394 "- header (0x4)) % offset size {3:X} == {4:X} != 0)\n",
2399 for (uint64_t
Index = 0;
C &&
C.tell() + OffsetByteSize <= NextUnit;
2401 uint64_t OffOff =
C.tell();
2402 uint64_t StrOff = DA.getAddress(
C);
2406 if (StrData.
size() <= StrOff) {
2407 ErrorCategory.Report(
2408 "String offset out of bounds of string section", [&]() {
2410 "{0}: contribution {1:X}: index {2:X}: invalid string "
2411 "offset *{3:X} == {4:X}, is beyond the bounds of the string "
2412 "section of length {5:X}\n",
2418 if (StrData[StrOff - 1] ==
'\0')
2420 ErrorCategory.Report(
2421 "Section contribution contains invalid string offset", [&]() {
2423 "{0}: contribution {1:X}: index {2:X}: invalid string "
2424 "offset *{3:X} == {4:X}, is neither zero nor "
2425 "immediately following a null character\n",
2432 if (
Error E =
C.takeError()) {
2434 ErrorCategory.Report(
"String offset error", [&]() {
2443 Report(s,
"", detailCallback);
2449 std::lock_guard<std::mutex> Lock(WriteMutex);
2451 std::string category_str = std::string(category);
2454 if (!sub_category.
empty()) {
2463 for (
const auto &[
name, aggData] : Aggregation) {
2464 handleCounts(
name, aggData.OverallCount);
2469 const auto Agg = Aggregation.find(category);
2470 if (Agg != Aggregation.end()) {
2472 handleCounts(
name, aggData);
2478 if (DumpOpts.ShowAggregateErrors && ErrorCategory.GetNumCategories()) {
2479 error() <<
"Aggregated error counts:\n";
2480 ErrorCategory.EnumerateResults([&](
StringRef s,
unsigned count) {
2484 if (!DumpOpts.JsonErrSummaryFile.empty()) {
2490 "unable to open json summary file {0} for writing: {1}\n",
2491 DumpOpts.JsonErrSummaryFile, EC.message());
2496 uint64_t ErrorCount = 0;
2497 ErrorCategory.EnumerateResults([&](
StringRef Category,
unsigned Count) {
2501 ErrorCategory.EnumerateDetailedResultsFor(
2502 Category, [&](
StringRef SubCategory,
unsigned SubCount) {
2507 ErrorCount +=
Count;
2510 RootNode.
try_emplace(
"error-categories", std::move(Categories));
2524 Die.
dump(OS, indent, DumpOpts);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ArrayRef< TableEntry > TableRef
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static void extractCUsTus(DWARFContext &DCtx)
Extracts all the data for CU/TUs so we can access it in parallel without locks.
static void verifySharedLocalEntities(const DWARFDie &Scope, function_ref< void(DWARFDie)> VerifyF)
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)
Constructs a full name for a DIE.
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))
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...
A structured debug information entry.
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)
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
DWARFTypeUnit * getTypeUnitForHash(uint64_t Hash, bool IsDWO)
unit_iterator_range normal_units()
Get all normal compile/type units in this context.
static bool isAddressSizeSupported(unsigned AddressSize)
unit_iterator_range dwo_units()
Get all units in the DWO context.
const DWARFObject & getDWARFObj() const
LLVM_ABI Expected< const DWARFAbbreviationDeclarationSet * > getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const
DWARFDebugInfoEntry - A DIE with only the minimum required data.
Represents a single accelerator table within the DWARF v5 .debug_names section.
LLVM_ABI uint32_t getHashArrayEntry(uint32_t Index) const
Reads an entry in the Hash Array for the given Index.
LLVM_ABI uint64_t getLocalTUOffset(uint32_t TU) const
Reads offset of local type unit TU, TU is 0-based.
LLVM_ABI 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
LLVM_ABI uint64_t getCUOffset(uint32_t CU) const
Reads offset of compilation unit CU. CU is 0-based.
LLVM_ABI Expected< Entry > getEntry(uint64_t *Offset) const
LLVM_ABI 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
LLVM_ABI 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.
.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.
LLVM_ABI 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.
LLVM_ABI Expected< DWARFAddressRangesVector > getAddressRanges() const
Get the address ranges for this DIE.
iterator_range< iterator > children() const
LLVM_ABI DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as the referenced DIE.
LLVM_ABI DWARFDie getParent() const
Get the parent of this DIE object.
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
DWARFUnit * getDwarfUnit() const
LLVM_ABI bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
LLVM_ABI 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...
LLVM_ABI DWARFDie getFirstChild() const
Get the first child of this DIE object.
dwarf::Tag getTag() const
LLVM_ABI Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
LLVM_ABI iterator_range< attribute_iterator > attributes() const
Get an iterator range to all attributes in the current DIE only.
LLVM_ABI 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 void forEachTypesSections(function_ref< void(const DWARFSection &)> F) const
virtual const DWARFSection & getStrOffsetsSection() const
virtual const DWARFSection & getRnglistsSection() const
virtual StringRef getStrSection() const
uint64_t getLength() const
uint64_t getOffset() 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.
uint16_t getVersion() const
die_iterator_range dies()
static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag)
uint64_t getNextUnitOffset() const
uint64_t getOffset() const
LLVM_ABI bool handleAccelTables()
Verify the information in accelerator tables, if they exist.
LLVM_ABI bool verifyDebugStrOffsets(std::optional< dwarf::DwarfFormat > LegacyFormat, StringRef SectionName, const DWARFSection &Section, StringRef StrData)
LLVM_ABI bool handleDebugTUIndex()
Verify the information in the .debug_tu_index section.
LLVM_ABI bool handleDebugStrOffsets()
Verify the information in the .debug_str_offsets[.dwo].
LLVM_ABI bool handleDebugCUIndex()
Verify the information in the .debug_cu_index section.
LLVM_ABI DWARFVerifier(raw_ostream &S, DWARFContext &D, DIDumpOptions DumpOpts=DIDumpOptions::getForSingleDIE())
LLVM_ABI bool handleDebugInfo()
Verify the information in the .debug_info and .debug_types sections.
LLVM_ABI bool handleDebugLine()
Verify the information in the .debug_line section.
LLVM_ABI void summarize()
Emits any aggregate information collected, depending on the dump options.
LLVM_ABI bool handleDebugAbbrev()
Verify the information in any of the following sections, if available: .debug_abbrev,...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
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.
Implements a dense probed hash-table based set.
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.
LLVM_ABI void Report(StringRef category, function_ref< void()> detailCallback)
LLVM_ABI void EnumerateDetailedResultsFor(StringRef category, function_ref< void(StringRef, unsigned)> handleCounts)
LLVM_ABI void EnumerateResults(function_ref< void(StringRef, unsigned)> handleCounts)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
static LLVM_ABI raw_ostream & note()
Convenience method for printing "note: " to stderr.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
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.
LLVM_ABI StringRef AttributeString(unsigned Attribute)
LLVM_ABI StringRef FormEncodingString(unsigned Encoding)
LLVM_ABI StringRef UnitTypeString(unsigned)
LLVM_ABI StringRef TagString(unsigned Tag)
Calculates the starting offsets for various sections within the .debug_names section.
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)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
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)
LLVM_ABI std::optional< StringRef > StripTemplateParameters(StringRef Name)
If Name is the name of a templated function that includes template parameters, returns a substring of...
@ Success
The lock was released successfully.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI 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...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI 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 parallelForEach(IterTy Begin, IterTy End, FuncTy Fn)
@ End
Run the machine verifier once, at the end of the pipeline.
void consumeError(Error Err)
Consume a Error without doing anything.
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Implement std::hash so that hash_code can be used in STL containers.
std::map< std::string, unsigned > DetailedCounts
Container for dump options that control which debug information will be dumped.
unsigned ChildRecurseDepth
bool ShowErrorDetails
When verifying, print each error in detail.
DWARFFormValue Value
The form and value for this attribute.
dwarf::Attribute Attr
The attribute enumeration of this attribute.
static LLVM_ABI 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.
SmallVector< Encoding > Op
Encoding for Op operands.
A class that keeps the address range information for a single DIE.
std::vector< DWARFAddressRange > Ranges
Sorted DWARFAddressRanges.
LLVM_ABI 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
LLVM_ABI bool intersects(const DieRangeInfo &RHS) const
Return true if any range in this object intersects with any range in RHS.
std::set< DieRangeInfo > Children
Sorted DWARFAddressRangeInfo.
LLVM_ABI std::optional< DWARFAddressRange > insert(const DWARFAddressRange &R)
Inserts the address range.