55 for (
auto &Unit :
Dwarf.compile_units()) {
56 Size += Unit->getLength();
66 return LHS <
RHS->getOrigUnit().getNextUnitOffset();
68 return CU != Units.end() ?
CU->get() :
nullptr;
74DWARFDie DWARFLinker::resolveDIEReference(
const DWARFFile &File,
76 const DWARFFormValue &RefValue,
78 CompileUnit *&RefCU) {
81 if (std::optional<uint64_t>
Off = RefValue.getAsRelativeReference()) {
82 RefOffset = RefValue.getUnit()->getOffset() + *
Off;
83 }
else if (
Off = RefValue.getAsDebugInfoReference();
Off) {
86 reportWarning(
"Unsupported reference type", File, &DIE);
90 if (
const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
97 reportWarning(
"could not find referenced DIE", File, &DIE);
107 case dwarf::DW_AT_type:
108 case dwarf::DW_AT_containing_type:
109 case dwarf::DW_AT_specification:
110 case dwarf::DW_AT_abstract_origin:
111 case dwarf::DW_AT_import:
112 case dwarf::DW_AT_LLVM_alloc_type:
120 case dwarf::DW_TAG_array_type:
121 case dwarf::DW_TAG_class_type:
122 case dwarf::DW_TAG_enumeration_type:
123 case dwarf::DW_TAG_pointer_type:
124 case dwarf::DW_TAG_reference_type:
125 case dwarf::DW_TAG_string_type:
126 case dwarf::DW_TAG_structure_type:
127 case dwarf::DW_TAG_subroutine_type:
128 case dwarf::DW_TAG_template_alias:
129 case dwarf::DW_TAG_typedef:
130 case dwarf::DW_TAG_union_type:
131 case dwarf::DW_TAG_ptr_to_member_type:
132 case dwarf::DW_TAG_set_type:
133 case dwarf::DW_TAG_subrange_type:
134 case dwarf::DW_TAG_base_type:
135 case dwarf::DW_TAG_const_type:
136 case dwarf::DW_TAG_constant:
137 case dwarf::DW_TAG_file_type:
138 case dwarf::DW_TAG_namelist:
139 case dwarf::DW_TAG_packed_type:
140 case dwarf::DW_TAG_volatile_type:
141 case dwarf::DW_TAG_restrict_type:
142 case dwarf::DW_TAG_atomic_type:
143 case dwarf::DW_TAG_interface_type:
144 case dwarf::DW_TAG_unspecified_type:
145 case dwarf::DW_TAG_shared_type:
146 case dwarf::DW_TAG_immutable_type:
157DWARFLinker::DIECloner::getCanonicalDIEName(DWARFDie Die,
const DWARFFile &File,
162 std::optional<DWARFFormValue>
Ref;
164 auto GetDieName = [](
const DWARFDie &
D) -> llvm::StringRef {
165 auto NameForm =
D.find(llvm::dwarf::DW_AT_name);
169 auto NameOrErr = NameForm->getAsCString();
178 llvm::StringRef
Name = GetDieName(Die);
183 if (!(
Ref = Die.find(llvm::dwarf::DW_AT_specification)) &&
184 !(
Ref = Die.find(llvm::dwarf::DW_AT_abstract_origin)))
187 Die = Linker.resolveDIEReference(File, CompileUnits, *
Ref, Die, Unit);
193 unsigned SpecIdx =
Unit->getOrigUnit().getDIEIndex(Die);
194 CompileUnit::DIEInfo &SpecInfo =
Unit->getInfo(SpecIdx);
195 if (SpecInfo.Ctxt && SpecInfo.Ctxt->hasCanonicalDIE()) {
196 if (!SpecInfo.Ctxt->getCanonicalName().empty()) {
197 Name = SpecInfo.Ctxt->getCanonicalName();
202 Name = GetDieName(Die);
210bool DWARFLinker::DIECloner::getDIENames(
212 const DWARFFile &File, CompileUnit &Unit,
bool StripTemplate) {
216 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
222 if (!
Info.MangledName)
223 if (
const char *MangledName = Die.getLinkageName())
224 Info.MangledName = StringPool.getEntry(MangledName);
230 if (llvm::StringRef Name = getCanonicalDIEName(Die, File, &Unit);
232 Info.Name = StringPool.getEntry(Name);
234 if (!
Info.MangledName)
237 if (StripTemplate &&
Info.Name &&
Info.MangledName !=
Info.Name) {
238 StringRef
Name =
Info.Name.getString();
240 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
243 return Info.Name ||
Info.MangledName;
257 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
258 if (
CU.getLanguage() != dwarf::DW_LANG_Swift)
261 if (!ParseableSwiftInterfaces)
265 if (!Path.ends_with(
".swiftinterface"))
270 SysRoot =
CU.getSysRoot();
271 if (!SysRoot.
empty() && Path.starts_with(SysRoot))
276 if (!DeveloperDir.
empty() && Path.starts_with(DeveloperDir))
280 std::optional<const char *> Name =
284 auto &Entry = (*ParseableSwiftInterfaces)[*Name];
286 DWARFDie CUDie =
CU.getOrigUnit().getUnitDIE();
291 if (!Entry.empty() && Entry != ResolvedPath)
292 ReportWarning(
Twine(
"Conflicting parseable interfaces for Swift Module ") +
293 *Name +
": " + Entry +
" and " + Path,
295 Entry = std::string(ResolvedPath);
338 Info.Prune &= (Die.
getTag() == dwarf::DW_TAG_module) ||
344 if (ModulesEndOffset == 0)
345 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();
347 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 &&
348 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
356 Info.Prune &= ChildInfo.
Prune;
372 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
374 std::vector<ContextWorklistItem> Worklist;
375 Worklist.emplace_back(
DIE, CurrentDeclContext, ParentIdx,
false);
377 while (!Worklist.empty()) {
381 switch (Current.
Type) {
392 unsigned Idx =
CU.getOrigUnit().getDIEIndex(Current.
Die);
407 if (Current.
Die.
getTag() == dwarf::DW_TAG_module &&
410 CU.getClangModuleName()) {
418 if (
CU.hasODR() || Info.InModuleScope) {
422 Current.
Context = PtrInvalidPair.getPointer();
424 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
428 Info.Ctxt = Current.
Context =
nullptr;
437 Worklist.emplace_back(
439 Worklist.emplace_back(Child, Current.
Context, Idx,
449 case dwarf::DW_TAG_class_type:
450 case dwarf::DW_TAG_common_block:
451 case dwarf::DW_TAG_enumeration_type:
452 case dwarf::DW_TAG_lexical_block:
453 case dwarf::DW_TAG_structure_type:
454 case dwarf::DW_TAG_subprogram:
455 case dwarf::DW_TAG_subroutine_type:
456 case dwarf::DW_TAG_union_type:
462void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
465 for (DIEBlock *
I : DIEBlocks)
467 for (DIELoc *
I : DIELocs)
481 auto StmtAttrs = Unit.getStmtSeqListAttributes();
483 SortedOffsets.
reserve(StmtAttrs.size());
493std::pair<bool, std::optional<int64_t>>
494DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
495 const DWARFDie &DIE) {
496 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
497 DIE.getTag() == dwarf::DW_TAG_constant) &&
498 "Wrong type of input die");
500 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
503 DWARFUnit *U = DIE.getDwarfUnit();
504 std::optional<uint32_t> LocationIdx =
505 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
507 return std::make_pair(
false, std::nullopt);
511 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
514 std::optional<DWARFFormValue> LocationValue =
515 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
517 return std::make_pair(
false, std::nullopt);
522 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
524 return std::make_pair(
false, std::nullopt);
527 DataExtractor
Data(*Expr, U->getContext().isLittleEndian());
528 DWARFExpression Expression(
Data, U->getAddressByteSize(),
529 U->getFormParams().Format);
531 bool HasLocationAddress =
false;
533 for (DWARFExpression::iterator It = Expression.begin();
534 It != Expression.end(); ++It) {
535 DWARFExpression::iterator NextIt = It;
538 const DWARFExpression::Operation &
Op = *It;
540 case dwarf::DW_OP_const2u:
541 case dwarf::DW_OP_const4u:
542 case dwarf::DW_OP_const8u:
543 case dwarf::DW_OP_const2s:
544 case dwarf::DW_OP_const4s:
545 case dwarf::DW_OP_const8s:
546 if (NextIt == Expression.end() ||
550 case dwarf::DW_OP_addr: {
551 HasLocationAddress =
true;
553 if (std::optional<int64_t> RelocAdjustment =
554 RelocMgr.getExprOpAddressRelocAdjustment(
555 *U,
Op, AttrOffset + CurExprOffset,
557 return std::make_pair(HasLocationAddress, *RelocAdjustment);
559 case dwarf::DW_OP_constx:
560 case dwarf::DW_OP_addrx: {
561 HasLocationAddress =
true;
562 if (std::optional<uint64_t> AddressOffset =
563 DIE.getDwarfUnit()->getIndexedAddressOffset(
566 if (std::optional<int64_t> RelocAdjustment =
567 RelocMgr.getExprOpAddressRelocAdjustment(
568 *U,
Op, *AddressOffset,
569 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
571 return std::make_pair(HasLocationAddress, *RelocAdjustment);
581 return std::make_pair(HasLocationAddress, std::nullopt);
586unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
588 CompileUnit::DIEInfo &MyInfo,
590 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
593 if (!(Flags & TF_InFunctionScope) &&
594 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
595 MyInfo.InDebugMap =
true;
596 return Flags | TF_Keep;
604 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
605 getVariableRelocAdjustment(RelocMgr, DIE);
607 if (LocExprAddrAndRelocAdjustment.first)
608 MyInfo.HasLocationExpressionAddr =
true;
610 if (!LocExprAddrAndRelocAdjustment.second)
613 MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second;
614 MyInfo.InDebugMap =
true;
616 if (((Flags & TF_InFunctionScope) &&
620 if (Options.Verbose) {
621 outs() <<
"Keeping variable DIE:";
622 DIDumpOptions DumpOpts;
623 DumpOpts.ChildRecurseDepth = 0;
624 DumpOpts.Verbose = Options.Verbose;
625 DIE.dump(
outs(), 8 , DumpOpts);
628 return Flags | TF_Keep;
633unsigned DWARFLinker::shouldKeepSubprogramDIE(
634 AddressesMap &RelocMgr,
const DWARFDie &DIE,
const DWARFFile &File,
635 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
636 Flags |= TF_InFunctionScope;
642 assert(LowPc &&
"low_pc attribute is not an address.");
643 std::optional<int64_t> RelocAdjustment =
644 RelocMgr.getSubprogramRelocAdjustment(DIE, Options.Verbose);
645 if (!RelocAdjustment)
648 MyInfo.AddrAdjust = *RelocAdjustment;
649 MyInfo.InDebugMap =
true;
651 if (Options.Verbose) {
652 outs() <<
"Keeping subprogram DIE:";
653 DIDumpOptions DumpOpts;
654 DumpOpts.ChildRecurseDepth = 0;
655 DumpOpts.Verbose = Options.Verbose;
656 DIE.dump(
outs(), 8 , DumpOpts);
659 if (DIE.getTag() == dwarf::DW_TAG_label) {
660 if (
Unit.hasLabelAt(*LowPc))
663 DWARFUnit &OrigUnit =
Unit.getOrigUnit();
673 if (
Unit.getLanguage() == dwarf::DW_LANG_Mips_Assembler ||
674 Unit.getLanguage() == dwarf::DW_LANG_Assembly) {
675 if (
auto Range = RelocMgr.getSymbolRangeForAddress(*LowPc)) {
676 Unit.addFunctionRange(
Range->LowPC,
Range->HighPC, MyInfo.AddrAdjust);
678 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
681 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
683 return Flags | TF_Keep;
688 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
690 reportWarning(
"Function without high_pc. Range will be discarded.\n", File,
694 if (*LowPc > *HighPc) {
695 reportWarning(
"low_pc greater than high_pc. Range will be discarded.\n",
701 Unit.addFunctionRange(
703 RelocMgr.constrainCodeRangeHighPC(*LowPc, *HighPc, MyInfo.AddrAdjust),
710unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr,
const DWARFDie &DIE,
711 const DWARFFile &File, CompileUnit &Unit,
712 CompileUnit::DIEInfo &MyInfo,
714 switch (DIE.getTag()) {
715 case dwarf::DW_TAG_constant:
716 case dwarf::DW_TAG_variable:
717 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
718 case dwarf::DW_TAG_subprogram:
719 case dwarf::DW_TAG_label:
720 return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags);
721 case dwarf::DW_TAG_base_type:
724 case dwarf::DW_TAG_imported_module:
725 case dwarf::DW_TAG_imported_declaration:
726 case dwarf::DW_TAG_imported_unit:
728 return Flags | TF_Keep;
742 case dwarf::DW_TAG_structure_type:
743 case dwarf::DW_TAG_class_type:
744 case dwarf::DW_TAG_union_type:
762 case dwarf::DW_TAG_typedef:
763 case dwarf::DW_TAG_member:
764 case dwarf::DW_TAG_reference_type:
765 case dwarf::DW_TAG_ptr_to_member_type:
766 case dwarf::DW_TAG_pointer_type:
783void DWARFLinker::lookForChildDIEsToKeep(
784 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
785 SmallVectorImpl<WorklistItem> &Worklist) {
792 Flags &= ~DWARFLinker::TF_ParentWalk;
796 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
801 for (
auto Child :
reverse(Die.children())) {
804 CompileUnit::DIEInfo &ChildInfo =
CU.getInfo(Child);
805 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateChildIncompleteness,
807 Worklist.emplace_back(Child,
CU, Flags);
814 if (!Info.Ctxt || (Die.
getTag() == dwarf::DW_TAG_namespace))
817 if (!
CU.hasODR() && !Info.InModuleScope)
820 return !Info.Incomplete && Info.Ctxt !=
CU.getInfo(Info.ParentIdx).Ctxt;
823void DWARFLinker::markODRCanonicalDie(
const DWARFDie &Die, CompileUnit &
CU) {
824 CompileUnit::DIEInfo &Info =
CU.getInfo(Die);
826 Info.ODRMarkingDone =
true;
828 !Info.Ctxt->hasCanonicalDIE())
829 Info.Ctxt->setHasCanonicalDIE();
834void DWARFLinker::lookForRefDIEsToKeep(
835 const DWARFDie &Die, CompileUnit &CU,
unsigned Flags,
836 const UnitListTy &Units,
const DWARFFile &File,
837 SmallVectorImpl<WorklistItem> &Worklist) {
838 bool UseOdr = (
Flags & DWARFLinker::TF_DependencyWalk)
839 ? (Flags & DWARFLinker::TF_ODR)
841 DWARFUnit &
Unit = CU.getOrigUnit();
842 DWARFDataExtractor
Data =
Unit.getDebugInfoExtractor();
843 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
847 for (
const auto &AttrSpec : Abbrev->attributes()) {
848 DWARFFormValue Val(AttrSpec.Form);
850 AttrSpec.Attr == dwarf::DW_AT_sibling) {
852 Unit.getFormParams());
857 CompileUnit *ReferencedCU;
859 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
860 CompileUnit::DIEInfo &
Info = ReferencedCU->getInfo(RefDie);
871 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
873 Info.Ctxt->hasCanonicalDIE())
878 Info.Ctxt->hasCanonicalDIE()))
880 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
884 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
888 for (
auto &
P :
reverse(ReferencedDIEs)) {
891 CompileUnit::DIEInfo &
Info =
P.second.getInfo(
P.first);
892 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness,
894 Worklist.emplace_back(
P.first,
P.second,
895 DWARFLinker::TF_Keep |
896 DWARFLinker::TF_DependencyWalk | ODRFlag);
901void DWARFLinker::lookForParentDIEsToKeep(
902 unsigned AncestorIdx, CompileUnit &CU,
unsigned Flags,
903 SmallVectorImpl<WorklistItem> &Worklist) {
905 if (CU.getInfo(AncestorIdx).Keep)
908 DWARFUnit &
Unit = CU.getOrigUnit();
909 DWARFDie ParentDIE =
Unit.getDIEAtIndex(AncestorIdx);
910 Worklist.emplace_back(CU.getInfo(AncestorIdx).ParentIdx, CU, Flags);
911 Worklist.emplace_back(ParentDIE, CU, Flags);
939void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
941 const DWARFDie &Die,
const DWARFFile &File,
942 CompileUnit &Cu,
unsigned Flags) {
945 Worklist.emplace_back(Die, Cu, Flags);
947 while (!Worklist.empty()) {
948 WorklistItem Current = Worklist.pop_back_val();
951 switch (Current.Type) {
952 case WorklistItemType::UpdateChildIncompleteness:
955 case WorklistItemType::UpdateRefIncompleteness:
958 case WorklistItemType::LookForChildDIEsToKeep:
959 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
961 case WorklistItemType::LookForRefDIEsToKeep:
962 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
965 case WorklistItemType::LookForParentDIEsToKeep:
966 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
969 case WorklistItemType::MarkODRCanonicalDie:
970 markODRCanonicalDie(Current.Die, Current.CU);
972 case WorklistItemType::LookForDIEsToKeep:
976 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
977 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx);
982 if (Current.Flags & TF_DependencyWalk)
983 MyInfo.Prune =
false;
990 bool AlreadyKept = MyInfo.Keep;
991 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
994 if (!(Current.Flags & TF_DependencyWalk))
995 Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU,
996 MyInfo, Current.Flags);
1001 if (!(Current.Flags & TF_DependencyWalk) ||
1002 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
1003 if (Current.CU.hasODR() || MyInfo.InModuleScope)
1004 Worklist.emplace_back(Current.Die, Current.CU,
1005 WorklistItemType::MarkODRCanonicalDie);
1011 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1012 WorklistItemType::LookForChildDIEsToKeep);
1014 if (AlreadyKept || !(Current.Flags & TF_Keep))
1023 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
1024 Current.Die.getTag() != dwarf::DW_TAG_member &&
1030 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1031 WorklistItemType::LookForRefDIEsToKeep);
1033 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
1034 : Current.CU.hasODR();
1035 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
1036 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
1039 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
1055 std::vector<DWARFDie> Worklist;
1056 Worklist.push_back(
CU.getOrigUnit().getUnitDIE());
1059 std::vector<BrokenLink> BrokenLinks;
1061 while (!Worklist.empty()) {
1062 const DWARFDie Current = Worklist.back();
1063 Worklist.pop_back();
1065 const bool CurrentDieIsKept =
CU.getInfo(Current).Keep;
1068 Worklist.push_back(Child);
1070 const bool ChildDieIsKept =
CU.getInfo(Child).Keep;
1071 if (!CurrentDieIsKept && ChildDieIsKept)
1072 BrokenLinks.emplace_back(Current, Child);
1076 if (!BrokenLinks.empty()) {
1079 "Found invalid link in keep chain between {0:x} and {1:x}\n",
1080 Link.Parent.getOffset(), Link.Child.getOffset());
1082 errs() <<
"Parent:";
1083 Link.Parent.dump(
errs(), 0, {});
1084 CU.getInfo(Link.Parent).dump();
1087 Link.Child.dump(
errs(), 2, {});
1088 CU.getInfo(Link.Child).dump();
1101void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
1103 FoldingSetNodeID ID;
1105 FoldingSetInsertToken Token;
1106 DIEAbbrev *InSet = AbbreviationsSet.lookup(ID, Token);
1111 Abbrev.setNumber(InSet->getNumber());
1114 Abbreviations.push_back(
1115 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
1116 for (
const auto &Attr : Abbrev.getData())
1117 Abbreviations.back()->AddAttribute(Attr);
1118 AbbreviationsSet.insert(Abbreviations.back().get(), Token);
1120 Abbrev.setNumber(Abbreviations.size());
1121 Abbreviations.back()->setNumber(Abbreviations.size());
1125unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
1126 AttributeSpec AttrSpec,
1127 const DWARFFormValue &Val,
1129 AttributesInfo &Info) {
1134 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
1139 if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
1140 Info.HasAppleOrigin =
true;
1141 if (std::optional<StringRef> FileName =
1142 ObjFile.Addresses->getLibraryInstallName()) {
1148 if (AttrSpec.Attr == dwarf::DW_AT_name)
1150 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
1151 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
1153 if (
U.getVersion() >= 5) {
1155 auto StringOffsetIndex =
1156 StringOffsetPool.getValueIndex(
StringEntry.getOffset());
1159 dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
1160 ->sizeOf(
U.getFormParams());
1163 AttrSpec.Form = dwarf::DW_FORM_strp;
1170unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
1171 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1172 unsigned AttrSize,
const DWARFFormValue &Val,
const DWARFFile &File,
1173 CompileUnit &Unit) {
1174 const DWARFUnit &
U =
Unit.getOrigUnit();
1176 if (std::optional<uint64_t>
Off = Val.getAsRelativeReference())
1177 Ref = Val.getUnit()->getOffset() + *
Off;
1178 else if (
Off = Val.getAsDebugInfoReference();
Off)
1183 DIE *NewRefDie =
nullptr;
1184 CompileUnit *RefUnit =
nullptr;
1187 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
1190 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
1193 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
1198 RefInfo.Ctxt->getCanonicalDIEOffset()) {
1199 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
1200 "Offset to canonical die is set, but context is not marked");
1201 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
1203 dwarf::DW_FORM_ref_addr, Attr);
1204 return U.getRefAddrByteSize();
1207 if (!RefInfo.Clone) {
1210 RefInfo.UnclonedReference =
true;
1213 NewRefDie = RefInfo.Clone;
1215 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1217 if (
Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1222 dwarf::DW_FORM_ref_addr, DIEEntry(*NewRefDie));
1228 Unit.noteForwardReference(
1229 NewRefDie, RefUnit, RefInfo.Ctxt,
1231 dwarf::DW_FORM_ref_addr, DIEInteger(
UINT64_MAX)));
1233 return U.getRefAddrByteSize();
1237 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1242void DWARFLinker::DIECloner::cloneExpression(
1243 DataExtractor &
Data, DWARFExpression Expression,
const DWARFFile &File,
1244 CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer,
1245 int64_t AddrRelocAdjustment,
bool IsLittleEndian) {
1248 uint8_t OrigAddressByteSize =
Unit.getOrigUnit().getAddressByteSize();
1251 for (
auto &
Op : Expression) {
1258 "cannot decode a DW_OP, copying the rest of the expression "
1261 StringRef Bytes =
Data.getData().substr(OpOffset);
1262 OutputBuffer.append(Bytes.begin(), Bytes.end());
1270 Desc.
Op[0] != Encoding::Size1))
1271 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
1275 Desc.
Op[0] == Encoding::Size1)) {
1295 if (RefOffset > 0 ||
Op.
getCode() != dwarf::DW_OP_convert) {
1296 RefOffset +=
Unit.getOrigUnit().getOffset();
1297 auto RefDie =
Unit.getOrigUnit().getDIEForOffset(RefOffset);
1298 CompileUnit::DIEInfo &
Info =
Unit.getInfo(RefDie);
1299 if (DIE *Clone =
Info.Clone)
1300 Offset = Clone->getOffset();
1303 "base type ref doesn't point to DW_TAG_base_type.", File);
1307 if (RealSize > ULEBsize) {
1310 Linker.reportWarning(
"base type ref doesn't fit.", File);
1312 assert(RealSize == ULEBsize &&
"padding failed");
1313 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1314 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1315 }
else if (!
Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_addrx) {
1316 if (std::optional<object::SectionedAddress> SA =
1317 Unit.getOrigUnit().getAddrOffsetSectionItem(
1323 OutputBuffer.push_back(dwarf::DW_OP_addr);
1327 ->getAddrIndexRelocAdjustment(
Unit.getOrigUnit(),
Op,
1329 .value_or(AddrRelocAdjustment);
1332 ArrayRef<uint8_t> AddressBytes(
1333 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1334 OrigAddressByteSize);
1335 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1337 Linker.reportWarning(
"cannot read DW_OP_addrx operand.", File);
1338 }
else if (!
Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_constx) {
1339 if (std::optional<object::SectionedAddress> SA =
1340 Unit.getOrigUnit().getAddrOffsetSectionItem(
1346 std::optional<uint8_t> OutOperandKind;
1347 switch (OrigAddressByteSize) {
1349 OutOperandKind = dwarf::DW_OP_const4u;
1352 OutOperandKind = dwarf::DW_OP_const8u;
1356 formatv((
"unsupported address size: {0}."), OrigAddressByteSize),
1361 if (OutOperandKind) {
1362 OutputBuffer.push_back(*OutOperandKind);
1366 ->getAddrIndexRelocAdjustment(
Unit.getOrigUnit(),
Op,
1368 .value_or(AddrRelocAdjustment);
1371 ArrayRef<uint8_t> AddressBytes(
1372 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1373 OrigAddressByteSize);
1374 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1377 Linker.reportWarning(
"cannot read DW_OP_constx operand.", File);
1381 OutputBuffer.append(Bytes.begin(), Bytes.end());
1387unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1388 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1389 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1390 bool IsLittleEndian) {
1393 DIELoc *Loc =
nullptr;
1394 DIEBlock *
Block =
nullptr;
1395 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1396 Loc =
new (DIEAlloc) DIELoc;
1397 Linker.DIELocs.push_back(Loc);
1399 Block =
new (DIEAlloc) DIEBlock;
1402 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1403 : static_cast<DIEValueList *>(
Block);
1405 DWARFUnit &OrigUnit =
Unit.getOrigUnit();
1408 SmallVector<uint8_t, 32> Buffer;
1409 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1413 DataExtractor Data(Bytes, IsLittleEndian);
1414 DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
1415 OrigUnit.getFormParams().Format);
1416 cloneExpression(Data, Expr, File, Unit, Buffer,
1417 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);
1420 for (
auto Byte : Bytes)
1422 dwarf::DW_FORM_data1, DIEInteger(Byte));
1428 Loc->setSize(Bytes.size());
1430 Block->setSize(Bytes.size());
1438 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&
1439 (Bytes.size() > UINT8_MAX)) ||
1440 (AttrSpec.Form == dwarf::DW_FORM_block2 &&
1441 (Bytes.size() > UINT16_MAX)) ||
1442 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))
1443 AttrSpec.Form = dwarf::DW_FORM_block;
1445 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
1446 dwarf::Form(AttrSpec.Form), Block);
1449 return Die.addValue(DIEAlloc,
Value)->sizeOf(OrigUnit.getFormParams());
1460 bool IsLength, int64_t PCOffset,
1462 std::optional<uint64_t> LowPC =
1467 *LowPC, IsLength ? *LowPC + HighPC : HighPC, PCOffset);
1468 return IsLength ? Constrained - *LowPC : Constrained;
1471unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1472 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1473 unsigned AttrSize,
const DWARFFormValue &Val,
const CompileUnit &Unit,
1474 AttributesInfo &Info) {
1475 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1476 Info.HasLowPc =
true;
1480 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1496 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1500 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
1502 Linker.reportWarning(
"Cann't read address attribute value.", ObjFile);
1506 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1507 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1508 if (std::optional<uint64_t> LowPC =
Unit.getLowPc())
1512 }
else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1513 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1519 if (AttrSpec.Attr == dwarf::DW_AT_high_pc)
1521 *ObjFile.Addresses);
1522 *Addr +=
Info.PCOffset;
1525 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
1527 AttrSpec.Form, DIEInteger(*Addr));
1528 return Unit.getOrigUnit().getAddressByteSize();
1531 auto AddrIndex = AddrPool.getValueIndex(*Addr);
1535 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))
1536 ->sizeOf(
Unit.getOrigUnit().getFormParams());
1539unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1540 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1541 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1542 unsigned AttrSize, AttributesInfo &Info) {
1547 if (AttrSpec.Attr == dwarf::DW_AT_GNU_dwo_id ||
1548 AttrSpec.Attr == dwarf::DW_AT_dwo_id)
1553 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1554 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1555 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacinfo();
1561 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1562 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1563 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacro();
1569 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1573 Info.AttrStrOffsetBaseSeen =
true;
1575 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1576 dwarf::DW_FORM_sec_offset, DIEInteger(8))
1577 ->sizeOf(
Unit.getOrigUnit().getFormParams());
1580 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
1583 dwarf::DW_FORM_sec_offset,
1584 DIEInteger(*Val.getAsSectionOffset()));
1587 Unit.noteStmtSeqListAttribute(Patch);
1589 return Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1593 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1594 Value = *OptionalValue;
1595 else if (
auto OptionalValue = Val.getAsSignedConstant())
1596 Value = *OptionalValue;
1597 else if (
auto OptionalValue = Val.getAsSectionOffset())
1598 Value = *OptionalValue;
1601 "Unsupported scalar attribute form. Dropping attribute.", File,
1605 if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1606 Info.IsDeclaration =
true;
1608 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1617 [[maybe_unused]]
dwarf::Form OriginalForm = AttrSpec.Form;
1618 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1622 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1624 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1628 std::optional<uint64_t>
Offset =
1629 Unit.getOrigUnit().getRnglistOffset(*Index);
1631 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1637 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1638 AttrSize =
Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1639 }
else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1643 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1645 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1649 std::optional<uint64_t>
Offset =
1650 Unit.getOrigUnit().getLoclistOffset(*Index);
1652 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1658 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1659 AttrSize =
Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1660 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1661 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1662 std::optional<uint64_t> LowPC =
Unit.getLowPc();
1667 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1668 Value = *Val.getAsSectionOffset();
1669 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1670 Value = *Val.getAsSignedConstant();
1671 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1672 Value = *OptionalValue;
1675 "Unsupported scalar attribute form. Dropping attribute.", File,
1682 if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1683 Die.getTag() != dwarf::DW_TAG_compile_unit)
1687 DIE::value_iterator Patch =
1690 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1691 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1692 Unit.noteRangeAttribute(Die, Patch);
1693 Info.HasRanges =
true;
1697 Unit.getOrigUnit().getVersion())) {
1699 CompileUnit::DIEInfo &LocationDieInfo =
Unit.getInfo(InputDIE);
1700 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
1701 ? LocationDieInfo.AddrAdjust
1703 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1704 Info.IsDeclaration =
true;
1707 assert((
Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1708 "Unhandled DW_FORM_rnglistx attribute");
1716unsigned DWARFLinker::DIECloner::cloneAttribute(
1717 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1718 CompileUnit &Unit,
const DWARFFormValue &Val,
const AttributeSpec AttrSpec,
1719 unsigned AttrSize, AttributesInfo &Info,
bool IsLittleEndian) {
1720 const DWARFUnit &
U =
Unit.getOrigUnit();
1722 switch (AttrSpec.Form) {
1723 case dwarf::DW_FORM_strp:
1724 case dwarf::DW_FORM_line_strp:
1725 case dwarf::DW_FORM_string:
1726 case dwarf::DW_FORM_strx:
1727 case dwarf::DW_FORM_strx1:
1728 case dwarf::DW_FORM_strx2:
1729 case dwarf::DW_FORM_strx3:
1730 case dwarf::DW_FORM_strx4:
1731 return cloneStringAttribute(Die, AttrSpec, Val, U, Info);
1732 case dwarf::DW_FORM_ref_addr:
1733 case dwarf::DW_FORM_ref1:
1734 case dwarf::DW_FORM_ref2:
1735 case dwarf::DW_FORM_ref4:
1736 case dwarf::DW_FORM_ref8:
1737 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1739 case dwarf::DW_FORM_block:
1740 case dwarf::DW_FORM_block1:
1741 case dwarf::DW_FORM_block2:
1742 case dwarf::DW_FORM_block4:
1743 case dwarf::DW_FORM_exprloc:
1744 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1746 case dwarf::DW_FORM_addr:
1747 case dwarf::DW_FORM_addrx:
1748 case dwarf::DW_FORM_addrx1:
1749 case dwarf::DW_FORM_addrx2:
1750 case dwarf::DW_FORM_addrx3:
1751 case dwarf::DW_FORM_addrx4:
1752 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1754 case dwarf::DW_FORM_data1:
1755 case dwarf::DW_FORM_data2:
1756 case dwarf::DW_FORM_data4:
1757 case dwarf::DW_FORM_data8:
1758 case dwarf::DW_FORM_udata:
1759 case dwarf::DW_FORM_sdata:
1760 case dwarf::DW_FORM_sec_offset:
1761 case dwarf::DW_FORM_flag:
1762 case dwarf::DW_FORM_flag_present:
1763 case dwarf::DW_FORM_rnglistx:
1764 case dwarf::DW_FORM_loclistx:
1765 case dwarf::DW_FORM_implicit_const:
1766 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1769 Linker.reportWarning(
"Unsupported attribute form " +
1771 " in cloneAttribute. Dropping.",
1778void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1780 DwarfStringPoolEntryRef Name,
1782 bool SkipPubSection) {
1783 std::optional<ObjCSelectorNames> Names =
1787 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),
1789 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),
1791 if (Names->ClassNameNoCategory)
1792 Unit.addObjCAccelerator(
1793 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);
1794 if (Names->MethodNameNoCategory)
1795 Unit.addNameAccelerator(
1796 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);
1803 switch (AttrSpec.
Attr) {
1806 case dwarf::DW_AT_low_pc:
1807 case dwarf::DW_AT_high_pc:
1808 case dwarf::DW_AT_ranges:
1809 return !Update && SkipPC;
1810 case dwarf::DW_AT_rnglists_base:
1816 case dwarf::DW_AT_loclists_base:
1822 case dwarf::DW_AT_location:
1823 case dwarf::DW_AT_frame_base:
1824 return !Update && SkipPC;
1834DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1836 int64_t PCOffset,
uint32_t OutOffset,
1837 unsigned Flags,
bool IsLittleEndian,
1840 unsigned Idx = U.getDIEIndex(InputDIE);
1844 if (!Unit.getInfo(Idx).Keep)
1848 assert(!(Die && Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1860 (Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1861 if (!Info.Ctxt->hasCanonicalDIE())
1862 Info.Ctxt->setHasCanonicalDIE();
1866 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1870 DWARFDataExtractor
Data =
U.getDebugInfoExtractor();
1874 uint64_t NextOffset = (Idx + 1 <
U.getNumDIEs())
1875 ?
U.getDIEAtIndex(Idx + 1).getOffset()
1876 :
U.getNextUnitOffset();
1877 AttributesInfo AttrInfo;
1882 SmallString<40> DIECopy(
Data.getData().substr(
Offset, NextOffset -
Offset));
1884 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1887 ObjFile.Addresses->applyValidRelocs(DIECopy,
Offset,
Data.isLittleEndian());
1897 if (Die->
getTag() == dwarf::DW_TAG_subprogram)
1898 PCOffset =
Info.AddrAdjust;
1899 AttrInfo.PCOffset = PCOffset;
1901 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1902 Flags |= TF_InFunctionScope;
1904 if (
Info.InDebugMap)
1905 Flags &= ~TF_SkipPC;
1909 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1912 if ((Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1913 Flags &= ~TF_SkipPC;
1916 else if (!
Info.InDebugMap &&
Info.HasLocationExpressionAddr &&
1921 std::optional<StringRef> LibraryInstallName =
1922 ObjFile.Addresses->getLibraryInstallName();
1924 for (
const auto &AttrSpec : Abbrev->attributes()) {
1931 AttributeLinkedOffsetFixup CurAttrFixup;
1933 CurAttrFixup.LinkedOffsetFixupVal =
1934 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1936 DWARFFormValue Val = AttrSpec.getFormValue();
1938 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1940 AttrSize =
Offset - AttrSize;
1943 cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
1944 AttrInfo, IsLittleEndian);
1945 if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
1946 AttributesFixups.push_back(CurAttrFixup);
1948 OutOffset += FinalAttrSize;
1954 const bool NeedsAppleOrigin = (
Tag == dwarf::DW_TAG_compile_unit) &&
1955 LibraryInstallName.has_value() &&
1956 !AttrInfo.HasAppleOrigin;
1957 if (NeedsAppleOrigin) {
1958 auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
1960 dwarf::DW_FORM_strp, DIEInteger(
StringEntry.getOffset()));
1969 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1970 Tag != dwarf::DW_TAG_compile_unit &&
1971 !(
Tag == dwarf::DW_TAG_variable &&
1973 getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit,
1974 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1975 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1976 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1977 Tag == dwarf::DW_TAG_inlined_subroutine);
1978 if (AttrInfo.Name) {
1979 if (AttrInfo.NameWithoutTemplate)
1980 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1982 Unit.addNameAccelerator(Die, AttrInfo.Name,
1983 Tag == dwarf::DW_TAG_inlined_subroutine);
1986 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,
1989 }
else if (
Tag == dwarf::DW_TAG_namespace) {
1991 AttrInfo.Name = DebugStrPool.getEntry(
"(anonymous namespace)");
1992 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1993 }
else if (
Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1994 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1995 }
else if (
isTypeTag(
Tag) && !AttrInfo.IsDeclaration) {
1996 bool Success = getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit);
2000 bool ObjCClassIsImplementation =
2001 (RuntimeLang == dwarf::DW_LANG_ObjC ||
2002 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
2005 if (
Success && AttrInfo.Name && !AttrInfo.Name.getString().empty()) {
2007 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
2012 if (
Success && AttrInfo.MangledName &&
2013 RuntimeLang == dwarf::DW_LANG_Swift &&
2014 !AttrInfo.MangledName.getString().empty() &&
2015 AttrInfo.MangledName != AttrInfo.Name) {
2016 auto Hash =
djbHash(AttrInfo.MangledName.getString().data());
2017 Unit.addTypeAccelerator(Die, AttrInfo.MangledName,
2018 ObjCClassIsImplementation, Hash);
2023 bool HasChildren =
false;
2024 for (
auto Child : InputDIE.
children()) {
2025 unsigned Idx =
U.getDIEIndex(Child);
2026 if (
Unit.getInfo(Idx).Keep) {
2032 if (
Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
2033 Die->
getTag() == dwarf::DW_TAG_compile_unit) {
2035 Die->
addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
2036 dwarf::DW_FORM_sec_offset, DIEInteger(8));
2044 Linker.assignAbbrev(NewAbbrev);
2050 OutOffset += AbbrevNumberSize;
2053 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2054 F.LinkedOffsetFixupVal += AbbrevNumberSize;
2056 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2057 ObjFile.Addresses->updateAndSaveValidRelocs(
2058 Unit.getOrigUnit().getVersion() >= 5,
Unit.getOrigUnit().getOffset(),
2059 F.LinkedOffsetFixupVal,
F.InputAttrStartOffset,
F.InputAttrEndOffset);
2068 for (
auto Child : InputDIE.
children()) {
2069 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
2072 OutOffset = Clone->getOffset() + Clone->getSize();
2077 OutOffset +=
sizeof(int8_t);
2086Error DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File,
2091 const auto &FunctionRanges =
Unit.getFunctionRanges();
2094 AddressRanges LinkedFunctionRanges;
2095 for (
const AddressRangeValuePair &
Range : FunctionRanges)
2096 LinkedFunctionRanges.insert(
2100 if (!LinkedFunctionRanges.empty())
2101 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
2104 std::optional<PatchLocation> UnitRngListAttribute =
2105 Unit.getUnitRangesAttribute();
2107 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
2108 std::optional<AddressRangeValuePair> CachedRange;
2109 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
2113 for (PatchLocation &AttributePatch : AllRngListAttributes) {
2116 AddressRanges LinkedRanges;
2117 if (Expected<DWARFAddressRangesVector> OriginalRanges =
2118 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
2120 for (
const auto &
Range : *OriginalRanges) {
2121 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
2122 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
2126 reportWarning(
"inconsistent range data.", File);
2131 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
2132 Range.HighPC + CachedRange->Value});
2136 reportWarning(
"invalid range list ignored.", File);
2140 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2141 Unit, LinkedRanges, AttributePatch, AddrPool))
2146 if (UnitRngListAttribute.has_value())
2147 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2148 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool))
2152 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
2158Error DWARFLinker::DIECloner::generateUnitLocations(
2159 CompileUnit &Unit,
const DWARFFile &File,
2160 ExpressionHandlerRef ExprHandler) {
2165 Unit.getLocationAttributes();
2167 if (AllLocListAttributes.empty())
2173 for (
auto &CurLocAttr : AllLocListAttributes) {
2176 Expected<DWARFLocationExpressionsVector> OriginalLocations =
2177 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
2179 if (!OriginalLocations) {
2181 Linker.reportWarning(
"Invalid location attribute ignored.", File);
2186 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
2187 DWARFLocationExpression LinkedExpression;
2189 if (CurExpression.Range) {
2191 LinkedExpression.Range = {
2192 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
2193 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
2197 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
2198 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
2199 CurLocAttr.RelocAdjustment);
2201 LinkedLocationExpressions.push_back(LinkedExpression);
2206 Unit, LinkedLocationExpressions, CurLocAttr, AddrPool))
2211 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
2217 for (
auto &V : Die.
values())
2218 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
2226Error DWARFLinker::DIECloner::emitDebugAddrSection(
2227 CompileUnit &Unit,
const uint16_t DwarfVersion)
const {
2232 if (DwarfVersion < 5)
2235 if (AddrPool.getValues().empty())
2238 MCSymbol *EndLabel =
Emitter->emitDwarfDebugAddrsHeader(Unit);
2240 dwarf::FormParams
FP = Unit.getOrigUnit().getFormParams();
2241 if (AddrOffset >
FP.getDwarfMaxOffset())
2245 patchAddrBase(*Unit.getOutputUnitDIE(), DIEInteger(AddrOffset));
2246 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),
2247 Unit.getOrigUnit().getAddressByteSize());
2248 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
2266 std::vector<TrackedRow> &Rows) {
2272 Seq.front().isStartSeqInOutput =
true;
2274 if (!Rows.empty() && Rows.back().Row.Address < Seq.front().Row.Address) {
2282 Rows, [=](
const TrackedRow &O) {
return O.Row.Address < Front; });
2291 Rows.insert(
InsertPoint + 1, Seq.begin() + 1, Seq.end());
2300 for (
auto &V : Die.
values())
2301 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2309void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2310 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2311 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2313 if (std::optional<uint64_t> MacroAttr =
2315 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2319 if (std::optional<uint64_t> MacroAttr =
2321 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2326Error DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2331 DWARFDie CUDie =
Unit.getOrigUnit().getUnitDIE();
2337 if (
auto *OutputDIE =
Unit.getOutputUnitDIE()) {
2339 dwarf::FormParams
FP =
Unit.getOrigUnit().getFormParams();
2340 if (StmtOffset >
FP.getDwarfMaxOffset())
2347 if (
const DWARFDebugLine::LineTable *LT =
2348 ObjFile.Dwarf->getLineTableForUnit(&
Unit.getOrigUnit())) {
2350 DWARFDebugLine::LineTable LineTable;
2353 LineTable.Prologue =
LT->Prologue;
2356 if (
Linker.Options.Update) {
2357 LineTable.Rows =
LT->Rows;
2360 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2361 LineTable.Rows.clear();
2363 LineTable.Sequences =
LT->Sequences;
2365 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2369 std::vector<TrackedRow> InputRows;
2370 InputRows.reserve(
LT->Rows.size());
2371 for (
size_t i = 0; i <
LT->Rows.size(); i++)
2372 InputRows.emplace_back(TrackedRow{LT->Rows[i], i, false});
2375 std::vector<TrackedRow> OutputRows;
2376 OutputRows.reserve(InputRows.size());
2380 std::vector<TrackedRow> Seq;
2381 Seq.reserve(InputRows.size());
2383 const auto &FunctionRanges =
Unit.getFunctionRanges();
2384 std::optional<AddressRangeValuePair> CurrRange;
2397 for (
size_t i = 0; i < InputRows.size(); i++) {
2398 TrackedRow
TR = InputRows[i];
2405 if (!CurrRange || !CurrRange->Range.contains(
TR.Row.Address.Address)) {
2409 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2411 FunctionRanges.getRangeThatContains(
TR.Row.Address.Address);
2412 if (StopAddress != -1ULL && !Seq.empty()) {
2415 auto NextLine = Seq.back();
2416 NextLine.Row.Address.Address = StopAddress;
2417 NextLine.Row.EndSequence = 1;
2418 NextLine.Row.PrologueEnd = 0;
2419 NextLine.Row.BasicBlock = 0;
2420 NextLine.Row.EpilogueBegin = 0;
2421 Seq.push_back(NextLine);
2430 if (
TR.Row.EndSequence && Seq.empty())
2434 TR.Row.Address.Address += CurrRange->Value;
2437 if (
TR.Row.EndSequence)
2448 if (!OutputRows.empty()) {
2449 OutputRows[0].isStartSeqInOutput =
true;
2450 for (
size_t i = 1; i < OutputRows.size(); ++i)
2451 OutputRows[i].isStartSeqInOutput = OutputRows[i - 1].Row.EndSequence;
2455 LineTable.Rows.clear();
2456 LineTable.Rows.reserve(OutputRows.size());
2457 for (
auto &TR : OutputRows)
2458 LineTable.Rows.push_back(
TR.Row);
2462 std::vector<uint64_t> OutputRowOffsets;
2466 bool hasStmtSeq =
Unit.getStmtSeqListAttributes().size() > 0;
2467 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2469 hasStmtSeq ? &OutputRowOffsets :
nullptr);
2472 assert(OutputRowOffsets.size() == OutputRows.size() &&
2473 "must have an offset for each row");
2476 DenseMap<uint64_t, uint64_t> SeqOffToOrigRow;
2481 if (!
LT->Rows.empty())
2489 DenseMap<size_t, size_t> OrigRowToOutputRow;
2490 std::vector<size_t> OutputRowToSeqStart(OutputRows.size());
2492 size_t CurrentSeqStart = 0;
2493 for (
size_t i = 0; i < OutputRows.size(); ++i) {
2495 if (OutputRows[i].isStartSeqInOutput)
2496 CurrentSeqStart = i;
2497 OutputRowToSeqStart[i] = CurrentSeqStart;
2500 OrigRowToOutputRow[OutputRows[i].OriginalRowIndex] = i;
2505 for (
const auto &StmtSeq :
Unit.getStmtSeqListAttributes()) {
2506 uint64_t OrigStmtSeq = StmtSeq.get();
2508 auto OrigRowIter = SeqOffToOrigRow.find(OrigStmtSeq);
2510 Unit.getOrigUnit().getFormParams().getDwarfMaxOffset();
2514 if (OrigRowIter == SeqOffToOrigRow.end()) {
2515 StmtSeq.set(InvalidOffset);
2518 size_t OrigRowIndex = OrigRowIter->second;
2521 auto OutputRowIter = OrigRowToOutputRow.find(OrigRowIndex);
2522 if (OutputRowIter == OrigRowToOutputRow.end()) {
2524 StmtSeq.set(InvalidOffset);
2527 size_t OutputRowIdx = OutputRowIter->second;
2532 size_t SeqStartIdx = OutputRowToSeqStart[OutputRowIdx];
2536 assert(SeqStartIdx < OutputRowOffsets.size() &&
2537 "Sequence start index out of bounds");
2538 uint64_t NewStmtSeqOffset = OutputRowOffsets[SeqStartIdx];
2541 StmtSeq.set(NewStmtSeqOffset);
2547 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2552void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2557 for (
const auto &Namespace :
Unit.getNamespaces())
2559 Unit.getStartOffset());
2561 for (
const auto &Pubname :
Unit.getPubnames())
2562 AppleNames.addName(Pubname.Name,
2563 Pubname.Die->getOffset() +
Unit.getStartOffset());
2565 for (
const auto &Pubtype :
Unit.getPubtypes())
2567 Pubtype.Name, Pubtype.Die->getOffset() +
Unit.getStartOffset(),
2568 Pubtype.Die->getTag(),
2571 Pubtype.QualifiedNameHash);
2573 for (
const auto &ObjC :
Unit.getObjC())
2574 AppleObjc.addName(ObjC.Name,
2575 ObjC.Die->getOffset() +
Unit.getStartOffset());
2578 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2579 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2582 for (
const auto &Namespace :
Unit.getNamespaces())
2587 Unit.getTag() == dwarf::DW_TAG_type_unit);
2588 for (
const auto &Pubname :
Unit.getPubnames())
2590 Pubname.Name, Pubname.Die->getOffset(),
2592 Pubname.Die->getTag(),
Unit.getUniqueID(),
2593 Unit.getTag() == dwarf::DW_TAG_type_unit);
2594 for (
const auto &Pubtype :
Unit.getPubtypes())
2596 Pubtype.Name, Pubtype.Die->getOffset(),
2598 Pubtype.Die->getTag(),
Unit.getUniqueID(),
2599 Unit.getTag() == dwarf::DW_TAG_type_unit);
2611void DWARFLinker::patchFrameInfoForObject(LinkContext &
Context) {
2612 DWARFContext &OrigDwarf = *
Context.File.Dwarf;
2613 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2615 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2620 for (std::unique_ptr<CompileUnit> &Unit :
Context.CompileUnits) {
2621 for (
auto CurRange :
Unit->getFunctionRanges())
2622 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
2625 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian());
2630 DenseMap<uint64_t, StringRef> LocalCIES;
2632 while (
Data.isValidOffset(InputOffset)) {
2633 uint64_t EntryOffset = InputOffset;
2634 uint32_t InitialLength =
Data.getU32(&InputOffset);
2635 if (InitialLength == 0xFFFFFFFF)
2636 return reportWarning(
"Dwarf64 bits no supported",
Context.File);
2638 uint32_t CIEId =
Data.getU32(&InputOffset);
2639 if (CIEId == 0xFFFFFFFF) {
2641 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2642 LocalCIES[EntryOffset] = CIEData;
2644 InputOffset += InitialLength - 4;
2648 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2654 std::optional<AddressRangeValuePair>
Range =
2655 AllUnitsRanges.getRangeThatContains(Loc);
2658 InputOffset = EntryOffset + InitialLength + 4;
2664 StringRef CIEData = LocalCIES[CIEId];
2665 if (CIEData.empty())
2666 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2671 auto IteratorInserted = EmittedCIEs.insert(
2672 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2674 if (IteratorInserted.second) {
2675 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2676 IteratorInserted.first->getValue() = LastCIEOffset;
2677 TheDwarfEmitter->emitCIE(CIEData);
2683 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2684 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2686 FrameData.substr(InputOffset, FDERemainingBytes));
2687 InputOffset += FDERemainingBytes;
2691uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2693 const DWARFFile &File,
2694 int ChildRecurseDepth) {
2695 const char *
Name =
nullptr;
2696 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2697 CompileUnit *CU = &
U;
2698 std::optional<DWARFFormValue>
Ref;
2704 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2705 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2713 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2715 OrigUnit = &RefCU->getOrigUnit();
2720 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2721 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2722 Name =
"(anonymous namespace)";
2724 if (CU->getInfo(Idx).ParentIdx == 0 ||
2726 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
2727 dwarf::DW_TAG_module)
2728 return djbHash(Name ? Name :
"",
djbHash(ChildRecurseDepth ?
"" :
"::"));
2730 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
2739 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2748 if (ObjectPrefixMap.empty())
2752 for (
const auto &Entry : ObjectPrefixMap)
2755 return p.str().str();
2762 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2764 if (PCMFile.empty())
2767 if (ObjectPrefixMap)
2768 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2773std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2774 std::string &PCMFile,
2775 LinkContext &Context,
2778 if (PCMFile.empty())
2779 return std::make_pair(
false,
false);
2784 std::string Name =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2787 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2789 return std::make_pair(
true,
true);
2792 if (!
Quiet && Options.Verbose) {
2794 outs() <<
"Found clang module reference " << PCMFile;
2797 auto Cached = ClangModules.find(PCMFile);
2798 if (Cached != ClangModules.end()) {
2802 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2803 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2804 "different version of the module ") +
2807 if (!
Quiet && Options.Verbose)
2808 outs() <<
" [cached].\n";
2809 return std::make_pair(
true,
true);
2812 return std::make_pair(
true,
false);
2815bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2820 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2821 std::pair<bool, bool> IsClangModuleRef =
2822 isClangModuleRef(CUDie, PCMFile,
Context, Indent,
false);
2824 if (!IsClangModuleRef.first)
2827 if (IsClangModuleRef.second)
2830 if (Options.Verbose)
2835 ClangModules.insert({PCMFile,
getDwoId(CUDie)});
2837 if (
Error E = loadClangModule(Loader, CUDie, PCMFile,
Context, OnCUDieLoaded,
2845Error DWARFLinker::loadClangModule(
2846 ObjFileLoaderTy Loader,
const DWARFDie &CUDie,
const std::string &PCMFile,
2850 std::string ModuleName =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2853 SmallString<0>
Path(Options.PrependPath);
2860 if (Loader ==
nullptr) {
2861 reportError(
"Could not load clang module: loader is not specified.\n",
2866 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2870 std::unique_ptr<CompileUnit>
Unit;
2871 for (
const auto &CU : ErrOrObj->Dwarf->compile_units()) {
2874 auto ChildCUDie = CU->getUnitDIE();
2877 if (!registerModuleReference(ChildCUDie,
Context, Loader, OnCUDieLoaded,
2882 ": Clang modules are expected to have exactly 1 compile unit.\n");
2883 reportError(Err,
Context.File);
2890 if (PCMDwoId != DwoId) {
2891 if (Options.Verbose)
2893 Twine(
"hash mismatch: this object file was built against a "
2894 "different version of the module ") +
2898 ClangModules[PCMFile] = PCMDwoId;
2902 Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR,
2908 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2913Expected<uint64_t> DWARFLinker::DIECloner::cloneAllCompileUnits(
2914 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2917 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2919 for (
auto &CurrentUnit : CompileUnits) {
2920 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2921 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2922 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2923 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2925 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2928 if (CurrentUnit->getInfo(0).Keep) {
2931 CurrentUnit->createOutputDIE();
2932 rememberUnitForMacroOffset(*CurrentUnit);
2933 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2934 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2937 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2941 if (
Error E = generateLineTableForUnit(*CurrentUnit))
2944 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2949 if (
Error E =
Linker.generateUnitRanges(*CurrentUnit, File, AddrPool))
2952 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2953 SmallVectorImpl<uint8_t> &OutBytes,
2954 int64_t RelocAdjustment) {
2955 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2956 DataExtractor
Data(SrcBytes, IsLittleEndian);
2957 cloneExpression(
Data,
2958 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2959 OrigUnit.getFormParams().Format),
2960 File, *CurrentUnit, OutBytes, RelocAdjustment,
2963 if (
Error E = generateUnitLocations(*CurrentUnit, File, ProcessExpr))
2965 if (
Error E = emitDebugAddrSection(*CurrentUnit, DwarfVersion))
2974 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2977 for (
auto &CurrentUnit : CompileUnits) {
2978 CurrentUnit->fixupForwardReferences();
2980 if (!CurrentUnit->getOutputUnitDIE())
2983 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2986 CurrentUnit->getStartOffset());
2987 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2988 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2990 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2994 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2997void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2998 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getLocSection().Data,
3000 TheDwarfEmitter->emitSectionContents(
3001 Dwarf.getDWARFObj().getRangesSection().Data,
3003 TheDwarfEmitter->emitSectionContents(
3005 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getArangesSection(),
3007 TheDwarfEmitter->emitSectionContents(
3009 TheDwarfEmitter->emitSectionContents(
3010 Dwarf.getDWARFObj().getRnglistsSection().Data,
3012 TheDwarfEmitter->emitSectionContents(
3013 Dwarf.getDWARFObj().getLoclistsSection().Data,
3019 ObjectContexts.emplace_back(LinkContext(File));
3021 if (ObjectContexts.back().File.Dwarf) {
3022 for (
const std::unique_ptr<DWARFUnit> &
CU :
3023 ObjectContexts.back().File.Dwarf->compile_units()) {
3032 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
3039 assert((Options.TargetDWARFVersion != 0) &&
3040 "TargetDWARFVersion should be set");
3044 unsigned NumObjects = ObjectContexts.size();
3056 for (LinkContext &OptContext : ObjectContexts) {
3057 if (Options.Verbose)
3058 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
3060 if (!OptContext.File.Dwarf)
3063 if (Options.VerifyInputDWARF)
3064 verifyInput(OptContext.File);
3071 !OptContext.File.Addresses->hasValidRelocs()) {
3072 if (Options.Verbose)
3073 outs() <<
"No valid relocations found. Skipping.\n";
3077 OptContext.Skip =
true;
3082 if (!OptContext.File.Dwarf)
3086 if (!OptContext.File.Dwarf->types_section_units().empty()) {
3087 reportWarning(
"type units are not currently supported: file will "
3090 OptContext.Skip =
true;
3096 OptContext.CompileUnits.reserve(
3097 OptContext.File.Dwarf->getNumCompileUnits());
3098 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
3099 auto CUDie =
CU->getUnitDIE(
true);
3100 if (Options.Verbose) {
3101 outs() <<
"Input compilation unit:";
3104 DumpOpts.
Verbose = Options.Verbose;
3105 CUDie.dump(
outs(), 0, DumpOpts);
3109 for (
auto &
CU : OptContext.ModuleUnits) {
3110 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
3111 DebugLineStrPool, StringOffsetPool))
3112 reportWarning(
toString(std::move(Err)),
CU.File);
3122 (TheDwarfEmitter ==
nullptr) ? 0
3123 : TheDwarfEmitter->getDebugInfoSectionSize();
3127 std::mutex ProcessedFilesMutex;
3128 std::condition_variable ProcessedFilesConditionVariable;
3129 BitVector ProcessedFiles(NumObjects,
false);
3133 auto AnalyzeLambda = [&](
size_t I) {
3134 auto &Context = ObjectContexts[
I];
3136 if (Context.Skip || !Context.File.Dwarf)
3139 for (
const auto &
CU : Context.File.Dwarf->compile_units()) {
3142 auto CUDie =
CU->getUnitDIE(
false);
3143 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
3146 !isClangModuleRef(CUDie, PCMFile, Context, 0,
true).first) {
3147 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
3148 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
3153 for (
auto &CurrentUnit : Context.CompileUnits) {
3154 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
3158 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
3159 ModulesEndOffset, Options.ParseableSwiftInterfaces,
3161 reportWarning(Warning, Context.File, &DIE);
3174 auto &OptContext = ObjectContexts[
I];
3175 if (OptContext.Skip || !OptContext.File.Dwarf)
3184 for (
auto &CurrentUnit : OptContext.CompileUnits)
3185 CurrentUnit->markEverythingAsKept();
3186 copyInvariantDebugSection(*OptContext.File.Dwarf);
3188 for (
auto &CurrentUnit : OptContext.CompileUnits) {
3189 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
3190 CurrentUnit->getOrigUnit().getUnitDIE(),
3191 OptContext.File, *CurrentUnit, 0);
3201 if (OptContext.File.Addresses->hasValidRelocs() ||
3203 SizeByObject[OptContext.File.FileName].Input =
3206 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
3207 OptContext.CompileUnits, Options.Update, DebugStrPool,
3208 DebugLineStrPool, StringOffsetPool)
3209 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
3210 OptContext.File.Dwarf->isLittleEndian());
3215 SizeByObject[OptContext.File.FileName].Output = *SizeOrErr;
3217 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
3219 patchFrameInfoForObject(OptContext);
3222 cleanupAuxiliarryData(OptContext);
3225 auto EmitLambda = [&]() {
3227 if (TheDwarfEmitter !=
nullptr) {
3228 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
3229 TheDwarfEmitter->emitStrings(DebugStrPool);
3230 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.
getValues(),
3231 Options.TargetDWARFVersion);
3232 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
3234 switch (TableKind) {
3236 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
3237 TheDwarfEmitter->emitAppleNames(AppleNames);
3238 TheDwarfEmitter->emitAppleTypes(AppleTypes);
3239 TheDwarfEmitter->emitAppleObjc(AppleObjc);
3246 TheDwarfEmitter->emitDebugNames(DebugNames);
3253 auto AnalyzeAll = [&]() {
3254 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3257 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3258 ProcessedFiles.
set(
I);
3259 ProcessedFilesConditionVariable.notify_one();
3264 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3266 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3267 if (!ProcessedFiles[
I]) {
3268 ProcessedFilesConditionVariable.wait(
3269 LockGuard, [&]() {
return ProcessedFiles[
I]; });
3285 if (Options.Threads == 1) {
3286 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3296 Pool.
async(AnalyzeAll);
3297 Pool.
async(CloneAll, std::reference_wrapper<Error>(CE));
3304 if (Options.Statistics) {
3306 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
3307 for (
auto &
E : SizeByObject)
3308 Sorted.emplace_back(
E.first(),
E.second);
3310 return LHS.second.Output >
RHS.second.Output;
3313 auto ComputePercentange = [](int64_t
Input, int64_t Output) ->
float {
3314 const float Difference = Output -
Input;
3315 const float Sum =
Input + Output;
3318 return (Difference / (Sum / 2));
3321 int64_t InputTotal = 0;
3322 int64_t OutputTotal = 0;
3323 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
3326 outs() <<
".debug_info section size (in bytes)\n";
3327 outs() <<
"----------------------------------------------------------------"
3328 "---------------\n";
3329 outs() <<
"Filename Object "
3331 outs() <<
"----------------------------------------------------------------"
3332 "---------------\n";
3335 for (
auto &
E : Sorted) {
3336 InputTotal +=
E.second.Input;
3337 OutputTotal +=
E.second.Output;
3340 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
3343 outs() <<
"----------------------------------------------------------------"
3344 "---------------\n";
3346 ComputePercentange(InputTotal, OutputTotal));
3347 outs() <<
"----------------------------------------------------------------"
3348 "---------------\n\n";
3354Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3360 assert(Unit.Unit.get() !=
nullptr);
3362 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3367 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3372 &ODRContexts.
getRoot(), ODRContexts, 0,
3373 Options.ParseableSwiftInterfaces,
3375 reportWarning(Warning, Context.File, &DIE);
3378 Unit.Unit->markEverythingAsKept();
3382 CompileUnits.emplace_back(std::move(Unit.Unit));
3385 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3386 Options.Update, DebugStrPool, DebugLineStrPool,
3388 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3389 Unit.File.Dwarf->isLittleEndian());
3395void DWARFLinker::verifyInput(
const DWARFFile &File) {
3402 if (
Options.InputVerificationHandler)
3403 Options.InputVerificationHandler(File, OS.str());
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE, int ChildRecurseDepth=0)
This file implements the BitVector class.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
dxil DXContainer Global Emitter
Provides ErrorOr<T> smart pointer.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
BitVector & set()
Set all bits in the bitvector.
void setChildrenFlag(bool hasChild)
value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V)
A structured debug information entry.
unsigned getAbbrevNumber() const
DIE & addChild(DIE *Child)
Add a child to the DIE.
LLVM_ABI DIEAbbrev generateAbbrev() const
Generate the abbreviation for this DIE.
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
void setAbbrevNumber(unsigned I)
Set the abbreviation number for this DIE.
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
void setOffset(unsigned O)
dwarf::Tag getTag() const
static LLVM_ABI std::optional< uint64_t > getDefiningParentDieOffset(const DIE &Die)
If Die has a non-null parent and the parent is not a declaration, return its offset.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
uint64_t getOffset() const
Get the absolute offset into the debug info or types section.
iterator_range< iterator > children() const
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Get the abbreviation declaration for this DIE.
dwarf::Tag getTag() const
LLVM_ABI std::optional< unsigned > getSubCode() const
uint64_t getEndOffset() const
Encoding
Size and signedness of expression operations' operands.
const Description & getDescription() const
uint64_t getRawOperand(unsigned Idx) const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
void wait() override
Blocking wait for all the tasks to execute first.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
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",...
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(uint64_t Val)
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
AddressesMap represents information about valid addresses used by debug information.
uint64_t constrainCodeRangeHighPC(uint64_t LowPC, uint64_t HighPC, int64_t Adjustment)
Constrains the end of the code range starting at LowPC, whose addresses shift by Adjustment in the ou...
This class represents DWARF information for source file and it's address map.
std::map< std::string, std::string > ObjectPrefixMapTy
function_ref< void(const DWARFUnit &Unit)> CompileUnitHandlerTy
AccelTableKind
The kind of accelerator tables to be emitted.
@ DebugNames
.debug_names.
@ Apple
.apple_names, .apple_namespaces, .apple_types, .apple_objc.
@ Pub
.debug_pubnames, .debug_pubtypes
std::map< std::string, std::string > SwiftInterfacesMapTy
std::function< ErrorOr< DWARFFile & >( StringRef ContainerName, StringRef Path)> ObjFileLoaderTy
const SmallVector< T > & getValues() const
Stores all information relating to a compile unit, be it in its original instance in the object file ...
void addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader=nullptr, CompileUnitHandlerTy OnCUDieLoaded=[](const DWARFUnit &) {}) override
Add object file to be linked.
Error link() override
Link debug info for added objFiles. Object files are linked all together.
This class gives a tree-like API to the DenseMap that stores the DeclContext objects.
LLVM_ABI PointerIntPair< DeclContext *, 1 > getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, CompileUnit &Unit, bool InClangModule)
Get the child of Context described by DIE in Unit.
A DeclContext is a named program scope that is used for ODR uniquing of types.
void setDefinedInClangModule(bool Val)
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
LLVM_ABI StringRef FormEncodingString(unsigned Encoding)
LLVM_ABI StringRef FormatString(DwarfFormat Format)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallVector< PatchLocation > RngListAttributesTy
std::vector< std::unique_ptr< CompileUnit > > UnitListTy
IndexedValuesMap< uint64_t > DebugDieValuePool
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
SmallVector< PatchLocation > LocListAttributesTy
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
LLVM_ABI bool hasImplicitAddressLocation(const DWARFDie &Die)
Test if the location of variable Die contains a global address but only uses to compute the variable'...
LLVM_ABI void buildStmtSeqOffsetToFirstRowIndex(const DWARFDebugLine::LineTable <, ArrayRef< uint64_t > SortedStmtSeqOffsets, DenseMap< uint64_t, uint64_t > &SeqOffToFirstRow)
Build a map from an input DW_AT_LLVM_stmt_sequence byte offset to the first-row index (in LT....
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
bool isInToolchainDir(StringRef Path)
Make a best effort to determine whether Path is inside a toolchain.
bool isTlsAddressOp(uint8_t O)
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
LLVM_ABI bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, uint16_t DwarfVersion)
Check whether specified Form belongs to the FC class.
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.
@ DW_FLAG_type_implementation
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
LLVM_ABI bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
LLVM_ABI bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
constexpr bool IsLittleEndianHost
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
static void verifyKeepChain(CompileUnit &CU)
Verify the keep chain by looking for DIEs that are kept but who's parent isn't.
static void updateRefIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &RefInfo)
Helper that updates the completeness of the current DIE based on the completeness of the DIEs it refe...
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
static void patchAddrBase(DIE &Die, DIEInteger Offset)
auto unique(Range &&R, Predicate P)
static std::string remapPath(StringRef Path, const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap)
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
static CompileUnit * getUnitForOffset(const UnitListTy &Units, uint64_t Offset)
Similar to DWARFUnitSection::getUnitForOffset(), but returning our CompileUnit object instead.
static void insertLineSequence(std::vector< TrackedRow > &Seq, std::vector< TrackedRow > &Rows)
Insert the new line info sequence Seq into the current set of already linked line info Rows.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
static void resolveRelativeObjectPath(SmallVectorImpl< char > &Buf, DWARFDie CU)
Resolve the relative path to a build artifact referenced by DWARF by applying DW_AT_comp_dir.
static std::string getPCMFile(const DWARFDie &CUDie, const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
static bool shouldSkipAttribute(bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, bool SkipPC)
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
static uint64_t getDebugInfoSize(DWARFContext &Dwarf)
Compute the total size of the debug info.
static bool isTypeTag(uint16_t Tag)
@ Dwarf
DWARF v5 .debug_names.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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...
static uint64_t getDwoId(const DWARFDie &CUDie)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, uint64_t ModulesEndOffset)
@ Success
The lock was released successfully.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
static void updateChildIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)
Helper that updates the completeness of the current DIE based on the completeness of one of its child...
SingleThreadExecutor DefaultThreadPool
DWARFExpression::Operation Op
static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
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...
static void analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, DeclContext *CurrentDeclContext, DeclContextTree &Contexts, uint64_t ModulesEndOffset, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Recursive helper to build the global DeclContext information and gather the child->parent relationshi...
static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag)
StrongType< NonRelocatableStringpool, OffsetsTag > OffsetsStringPool
static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU)
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
static void analyzeImportedModule(const DWARFDie &DIE, CompileUnit &CU, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
ContextWorklistItemType
The distinct types of work performed by the work loop in analyzeContextInfo.
static uint64_t constrainHighPC(const DWARFDie &InputDIE, uint64_t HighPC, bool IsLength, int64_t PCOffset, AddressesMap &Addresses)
Returns InputDIE's DW_AT_high_pc value HighPC, constrained so the code range it ends stays clear of t...
void consumeError(Error Err)
Consume a Error without doing anything.
static bool isODRAttribute(uint16_t Attr)
static void patchStmtList(DIE &Die, DIEInteger Offset)
static void constructSeqOffsettoOrigRowMapping(CompileUnit &Unit, const DWARFDebugLine::LineTable <, DenseMap< uint64_t, uint64_t > &SeqOffToOrigRow)
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
int64_t LinkedOffsetFixupVal
uint64_t InputAttrStartOffset
uint64_t InputAttrEndOffset
A broken link in the keep chain.
BrokenLink(DWARFDie Parent, DWARFDie Child)
This class represents an item in the work list.
CompileUnit::DIEInfo * OtherInfo
ContextWorklistItem(DWARFDie Die, DeclContext *Context, unsigned ParentIdx, bool InImportedModule)
ContextWorklistItemType Type
ContextWorklistItem(DWARFDie Die, ContextWorklistItemType T, CompileUnit::DIEInfo *OtherInfo=nullptr)
Container for dump options that control which debug information will be dumped.
DIDumpOptions noImplicitRecursion() const
Return the options with RecurseDepth set to 0 unless explicitly required.
unsigned ChildRecurseDepth
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Standard .debug_line state machine structure.
SmallVector< Encoding > Op
Encoding for Op operands.
Hold the input and output of the debug info size in bytes.
A helper struct to help keep track of the association between the input and output rows during line t...
Information gathered about a DIE in the object file.
bool Prune
Is this a pure forward declaration we can strip?
bool Incomplete
Does DIE transitively refer an incomplete decl?