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;
1106 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
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.InsertNode(Abbreviations.back().get(), InsertToken);
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();
1250 uint64_t OpOffset = 0;
1251 for (
auto &
Op : Expression) {
1257 Desc.
Op[0] != Encoding::Size1))
1258 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
1262 Desc.
Op[0] == Encoding::Size1)) {
1282 if (RefOffset > 0 ||
Op.
getCode() != dwarf::DW_OP_convert) {
1283 RefOffset +=
Unit.getOrigUnit().getOffset();
1284 auto RefDie =
Unit.getOrigUnit().getDIEForOffset(RefOffset);
1285 CompileUnit::DIEInfo &
Info =
Unit.getInfo(RefDie);
1286 if (DIE *Clone =
Info.Clone)
1287 Offset = Clone->getOffset();
1289 Linker.reportWarning(
1290 "base type ref doesn't point to DW_TAG_base_type.", File);
1294 if (RealSize > ULEBsize) {
1297 Linker.reportWarning(
"base type ref doesn't fit.", File);
1299 assert(RealSize == ULEBsize &&
"padding failed");
1300 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1301 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1302 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_addrx) {
1303 if (std::optional<object::SectionedAddress> SA =
1304 Unit.getOrigUnit().getAddrOffsetSectionItem(
1310 OutputBuffer.push_back(dwarf::DW_OP_addr);
1311 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1314 ArrayRef<uint8_t> AddressBytes(
1315 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1316 OrigAddressByteSize);
1317 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1319 Linker.reportWarning(
"cannot read DW_OP_addrx operand.", File);
1320 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_constx) {
1321 if (std::optional<object::SectionedAddress> SA =
1322 Unit.getOrigUnit().getAddrOffsetSectionItem(
1328 std::optional<uint8_t> OutOperandKind;
1329 switch (OrigAddressByteSize) {
1331 OutOperandKind = dwarf::DW_OP_const4u;
1334 OutOperandKind = dwarf::DW_OP_const8u;
1337 Linker.reportWarning(
1338 formatv((
"unsupported address size: {0}."), OrigAddressByteSize),
1343 if (OutOperandKind) {
1344 OutputBuffer.push_back(*OutOperandKind);
1345 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1348 ArrayRef<uint8_t> AddressBytes(
1349 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1350 OrigAddressByteSize);
1351 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1354 Linker.reportWarning(
"cannot read DW_OP_constx operand.", File);
1358 OutputBuffer.append(Bytes.begin(), Bytes.end());
1364unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1365 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1366 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1367 bool IsLittleEndian) {
1370 DIELoc *Loc =
nullptr;
1371 DIEBlock *
Block =
nullptr;
1372 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1373 Loc =
new (DIEAlloc) DIELoc;
1374 Linker.DIELocs.push_back(Loc);
1376 Block =
new (DIEAlloc) DIEBlock;
1377 Linker.DIEBlocks.push_back(
Block);
1379 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1380 : static_cast<DIEValueList *>(
Block);
1382 DWARFUnit &OrigUnit =
Unit.getOrigUnit();
1385 SmallVector<uint8_t, 32> Buffer;
1386 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1390 DataExtractor Data(Bytes, IsLittleEndian);
1391 DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
1392 OrigUnit.getFormParams().Format);
1393 cloneExpression(Data, Expr, File, Unit, Buffer,
1394 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);
1397 for (
auto Byte : Bytes)
1399 dwarf::DW_FORM_data1, DIEInteger(Byte));
1405 Loc->setSize(Bytes.size());
1407 Block->setSize(Bytes.size());
1415 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&
1416 (Bytes.size() > UINT8_MAX)) ||
1417 (AttrSpec.Form == dwarf::DW_FORM_block2 &&
1418 (Bytes.size() > UINT16_MAX)) ||
1419 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))
1420 AttrSpec.Form = dwarf::DW_FORM_block;
1422 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
1423 dwarf::Form(AttrSpec.Form), Block);
1426 return Die.addValue(DIEAlloc,
Value)->sizeOf(OrigUnit.getFormParams());
1437 bool IsLength, int64_t PCOffset,
1439 std::optional<uint64_t> LowPC =
1444 *LowPC, IsLength ? *LowPC + HighPC : HighPC, PCOffset);
1445 return IsLength ? Constrained - *LowPC : Constrained;
1448unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1449 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1450 unsigned AttrSize,
const DWARFFormValue &Val,
const CompileUnit &Unit,
1451 AttributesInfo &Info) {
1452 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1453 Info.HasLowPc =
true;
1457 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1473 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1477 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
1479 Linker.reportWarning(
"Cann't read address attribute value.", ObjFile);
1483 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1484 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1485 if (std::optional<uint64_t> LowPC =
Unit.getLowPc())
1489 }
else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1490 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1491 if (uint64_t HighPc =
Unit.getHighPc())
1496 if (AttrSpec.Attr == dwarf::DW_AT_high_pc)
1498 *ObjFile.Addresses);
1499 *Addr +=
Info.PCOffset;
1502 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
1504 AttrSpec.Form, DIEInteger(*Addr));
1505 return Unit.getOrigUnit().getAddressByteSize();
1508 auto AddrIndex = AddrPool.getValueIndex(*Addr);
1512 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))
1513 ->sizeOf(
Unit.getOrigUnit().getFormParams());
1516unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1517 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1518 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1519 unsigned AttrSize, AttributesInfo &Info) {
1524 if (AttrSpec.Attr == dwarf::DW_AT_GNU_dwo_id ||
1525 AttrSpec.Attr == dwarf::DW_AT_dwo_id)
1530 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1531 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1532 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacinfo();
1538 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1539 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1540 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacro();
1546 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1550 Info.AttrStrOffsetBaseSeen =
true;
1552 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1553 dwarf::DW_FORM_sec_offset, DIEInteger(8))
1554 ->sizeOf(
Unit.getOrigUnit().getFormParams());
1557 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
1560 dwarf::DW_FORM_sec_offset,
1561 DIEInteger(*Val.getAsSectionOffset()));
1564 Unit.noteStmtSeqListAttribute(Patch);
1566 return Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1570 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1571 Value = *OptionalValue;
1572 else if (
auto OptionalValue = Val.getAsSignedConstant())
1573 Value = *OptionalValue;
1574 else if (
auto OptionalValue = Val.getAsSectionOffset())
1575 Value = *OptionalValue;
1577 Linker.reportWarning(
1578 "Unsupported scalar attribute form. Dropping attribute.", File,
1582 if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1583 Info.IsDeclaration =
true;
1585 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1594 [[maybe_unused]]
dwarf::Form OriginalForm = AttrSpec.Form;
1595 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1599 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1601 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1605 std::optional<uint64_t>
Offset =
1606 Unit.getOrigUnit().getRnglistOffset(*Index);
1608 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1614 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1615 AttrSize =
Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1616 }
else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1620 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1622 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1626 std::optional<uint64_t>
Offset =
1627 Unit.getOrigUnit().getLoclistOffset(*Index);
1629 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1635 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1636 AttrSize =
Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1637 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1638 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1639 std::optional<uint64_t> LowPC =
Unit.getLowPc();
1644 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1645 Value = *Val.getAsSectionOffset();
1646 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1647 Value = *Val.getAsSignedConstant();
1648 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1649 Value = *OptionalValue;
1651 Linker.reportWarning(
1652 "Unsupported scalar attribute form. Dropping attribute.", File,
1659 if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1660 Die.getTag() != dwarf::DW_TAG_compile_unit)
1664 DIE::value_iterator Patch =
1667 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1668 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1669 Unit.noteRangeAttribute(Die, Patch);
1670 Info.HasRanges =
true;
1674 Unit.getOrigUnit().getVersion())) {
1676 CompileUnit::DIEInfo &LocationDieInfo =
Unit.getInfo(InputDIE);
1677 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
1678 ? LocationDieInfo.AddrAdjust
1680 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1681 Info.IsDeclaration =
true;
1684 assert((
Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1685 "Unhandled DW_FORM_rnglistx attribute");
1693unsigned DWARFLinker::DIECloner::cloneAttribute(
1694 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1695 CompileUnit &Unit,
const DWARFFormValue &Val,
const AttributeSpec AttrSpec,
1696 unsigned AttrSize, AttributesInfo &Info,
bool IsLittleEndian) {
1697 const DWARFUnit &
U =
Unit.getOrigUnit();
1699 switch (AttrSpec.Form) {
1700 case dwarf::DW_FORM_strp:
1701 case dwarf::DW_FORM_line_strp:
1702 case dwarf::DW_FORM_string:
1703 case dwarf::DW_FORM_strx:
1704 case dwarf::DW_FORM_strx1:
1705 case dwarf::DW_FORM_strx2:
1706 case dwarf::DW_FORM_strx3:
1707 case dwarf::DW_FORM_strx4:
1708 return cloneStringAttribute(Die, AttrSpec, Val, U, Info);
1709 case dwarf::DW_FORM_ref_addr:
1710 case dwarf::DW_FORM_ref1:
1711 case dwarf::DW_FORM_ref2:
1712 case dwarf::DW_FORM_ref4:
1713 case dwarf::DW_FORM_ref8:
1714 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1716 case dwarf::DW_FORM_block:
1717 case dwarf::DW_FORM_block1:
1718 case dwarf::DW_FORM_block2:
1719 case dwarf::DW_FORM_block4:
1720 case dwarf::DW_FORM_exprloc:
1721 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1723 case dwarf::DW_FORM_addr:
1724 case dwarf::DW_FORM_addrx:
1725 case dwarf::DW_FORM_addrx1:
1726 case dwarf::DW_FORM_addrx2:
1727 case dwarf::DW_FORM_addrx3:
1728 case dwarf::DW_FORM_addrx4:
1729 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1731 case dwarf::DW_FORM_data1:
1732 case dwarf::DW_FORM_data2:
1733 case dwarf::DW_FORM_data4:
1734 case dwarf::DW_FORM_data8:
1735 case dwarf::DW_FORM_udata:
1736 case dwarf::DW_FORM_sdata:
1737 case dwarf::DW_FORM_sec_offset:
1738 case dwarf::DW_FORM_flag:
1739 case dwarf::DW_FORM_flag_present:
1740 case dwarf::DW_FORM_rnglistx:
1741 case dwarf::DW_FORM_loclistx:
1742 case dwarf::DW_FORM_implicit_const:
1743 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1746 Linker.reportWarning(
"Unsupported attribute form " +
1748 " in cloneAttribute. Dropping.",
1755void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1757 DwarfStringPoolEntryRef Name,
1759 bool SkipPubSection) {
1760 std::optional<ObjCSelectorNames> Names =
1764 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),
1766 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),
1768 if (Names->ClassNameNoCategory)
1769 Unit.addObjCAccelerator(
1770 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);
1771 if (Names->MethodNameNoCategory)
1772 Unit.addNameAccelerator(
1773 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);
1780 switch (AttrSpec.
Attr) {
1783 case dwarf::DW_AT_low_pc:
1784 case dwarf::DW_AT_high_pc:
1785 case dwarf::DW_AT_ranges:
1786 return !Update && SkipPC;
1787 case dwarf::DW_AT_rnglists_base:
1793 case dwarf::DW_AT_loclists_base:
1799 case dwarf::DW_AT_location:
1800 case dwarf::DW_AT_frame_base:
1801 return !Update && SkipPC;
1811DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1813 int64_t PCOffset,
uint32_t OutOffset,
1814 unsigned Flags,
bool IsLittleEndian,
1817 unsigned Idx = U.getDIEIndex(InputDIE);
1821 if (!Unit.getInfo(Idx).Keep)
1825 assert(!(Die && Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1837 (Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1838 if (!Info.Ctxt->hasCanonicalDIE())
1839 Info.Ctxt->setHasCanonicalDIE();
1843 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1847 DWARFDataExtractor
Data =
U.getDebugInfoExtractor();
1851 uint64_t NextOffset = (Idx + 1 <
U.getNumDIEs())
1852 ?
U.getDIEAtIndex(Idx + 1).getOffset()
1853 :
U.getNextUnitOffset();
1854 AttributesInfo AttrInfo;
1859 SmallString<40> DIECopy(
Data.getData().substr(
Offset, NextOffset -
Offset));
1861 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1864 ObjFile.Addresses->applyValidRelocs(DIECopy,
Offset,
Data.isLittleEndian());
1874 if (Die->
getTag() == dwarf::DW_TAG_subprogram)
1875 PCOffset =
Info.AddrAdjust;
1876 AttrInfo.PCOffset = PCOffset;
1878 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1879 Flags |= TF_InFunctionScope;
1882 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1885 if ((Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1886 Flags &= ~TF_SkipPC;
1889 else if (!
Info.InDebugMap &&
Info.HasLocationExpressionAddr &&
1894 std::optional<StringRef> LibraryInstallName =
1895 ObjFile.Addresses->getLibraryInstallName();
1897 for (
const auto &AttrSpec : Abbrev->attributes()) {
1904 AttributeLinkedOffsetFixup CurAttrFixup;
1906 CurAttrFixup.LinkedOffsetFixupVal =
1907 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1909 DWARFFormValue Val = AttrSpec.getFormValue();
1910 uint64_t AttrSize =
Offset;
1911 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1913 AttrSize =
Offset - AttrSize;
1915 uint64_t FinalAttrSize =
1916 cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
1917 AttrInfo, IsLittleEndian);
1918 if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
1919 AttributesFixups.push_back(CurAttrFixup);
1921 OutOffset += FinalAttrSize;
1927 const bool NeedsAppleOrigin = (
Tag == dwarf::DW_TAG_compile_unit) &&
1928 LibraryInstallName.has_value() &&
1929 !AttrInfo.HasAppleOrigin;
1930 if (NeedsAppleOrigin) {
1931 auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
1933 dwarf::DW_FORM_strp, DIEInteger(
StringEntry.getOffset()));
1942 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1943 Tag != dwarf::DW_TAG_compile_unit &&
1944 getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit,
1945 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1946 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1947 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1948 Tag == dwarf::DW_TAG_inlined_subroutine);
1949 if (AttrInfo.Name) {
1950 if (AttrInfo.NameWithoutTemplate)
1951 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1953 Unit.addNameAccelerator(Die, AttrInfo.Name,
1954 Tag == dwarf::DW_TAG_inlined_subroutine);
1957 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,
1960 }
else if (
Tag == dwarf::DW_TAG_namespace) {
1962 AttrInfo.Name = DebugStrPool.getEntry(
"(anonymous namespace)");
1963 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1964 }
else if (
Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1965 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1966 }
else if (
isTypeTag(
Tag) && !AttrInfo.IsDeclaration) {
1967 bool Success = getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit);
1968 uint64_t RuntimeLang =
1971 bool ObjCClassIsImplementation =
1972 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1973 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1976 if (
Success && AttrInfo.Name && !AttrInfo.Name.getString().empty()) {
1978 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1983 if (
Success && AttrInfo.MangledName &&
1984 RuntimeLang == dwarf::DW_LANG_Swift &&
1985 !AttrInfo.MangledName.getString().empty() &&
1986 AttrInfo.MangledName != AttrInfo.Name) {
1987 auto Hash =
djbHash(AttrInfo.MangledName.getString().data());
1988 Unit.addTypeAccelerator(Die, AttrInfo.MangledName,
1989 ObjCClassIsImplementation, Hash);
1994 bool HasChildren =
false;
1995 for (
auto Child : InputDIE.
children()) {
1996 unsigned Idx =
U.getDIEIndex(Child);
1997 if (
Unit.getInfo(Idx).Keep) {
2003 if (
Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
2004 Die->
getTag() == dwarf::DW_TAG_compile_unit) {
2006 Die->
addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
2007 dwarf::DW_FORM_sec_offset, DIEInteger(8));
2015 Linker.assignAbbrev(NewAbbrev);
2021 OutOffset += AbbrevNumberSize;
2024 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2025 F.LinkedOffsetFixupVal += AbbrevNumberSize;
2027 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2028 ObjFile.Addresses->updateAndSaveValidRelocs(
2029 Unit.getOrigUnit().getVersion() >= 5,
Unit.getOrigUnit().getOffset(),
2030 F.LinkedOffsetFixupVal,
F.InputAttrStartOffset,
F.InputAttrEndOffset);
2039 for (
auto Child : InputDIE.
children()) {
2040 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
2043 OutOffset = Clone->getOffset() + Clone->getSize();
2048 OutOffset +=
sizeof(int8_t);
2057Error DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File,
2062 const auto &FunctionRanges =
Unit.getFunctionRanges();
2065 AddressRanges LinkedFunctionRanges;
2066 for (
const AddressRangeValuePair &
Range : FunctionRanges)
2067 LinkedFunctionRanges.insert(
2071 if (!LinkedFunctionRanges.empty())
2072 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
2075 std::optional<PatchLocation> UnitRngListAttribute =
2076 Unit.getUnitRangesAttribute();
2078 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
2079 std::optional<AddressRangeValuePair> CachedRange;
2080 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
2084 for (PatchLocation &AttributePatch : AllRngListAttributes) {
2087 AddressRanges LinkedRanges;
2088 if (Expected<DWARFAddressRangesVector> OriginalRanges =
2089 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
2091 for (
const auto &
Range : *OriginalRanges) {
2092 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
2093 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
2097 reportWarning(
"inconsistent range data.", File);
2102 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
2103 Range.HighPC + CachedRange->Value});
2107 reportWarning(
"invalid range list ignored.", File);
2111 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2112 Unit, LinkedRanges, AttributePatch, AddrPool))
2117 if (UnitRngListAttribute.has_value())
2118 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2119 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool))
2123 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
2129Error DWARFLinker::DIECloner::generateUnitLocations(
2130 CompileUnit &Unit,
const DWARFFile &File,
2131 ExpressionHandlerRef ExprHandler) {
2136 Unit.getLocationAttributes();
2138 if (AllLocListAttributes.empty())
2144 for (
auto &CurLocAttr : AllLocListAttributes) {
2147 Expected<DWARFLocationExpressionsVector> OriginalLocations =
2148 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
2150 if (!OriginalLocations) {
2152 Linker.reportWarning(
"Invalid location attribute ignored.", File);
2157 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
2158 DWARFLocationExpression LinkedExpression;
2160 if (CurExpression.Range) {
2162 LinkedExpression.Range = {
2163 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
2164 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
2168 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
2169 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
2170 CurLocAttr.RelocAdjustment);
2172 LinkedLocationExpressions.push_back(LinkedExpression);
2177 Unit, LinkedLocationExpressions, CurLocAttr, AddrPool))
2182 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
2188 for (
auto &V : Die.
values())
2189 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
2197Error DWARFLinker::DIECloner::emitDebugAddrSection(
2198 CompileUnit &Unit,
const uint16_t DwarfVersion)
const {
2203 if (DwarfVersion < 5)
2206 if (AddrPool.getValues().empty())
2209 MCSymbol *EndLabel =
Emitter->emitDwarfDebugAddrsHeader(Unit);
2211 dwarf::FormParams
FP = Unit.getOrigUnit().getFormParams();
2212 if (AddrOffset >
FP.getDwarfMaxOffset())
2216 patchAddrBase(*Unit.getOutputUnitDIE(), DIEInteger(AddrOffset));
2217 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),
2218 Unit.getOrigUnit().getAddressByteSize());
2219 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
2237 std::vector<TrackedRow> &Rows) {
2243 Seq.front().isStartSeqInOutput =
true;
2245 if (!Rows.empty() && Rows.back().Row.Address < Seq.front().Row.Address) {
2253 Rows, [=](
const TrackedRow &O) {
return O.Row.Address < Front; });
2262 Rows.insert(
InsertPoint + 1, Seq.begin() + 1, Seq.end());
2271 for (
auto &V : Die.
values())
2272 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2280void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2281 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2282 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2284 if (std::optional<uint64_t> MacroAttr =
2286 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2290 if (std::optional<uint64_t> MacroAttr =
2292 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2297Error DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2302 DWARFDie CUDie =
Unit.getOrigUnit().getUnitDIE();
2308 if (
auto *OutputDIE =
Unit.getOutputUnitDIE()) {
2309 uint64_t StmtOffset =
Emitter->getLineSectionSize();
2310 dwarf::FormParams
FP =
Unit.getOrigUnit().getFormParams();
2311 if (StmtOffset >
FP.getDwarfMaxOffset())
2318 if (
const DWARFDebugLine::LineTable *LT =
2319 ObjFile.Dwarf->getLineTableForUnit(&
Unit.getOrigUnit())) {
2321 DWARFDebugLine::LineTable LineTable;
2324 LineTable.Prologue =
LT->Prologue;
2327 if (Linker.Options.Update) {
2328 LineTable.Rows =
LT->Rows;
2331 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2332 LineTable.Rows.clear();
2334 LineTable.Sequences =
LT->Sequences;
2336 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2340 std::vector<TrackedRow> InputRows;
2341 InputRows.reserve(
LT->Rows.size());
2342 for (
size_t i = 0; i <
LT->Rows.size(); i++)
2343 InputRows.emplace_back(TrackedRow{LT->Rows[i], i, false});
2346 std::vector<TrackedRow> OutputRows;
2347 OutputRows.reserve(InputRows.size());
2351 std::vector<TrackedRow> Seq;
2352 Seq.reserve(InputRows.size());
2354 const auto &FunctionRanges =
Unit.getFunctionRanges();
2355 std::optional<AddressRangeValuePair> CurrRange;
2368 for (
size_t i = 0; i < InputRows.size(); i++) {
2369 TrackedRow
TR = InputRows[i];
2376 if (!CurrRange || !CurrRange->Range.contains(
TR.Row.Address.Address)) {
2379 uint64_t StopAddress =
2380 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2382 FunctionRanges.getRangeThatContains(
TR.Row.Address.Address);
2383 if (StopAddress != -1ULL && !Seq.empty()) {
2386 auto NextLine = Seq.back();
2387 NextLine.Row.Address.Address = StopAddress;
2388 NextLine.Row.EndSequence = 1;
2389 NextLine.Row.PrologueEnd = 0;
2390 NextLine.Row.BasicBlock = 0;
2391 NextLine.Row.EpilogueBegin = 0;
2392 Seq.push_back(NextLine);
2401 if (
TR.Row.EndSequence && Seq.empty())
2405 TR.Row.Address.Address += CurrRange->Value;
2408 if (
TR.Row.EndSequence)
2419 if (!OutputRows.empty()) {
2420 OutputRows[0].isStartSeqInOutput =
true;
2421 for (
size_t i = 1; i < OutputRows.size(); ++i)
2422 OutputRows[i].isStartSeqInOutput = OutputRows[i - 1].Row.EndSequence;
2426 LineTable.Rows.clear();
2427 LineTable.Rows.reserve(OutputRows.size());
2428 for (
auto &TR : OutputRows)
2429 LineTable.Rows.push_back(
TR.Row);
2433 std::vector<uint64_t> OutputRowOffsets;
2437 bool hasStmtSeq =
Unit.getStmtSeqListAttributes().size() > 0;
2438 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2440 hasStmtSeq ? &OutputRowOffsets :
nullptr);
2443 assert(OutputRowOffsets.size() == OutputRows.size() &&
2444 "must have an offset for each row");
2447 DenseMap<uint64_t, uint64_t> SeqOffToOrigRow;
2452 if (!
LT->Rows.empty())
2460 DenseMap<size_t, size_t> OrigRowToOutputRow;
2461 std::vector<size_t> OutputRowToSeqStart(OutputRows.size());
2463 size_t CurrentSeqStart = 0;
2464 for (
size_t i = 0; i < OutputRows.size(); ++i) {
2466 if (OutputRows[i].isStartSeqInOutput)
2467 CurrentSeqStart = i;
2468 OutputRowToSeqStart[i] = CurrentSeqStart;
2471 OrigRowToOutputRow[OutputRows[i].OriginalRowIndex] = i;
2476 for (
const auto &StmtSeq :
Unit.getStmtSeqListAttributes()) {
2477 uint64_t OrigStmtSeq = StmtSeq.get();
2479 auto OrigRowIter = SeqOffToOrigRow.find(OrigStmtSeq);
2480 const uint64_t InvalidOffset =
2481 Unit.getOrigUnit().getFormParams().getDwarfMaxOffset();
2485 if (OrigRowIter == SeqOffToOrigRow.end()) {
2486 StmtSeq.set(InvalidOffset);
2489 size_t OrigRowIndex = OrigRowIter->second;
2492 auto OutputRowIter = OrigRowToOutputRow.find(OrigRowIndex);
2493 if (OutputRowIter == OrigRowToOutputRow.end()) {
2495 StmtSeq.set(InvalidOffset);
2498 size_t OutputRowIdx = OutputRowIter->second;
2503 size_t SeqStartIdx = OutputRowToSeqStart[OutputRowIdx];
2507 assert(SeqStartIdx < OutputRowOffsets.size() &&
2508 "Sequence start index out of bounds");
2509 uint64_t NewStmtSeqOffset = OutputRowOffsets[SeqStartIdx];
2512 StmtSeq.set(NewStmtSeqOffset);
2518 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2523void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2528 for (
const auto &Namespace :
Unit.getNamespaces())
2530 Unit.getStartOffset());
2532 for (
const auto &Pubname :
Unit.getPubnames())
2533 AppleNames.addName(Pubname.Name,
2534 Pubname.Die->getOffset() +
Unit.getStartOffset());
2536 for (
const auto &Pubtype :
Unit.getPubtypes())
2538 Pubtype.Name, Pubtype.Die->getOffset() +
Unit.getStartOffset(),
2539 Pubtype.Die->getTag(),
2542 Pubtype.QualifiedNameHash);
2544 for (
const auto &ObjC :
Unit.getObjC())
2545 AppleObjc.addName(ObjC.Name,
2546 ObjC.Die->getOffset() +
Unit.getStartOffset());
2549 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2550 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2553 for (
const auto &Namespace :
Unit.getNamespaces())
2558 Unit.getTag() == dwarf::DW_TAG_type_unit);
2559 for (
const auto &Pubname :
Unit.getPubnames())
2561 Pubname.Name, Pubname.Die->getOffset(),
2563 Pubname.Die->getTag(),
Unit.getUniqueID(),
2564 Unit.getTag() == dwarf::DW_TAG_type_unit);
2565 for (
const auto &Pubtype :
Unit.getPubtypes())
2567 Pubtype.Name, Pubtype.Die->getOffset(),
2569 Pubtype.Die->getTag(),
Unit.getUniqueID(),
2570 Unit.getTag() == dwarf::DW_TAG_type_unit);
2582void DWARFLinker::patchFrameInfoForObject(LinkContext &
Context) {
2583 DWARFContext &OrigDwarf = *
Context.File.Dwarf;
2584 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2586 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2591 for (std::unique_ptr<CompileUnit> &Unit :
Context.CompileUnits) {
2592 for (
auto CurRange :
Unit->getFunctionRanges())
2593 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
2596 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian());
2597 uint64_t InputOffset = 0;
2601 DenseMap<uint64_t, StringRef> LocalCIES;
2603 while (
Data.isValidOffset(InputOffset)) {
2604 uint64_t EntryOffset = InputOffset;
2605 uint32_t InitialLength =
Data.getU32(&InputOffset);
2606 if (InitialLength == 0xFFFFFFFF)
2607 return reportWarning(
"Dwarf64 bits no supported",
Context.File);
2609 uint32_t CIEId =
Data.getU32(&InputOffset);
2610 if (CIEId == 0xFFFFFFFF) {
2612 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2613 LocalCIES[EntryOffset] = CIEData;
2615 InputOffset += InitialLength - 4;
2619 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2625 std::optional<AddressRangeValuePair>
Range =
2626 AllUnitsRanges.getRangeThatContains(Loc);
2629 InputOffset = EntryOffset + InitialLength + 4;
2635 StringRef CIEData = LocalCIES[CIEId];
2636 if (CIEData.empty())
2637 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2642 auto IteratorInserted = EmittedCIEs.insert(
2643 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2645 if (IteratorInserted.second) {
2646 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2647 IteratorInserted.first->getValue() = LastCIEOffset;
2648 TheDwarfEmitter->emitCIE(CIEData);
2654 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2655 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2657 FrameData.substr(InputOffset, FDERemainingBytes));
2658 InputOffset += FDERemainingBytes;
2662uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2664 const DWARFFile &File,
2665 int ChildRecurseDepth) {
2666 const char *
Name =
nullptr;
2667 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2668 CompileUnit *CU = &
U;
2669 std::optional<DWARFFormValue>
Ref;
2675 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2676 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2684 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2686 OrigUnit = &RefCU->getOrigUnit();
2691 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2692 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2693 Name =
"(anonymous namespace)";
2695 if (CU->getInfo(Idx).ParentIdx == 0 ||
2697 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
2698 dwarf::DW_TAG_module)
2699 return djbHash(Name ? Name :
"",
djbHash(ChildRecurseDepth ?
"" :
"::"));
2701 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
2710 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2719 if (ObjectPrefixMap.empty())
2723 for (
const auto &Entry : ObjectPrefixMap)
2726 return p.str().str();
2733 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2735 if (PCMFile.empty())
2738 if (ObjectPrefixMap)
2739 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2744std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2745 std::string &PCMFile,
2746 LinkContext &Context,
2749 if (PCMFile.empty())
2750 return std::make_pair(
false,
false);
2755 std::string Name =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2758 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2760 return std::make_pair(
true,
true);
2763 if (!
Quiet && Options.Verbose) {
2765 outs() <<
"Found clang module reference " << PCMFile;
2768 auto Cached = ClangModules.find(PCMFile);
2769 if (Cached != ClangModules.end()) {
2773 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2774 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2775 "different version of the module ") +
2778 if (!
Quiet && Options.Verbose)
2779 outs() <<
" [cached].\n";
2780 return std::make_pair(
true,
true);
2783 return std::make_pair(
true,
false);
2786bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2791 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2792 std::pair<bool, bool> IsClangModuleRef =
2793 isClangModuleRef(CUDie, PCMFile,
Context, Indent,
false);
2795 if (!IsClangModuleRef.first)
2798 if (IsClangModuleRef.second)
2801 if (Options.Verbose)
2806 ClangModules.insert({PCMFile,
getDwoId(CUDie)});
2808 if (
Error E = loadClangModule(Loader, CUDie, PCMFile,
Context, OnCUDieLoaded,
2816Error DWARFLinker::loadClangModule(
2817 ObjFileLoaderTy Loader,
const DWARFDie &CUDie,
const std::string &PCMFile,
2821 std::string ModuleName =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2824 SmallString<0>
Path(Options.PrependPath);
2831 if (Loader ==
nullptr) {
2832 reportError(
"Could not load clang module: loader is not specified.\n",
2837 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2841 std::unique_ptr<CompileUnit>
Unit;
2842 for (
const auto &CU : ErrOrObj->Dwarf->compile_units()) {
2845 auto ChildCUDie = CU->getUnitDIE();
2848 if (!registerModuleReference(ChildCUDie,
Context, Loader, OnCUDieLoaded,
2853 ": Clang modules are expected to have exactly 1 compile unit.\n");
2854 reportError(Err,
Context.File);
2860 uint64_t PCMDwoId =
getDwoId(ChildCUDie);
2861 if (PCMDwoId != DwoId) {
2862 if (Options.Verbose)
2864 Twine(
"hash mismatch: this object file was built against a "
2865 "different version of the module ") +
2869 ClangModules[PCMFile] = PCMDwoId;
2873 Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR,
2879 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2884Expected<uint64_t> DWARFLinker::DIECloner::cloneAllCompileUnits(
2885 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2886 uint64_t OutputDebugInfoSize =
2888 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2890 for (
auto &CurrentUnit : CompileUnits) {
2891 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2892 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2893 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2894 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2896 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2899 if (CurrentUnit->getInfo(0).Keep) {
2902 CurrentUnit->createOutputDIE();
2903 rememberUnitForMacroOffset(*CurrentUnit);
2904 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2905 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2908 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2912 if (
Error E = generateLineTableForUnit(*CurrentUnit))
2915 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2920 if (
Error E = Linker.generateUnitRanges(*CurrentUnit, File, AddrPool))
2923 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2924 SmallVectorImpl<uint8_t> &OutBytes,
2925 int64_t RelocAdjustment) {
2926 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2927 DataExtractor
Data(SrcBytes, IsLittleEndian);
2928 cloneExpression(
Data,
2929 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2930 OrigUnit.getFormParams().Format),
2931 File, *CurrentUnit, OutBytes, RelocAdjustment,
2934 if (
Error E = generateUnitLocations(*CurrentUnit, File, ProcessExpr))
2936 if (
Error E = emitDebugAddrSection(*CurrentUnit, DwarfVersion))
2945 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2948 for (
auto &CurrentUnit : CompileUnits) {
2949 CurrentUnit->fixupForwardReferences();
2951 if (!CurrentUnit->getOutputUnitDIE())
2954 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2957 CurrentUnit->getStartOffset());
2958 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2959 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2961 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2965 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2968void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2969 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getLocSection().Data,
2971 TheDwarfEmitter->emitSectionContents(
2972 Dwarf.getDWARFObj().getRangesSection().Data,
2974 TheDwarfEmitter->emitSectionContents(
2976 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getArangesSection(),
2978 TheDwarfEmitter->emitSectionContents(
2980 TheDwarfEmitter->emitSectionContents(
2981 Dwarf.getDWARFObj().getRnglistsSection().Data,
2983 TheDwarfEmitter->emitSectionContents(
2984 Dwarf.getDWARFObj().getLoclistsSection().Data,
2990 ObjectContexts.emplace_back(LinkContext(File));
2992 if (ObjectContexts.back().File.Dwarf) {
2993 for (
const std::unique_ptr<DWARFUnit> &
CU :
2994 ObjectContexts.back().File.Dwarf->compile_units()) {
3003 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
3010 assert((Options.TargetDWARFVersion != 0) &&
3011 "TargetDWARFVersion should be set");
3015 unsigned NumObjects = ObjectContexts.size();
3027 for (LinkContext &OptContext : ObjectContexts) {
3028 if (Options.Verbose)
3029 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
3031 if (!OptContext.File.Dwarf)
3034 if (Options.VerifyInputDWARF)
3035 verifyInput(OptContext.File);
3042 !OptContext.File.Addresses->hasValidRelocs()) {
3043 if (Options.Verbose)
3044 outs() <<
"No valid relocations found. Skipping.\n";
3048 OptContext.Skip =
true;
3053 if (!OptContext.File.Dwarf)
3057 if (!OptContext.File.Dwarf->types_section_units().empty()) {
3058 reportWarning(
"type units are not currently supported: file will "
3061 OptContext.Skip =
true;
3067 OptContext.CompileUnits.reserve(
3068 OptContext.File.Dwarf->getNumCompileUnits());
3069 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
3070 auto CUDie =
CU->getUnitDIE(
true);
3071 if (Options.Verbose) {
3072 outs() <<
"Input compilation unit:";
3075 DumpOpts.
Verbose = Options.Verbose;
3076 CUDie.dump(
outs(), 0, DumpOpts);
3080 for (
auto &
CU : OptContext.ModuleUnits) {
3081 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
3082 DebugLineStrPool, StringOffsetPool))
3083 reportWarning(
toString(std::move(Err)),
CU.File);
3093 (TheDwarfEmitter ==
nullptr) ? 0
3094 : TheDwarfEmitter->getDebugInfoSectionSize();
3098 std::mutex ProcessedFilesMutex;
3099 std::condition_variable ProcessedFilesConditionVariable;
3100 BitVector ProcessedFiles(NumObjects,
false);
3104 auto AnalyzeLambda = [&](
size_t I) {
3105 auto &Context = ObjectContexts[
I];
3107 if (Context.Skip || !Context.File.Dwarf)
3110 for (
const auto &
CU : Context.File.Dwarf->compile_units()) {
3113 auto CUDie =
CU->getUnitDIE(
false);
3114 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
3117 !isClangModuleRef(CUDie, PCMFile, Context, 0,
true).first) {
3118 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
3119 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
3124 for (
auto &CurrentUnit : Context.CompileUnits) {
3125 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
3129 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
3130 ModulesEndOffset, Options.ParseableSwiftInterfaces,
3132 reportWarning(Warning, Context.File, &DIE);
3145 auto &OptContext = ObjectContexts[
I];
3146 if (OptContext.Skip || !OptContext.File.Dwarf)
3155 for (
auto &CurrentUnit : OptContext.CompileUnits)
3156 CurrentUnit->markEverythingAsKept();
3157 copyInvariantDebugSection(*OptContext.File.Dwarf);
3159 for (
auto &CurrentUnit : OptContext.CompileUnits) {
3160 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
3161 CurrentUnit->getOrigUnit().getUnitDIE(),
3162 OptContext.File, *CurrentUnit, 0);
3172 if (OptContext.File.Addresses->hasValidRelocs() ||
3174 SizeByObject[OptContext.File.FileName].Input =
3177 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
3178 OptContext.CompileUnits, Options.Update, DebugStrPool,
3179 DebugLineStrPool, StringOffsetPool)
3180 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
3181 OptContext.File.Dwarf->isLittleEndian());
3186 SizeByObject[OptContext.File.FileName].Output = *SizeOrErr;
3188 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
3190 patchFrameInfoForObject(OptContext);
3193 cleanupAuxiliarryData(OptContext);
3196 auto EmitLambda = [&]() {
3198 if (TheDwarfEmitter !=
nullptr) {
3199 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
3200 TheDwarfEmitter->emitStrings(DebugStrPool);
3201 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.
getValues(),
3202 Options.TargetDWARFVersion);
3203 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
3205 switch (TableKind) {
3207 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
3208 TheDwarfEmitter->emitAppleNames(AppleNames);
3209 TheDwarfEmitter->emitAppleTypes(AppleTypes);
3210 TheDwarfEmitter->emitAppleObjc(AppleObjc);
3217 TheDwarfEmitter->emitDebugNames(DebugNames);
3224 auto AnalyzeAll = [&]() {
3225 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3228 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3229 ProcessedFiles.
set(
I);
3230 ProcessedFilesConditionVariable.notify_one();
3235 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3237 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3238 if (!ProcessedFiles[
I]) {
3239 ProcessedFilesConditionVariable.wait(
3240 LockGuard, [&]() {
return ProcessedFiles[
I]; });
3256 if (Options.Threads == 1) {
3257 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3267 Pool.
async(AnalyzeAll);
3268 Pool.
async(CloneAll, std::reference_wrapper<Error>(CE));
3275 if (Options.Statistics) {
3277 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
3278 for (
auto &
E : SizeByObject)
3279 Sorted.emplace_back(
E.first(),
E.second);
3281 return LHS.second.Output >
RHS.second.Output;
3284 auto ComputePercentange = [](int64_t
Input, int64_t Output) ->
float {
3285 const float Difference = Output -
Input;
3286 const float Sum =
Input + Output;
3289 return (Difference / (Sum / 2));
3292 int64_t InputTotal = 0;
3293 int64_t OutputTotal = 0;
3294 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
3297 outs() <<
".debug_info section size (in bytes)\n";
3298 outs() <<
"----------------------------------------------------------------"
3299 "---------------\n";
3300 outs() <<
"Filename Object "
3302 outs() <<
"----------------------------------------------------------------"
3303 "---------------\n";
3306 for (
auto &
E : Sorted) {
3307 InputTotal +=
E.second.Input;
3308 OutputTotal +=
E.second.Output;
3311 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
3314 outs() <<
"----------------------------------------------------------------"
3315 "---------------\n";
3317 ComputePercentange(InputTotal, OutputTotal));
3318 outs() <<
"----------------------------------------------------------------"
3319 "---------------\n\n";
3325Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3331 assert(Unit.Unit.get() !=
nullptr);
3333 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3338 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3343 &ODRContexts.
getRoot(), ODRContexts, 0,
3344 Options.ParseableSwiftInterfaces,
3346 reportWarning(Warning, Context.File, &DIE);
3349 Unit.Unit->markEverythingAsKept();
3353 CompileUnits.emplace_back(std::move(Unit.Unit));
3356 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3357 Options.Update, DebugStrPool, DebugLineStrPool,
3359 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3360 Unit.File.Dwarf->isLittleEndian());
3366void DWARFLinker::verifyInput(
const DWARFFile &File) {
3373 if (
Options.InputVerificationHandler)
3374 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 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?