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();
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 (Die ==
Unit.getOutputUnitDIE() &&
Unit.getOrigUnit().getVersion() >= 5 &&
2033 !AttrInfo.AttrStrOffsetBaseSeen) {
2035 Die->
addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
2036 dwarf::DW_FORM_sec_offset, DIEInteger(8));
2042 if (!Update && Die ==
Unit.getOutputUnitDIE() &&
U.getVersion() >= 5 &&
2044 OutOffset += Die->
addValue(DIEAlloc, dwarf::DW_AT_addr_base,
2045 dwarf::DW_FORM_sec_offset, DIEInteger(0))
2046 ->sizeOf(
U.getFormParams());
2053 Linker.assignAbbrev(NewAbbrev);
2059 OutOffset += AbbrevNumberSize;
2062 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2063 F.LinkedOffsetFixupVal += AbbrevNumberSize;
2065 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2066 ObjFile.Addresses->updateAndSaveValidRelocs(
2067 Unit.getOrigUnit().getVersion() >= 5,
Unit.getOrigUnit().getOffset(),
2068 F.LinkedOffsetFixupVal,
F.InputAttrStartOffset,
F.InputAttrEndOffset);
2077 for (
auto Child : InputDIE.
children()) {
2078 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
2081 OutOffset = Clone->getOffset() + Clone->getSize();
2086 OutOffset +=
sizeof(int8_t);
2095Error DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File,
2100 const auto &FunctionRanges =
Unit.getFunctionRanges();
2103 AddressRanges LinkedFunctionRanges;
2104 for (
const AddressRangeValuePair &
Range : FunctionRanges)
2105 LinkedFunctionRanges.insert(
2109 if (!LinkedFunctionRanges.empty())
2110 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
2113 std::optional<PatchLocation> UnitRngListAttribute =
2114 Unit.getUnitRangesAttribute();
2116 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
2117 std::optional<AddressRangeValuePair> CachedRange;
2118 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
2122 for (PatchLocation &AttributePatch : AllRngListAttributes) {
2125 AddressRanges LinkedRanges;
2126 if (Expected<DWARFAddressRangesVector> OriginalRanges =
2127 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
2129 for (
const auto &
Range : *OriginalRanges) {
2130 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
2131 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
2135 reportWarning(
"inconsistent range data.", File);
2140 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
2141 Range.HighPC + CachedRange->Value});
2145 reportWarning(
"invalid range list ignored.", File);
2149 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2150 Unit, LinkedRanges, AttributePatch, AddrPool))
2155 if (UnitRngListAttribute.has_value())
2156 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2157 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool))
2161 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
2167Error DWARFLinker::DIECloner::generateUnitLocations(
2168 CompileUnit &Unit,
const DWARFFile &File,
2169 ExpressionHandlerRef ExprHandler) {
2174 Unit.getLocationAttributes();
2176 if (AllLocListAttributes.empty())
2182 for (
auto &CurLocAttr : AllLocListAttributes) {
2185 Expected<DWARFLocationExpressionsVector> OriginalLocations =
2186 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
2188 if (!OriginalLocations) {
2190 Linker.reportWarning(
"Invalid location attribute ignored.", File);
2195 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
2196 DWARFLocationExpression LinkedExpression;
2198 if (CurExpression.Range) {
2200 LinkedExpression.Range = {
2201 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
2202 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
2206 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
2207 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
2208 CurLocAttr.RelocAdjustment);
2210 LinkedLocationExpressions.push_back(LinkedExpression);
2215 Unit, LinkedLocationExpressions, CurLocAttr, AddrPool))
2220 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
2226 for (
auto &V : Die.
values())
2227 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
2235Error DWARFLinker::DIECloner::emitDebugAddrSection(
2236 CompileUnit &Unit,
const uint16_t DwarfVersion)
const {
2241 if (DwarfVersion < 5)
2246 DIE *OutputUnitDIE = Unit.getOutputUnitDIE();
2247 if (OutputUnitDIE ==
nullptr)
2250 MCSymbol *EndLabel =
Emitter->emitDwarfDebugAddrsHeader(Unit);
2252 dwarf::FormParams
FP = Unit.getOrigUnit().getFormParams();
2253 if (AddrOffset >
FP.getDwarfMaxOffset())
2258 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),
2259 Unit.getOrigUnit().getAddressByteSize());
2260 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
2278 std::vector<TrackedRow> &Rows) {
2284 Seq.front().isStartSeqInOutput =
true;
2286 if (!Rows.empty() && Rows.back().Row.Address < Seq.front().Row.Address) {
2294 Rows, [=](
const TrackedRow &O) {
return O.Row.Address < Front; });
2303 Rows.insert(
InsertPoint + 1, Seq.begin() + 1, Seq.end());
2312 for (
auto &V : Die.
values())
2313 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2321void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2322 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2323 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2325 if (std::optional<uint64_t> MacroAttr =
2327 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2331 if (std::optional<uint64_t> MacroAttr =
2333 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2338Error DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2343 DWARFDie CUDie =
Unit.getOrigUnit().getUnitDIE();
2349 if (
auto *OutputDIE =
Unit.getOutputUnitDIE()) {
2351 dwarf::FormParams
FP =
Unit.getOrigUnit().getFormParams();
2352 if (StmtOffset >
FP.getDwarfMaxOffset())
2359 if (
const DWARFDebugLine::LineTable *LT =
2360 ObjFile.Dwarf->getLineTableForUnit(&
Unit.getOrigUnit())) {
2362 DWARFDebugLine::LineTable LineTable;
2365 LineTable.Prologue =
LT->Prologue;
2368 if (
Linker.Options.Update) {
2369 LineTable.Rows =
LT->Rows;
2372 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2373 LineTable.Rows.clear();
2375 LineTable.Sequences =
LT->Sequences;
2377 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2381 std::vector<TrackedRow> InputRows;
2382 InputRows.reserve(
LT->Rows.size());
2383 for (
size_t i = 0; i <
LT->Rows.size(); i++)
2384 InputRows.emplace_back(TrackedRow{LT->Rows[i], i, false});
2387 std::vector<TrackedRow> OutputRows;
2388 OutputRows.reserve(InputRows.size());
2392 std::vector<TrackedRow> Seq;
2393 Seq.reserve(InputRows.size());
2395 const auto &FunctionRanges =
Unit.getFunctionRanges();
2396 std::optional<AddressRangeValuePair> CurrRange;
2409 for (
size_t i = 0; i < InputRows.size(); i++) {
2410 TrackedRow
TR = InputRows[i];
2417 if (!CurrRange || !CurrRange->Range.contains(
TR.Row.Address.Address)) {
2421 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2423 FunctionRanges.getRangeThatContains(
TR.Row.Address.Address);
2424 if (StopAddress != -1ULL && !Seq.empty()) {
2427 auto NextLine = Seq.back();
2428 NextLine.Row.Address.Address = StopAddress;
2429 NextLine.Row.EndSequence = 1;
2430 NextLine.Row.PrologueEnd = 0;
2431 NextLine.Row.BasicBlock = 0;
2432 NextLine.Row.EpilogueBegin = 0;
2433 Seq.push_back(NextLine);
2442 if (
TR.Row.EndSequence && Seq.empty())
2446 TR.Row.Address.Address += CurrRange->Value;
2449 if (
TR.Row.EndSequence)
2460 if (!OutputRows.empty()) {
2461 OutputRows[0].isStartSeqInOutput =
true;
2462 for (
size_t i = 1; i < OutputRows.size(); ++i)
2463 OutputRows[i].isStartSeqInOutput = OutputRows[i - 1].Row.EndSequence;
2467 LineTable.Rows.clear();
2468 LineTable.Rows.reserve(OutputRows.size());
2469 for (
auto &TR : OutputRows)
2470 LineTable.Rows.push_back(
TR.Row);
2474 std::vector<uint64_t> OutputRowOffsets;
2478 bool hasStmtSeq =
Unit.getStmtSeqListAttributes().size() > 0;
2479 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2481 hasStmtSeq ? &OutputRowOffsets :
nullptr);
2484 assert(OutputRowOffsets.size() == OutputRows.size() &&
2485 "must have an offset for each row");
2488 DenseMap<uint64_t, uint64_t> SeqOffToOrigRow;
2493 if (!
LT->Rows.empty())
2501 DenseMap<size_t, size_t> OrigRowToOutputRow;
2502 std::vector<size_t> OutputRowToSeqStart(OutputRows.size());
2504 size_t CurrentSeqStart = 0;
2505 for (
size_t i = 0; i < OutputRows.size(); ++i) {
2507 if (OutputRows[i].isStartSeqInOutput)
2508 CurrentSeqStart = i;
2509 OutputRowToSeqStart[i] = CurrentSeqStart;
2512 OrigRowToOutputRow[OutputRows[i].OriginalRowIndex] = i;
2517 for (
const auto &StmtSeq :
Unit.getStmtSeqListAttributes()) {
2518 uint64_t OrigStmtSeq = StmtSeq.get();
2520 auto OrigRowIter = SeqOffToOrigRow.find(OrigStmtSeq);
2522 Unit.getOrigUnit().getFormParams().getDwarfMaxOffset();
2526 if (OrigRowIter == SeqOffToOrigRow.end()) {
2527 StmtSeq.set(InvalidOffset);
2530 size_t OrigRowIndex = OrigRowIter->second;
2533 auto OutputRowIter = OrigRowToOutputRow.find(OrigRowIndex);
2534 if (OutputRowIter == OrigRowToOutputRow.end()) {
2536 StmtSeq.set(InvalidOffset);
2539 size_t OutputRowIdx = OutputRowIter->second;
2544 size_t SeqStartIdx = OutputRowToSeqStart[OutputRowIdx];
2548 assert(SeqStartIdx < OutputRowOffsets.size() &&
2549 "Sequence start index out of bounds");
2550 uint64_t NewStmtSeqOffset = OutputRowOffsets[SeqStartIdx];
2553 StmtSeq.set(NewStmtSeqOffset);
2559 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2564void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2569 for (
const auto &Namespace :
Unit.getNamespaces())
2571 Unit.getStartOffset());
2573 for (
const auto &Pubname :
Unit.getPubnames())
2574 AppleNames.addName(Pubname.Name,
2575 Pubname.Die->getOffset() +
Unit.getStartOffset());
2577 for (
const auto &Pubtype :
Unit.getPubtypes())
2579 Pubtype.Name, Pubtype.Die->getOffset() +
Unit.getStartOffset(),
2580 Pubtype.Die->getTag(),
2583 Pubtype.QualifiedNameHash);
2585 for (
const auto &ObjC :
Unit.getObjC())
2586 AppleObjc.addName(ObjC.Name,
2587 ObjC.Die->getOffset() +
Unit.getStartOffset());
2590 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2591 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2594 for (
const auto &Namespace :
Unit.getNamespaces())
2599 Unit.getTag() == dwarf::DW_TAG_type_unit);
2600 for (
const auto &Pubname :
Unit.getPubnames())
2602 Pubname.Name, Pubname.Die->getOffset(),
2604 Pubname.Die->getTag(),
Unit.getUniqueID(),
2605 Unit.getTag() == dwarf::DW_TAG_type_unit);
2606 for (
const auto &Pubtype :
Unit.getPubtypes())
2608 Pubtype.Name, Pubtype.Die->getOffset(),
2610 Pubtype.Die->getTag(),
Unit.getUniqueID(),
2611 Unit.getTag() == dwarf::DW_TAG_type_unit);
2623void DWARFLinker::patchFrameInfoForObject(LinkContext &
Context) {
2624 DWARFContext &OrigDwarf = *
Context.File.Dwarf;
2625 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2627 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2632 for (std::unique_ptr<CompileUnit> &Unit :
Context.CompileUnits) {
2633 for (
auto CurRange :
Unit->getFunctionRanges())
2634 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
2637 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian());
2642 DenseMap<uint64_t, StringRef> LocalCIES;
2644 while (
Data.isValidOffset(InputOffset)) {
2645 uint64_t EntryOffset = InputOffset;
2646 uint32_t InitialLength =
Data.getU32(&InputOffset);
2647 if (InitialLength == 0xFFFFFFFF)
2648 return reportWarning(
"Dwarf64 bits no supported",
Context.File);
2650 uint32_t CIEId =
Data.getU32(&InputOffset);
2651 if (CIEId == 0xFFFFFFFF) {
2653 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2654 LocalCIES[EntryOffset] = CIEData;
2656 InputOffset += InitialLength - 4;
2660 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2666 std::optional<AddressRangeValuePair>
Range =
2667 AllUnitsRanges.getRangeThatContains(Loc);
2670 InputOffset = EntryOffset + InitialLength + 4;
2676 StringRef CIEData = LocalCIES[CIEId];
2677 if (CIEData.empty())
2678 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2683 auto IteratorInserted = EmittedCIEs.insert(
2684 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2686 if (IteratorInserted.second) {
2687 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2688 IteratorInserted.first->getValue() = LastCIEOffset;
2689 TheDwarfEmitter->emitCIE(CIEData);
2695 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2696 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2698 FrameData.substr(InputOffset, FDERemainingBytes));
2699 InputOffset += FDERemainingBytes;
2703uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2705 const DWARFFile &File,
2706 int ChildRecurseDepth) {
2707 const char *
Name =
nullptr;
2708 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2709 CompileUnit *CU = &
U;
2710 std::optional<DWARFFormValue>
Ref;
2716 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2717 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2725 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2727 OrigUnit = &RefCU->getOrigUnit();
2732 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2733 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2734 Name =
"(anonymous namespace)";
2736 if (CU->getInfo(Idx).ParentIdx == 0 ||
2738 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
2739 dwarf::DW_TAG_module)
2740 return djbHash(Name ? Name :
"",
djbHash(ChildRecurseDepth ?
"" :
"::"));
2742 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
2751 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2760 if (ObjectPrefixMap.empty())
2764 for (
const auto &Entry : ObjectPrefixMap)
2767 return p.str().str();
2774 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2776 if (PCMFile.empty())
2779 if (ObjectPrefixMap)
2780 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2785std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2786 std::string &PCMFile,
2787 LinkContext &Context,
2790 if (PCMFile.empty())
2791 return std::make_pair(
false,
false);
2796 std::string Name =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2799 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2801 return std::make_pair(
true,
true);
2804 if (!
Quiet && Options.Verbose) {
2806 outs() <<
"Found clang module reference " << PCMFile;
2809 auto Cached = ClangModules.find(PCMFile);
2810 if (Cached != ClangModules.end()) {
2814 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2815 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2816 "different version of the module ") +
2819 if (!
Quiet && Options.Verbose)
2820 outs() <<
" [cached].\n";
2821 return std::make_pair(
true,
true);
2824 return std::make_pair(
true,
false);
2827bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2832 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2833 std::pair<bool, bool> IsClangModuleRef =
2834 isClangModuleRef(CUDie, PCMFile,
Context, Indent,
false);
2836 if (!IsClangModuleRef.first)
2839 if (IsClangModuleRef.second)
2842 if (Options.Verbose)
2847 ClangModules.insert({PCMFile,
getDwoId(CUDie)});
2849 if (
Error E = loadClangModule(Loader, CUDie, PCMFile,
Context, OnCUDieLoaded,
2857Error DWARFLinker::loadClangModule(
2858 ObjFileLoaderTy Loader,
const DWARFDie &CUDie,
const std::string &PCMFile,
2862 std::string ModuleName =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2865 SmallString<0>
Path(Options.PrependPath);
2872 if (Loader ==
nullptr) {
2873 reportError(
"Could not load clang module: loader is not specified.\n",
2878 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2882 std::unique_ptr<CompileUnit>
Unit;
2883 for (
const auto &CU : ErrOrObj->Dwarf->compile_units()) {
2886 auto ChildCUDie = CU->getUnitDIE();
2889 if (!registerModuleReference(ChildCUDie,
Context, Loader, OnCUDieLoaded,
2894 ": Clang modules are expected to have exactly 1 compile unit.\n");
2895 reportError(Err,
Context.File);
2902 if (PCMDwoId != DwoId) {
2903 if (Options.Verbose)
2905 Twine(
"hash mismatch: this object file was built against a "
2906 "different version of the module ") +
2910 ClangModules[PCMFile] = PCMDwoId;
2914 Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR,
2920 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2925Expected<uint64_t> DWARFLinker::DIECloner::cloneAllCompileUnits(
2926 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2929 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2931 for (
auto &CurrentUnit : CompileUnits) {
2932 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2933 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2934 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2935 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2937 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2940 if (CurrentUnit->getInfo(0).Keep) {
2943 CurrentUnit->createOutputDIE();
2944 rememberUnitForMacroOffset(*CurrentUnit);
2945 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2946 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2949 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2953 if (
Error E = generateLineTableForUnit(*CurrentUnit))
2956 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2961 if (
Error E =
Linker.generateUnitRanges(*CurrentUnit, File, AddrPool))
2964 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2965 SmallVectorImpl<uint8_t> &OutBytes,
2966 int64_t RelocAdjustment) {
2967 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2968 DataExtractor
Data(SrcBytes, IsLittleEndian);
2969 cloneExpression(
Data,
2970 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2971 OrigUnit.getFormParams().Format),
2972 File, *CurrentUnit, OutBytes, RelocAdjustment,
2975 if (
Error E = generateUnitLocations(*CurrentUnit, File, ProcessExpr))
2977 if (
Error E = emitDebugAddrSection(*CurrentUnit, DwarfVersion))
2986 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2989 for (
auto &CurrentUnit : CompileUnits) {
2990 CurrentUnit->fixupForwardReferences();
2992 if (!CurrentUnit->getOutputUnitDIE())
2995 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2998 CurrentUnit->getStartOffset());
2999 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
3000 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
3002 CurrentUnit->computeNextUnitOffset(DwarfVersion));
3006 return OutputDebugInfoSize - StartOutputDebugInfoSize;
3009void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
3010 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getLocSection().Data,
3012 TheDwarfEmitter->emitSectionContents(
3013 Dwarf.getDWARFObj().getRangesSection().Data,
3015 TheDwarfEmitter->emitSectionContents(
3017 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getArangesSection(),
3019 TheDwarfEmitter->emitSectionContents(
3021 TheDwarfEmitter->emitSectionContents(
3022 Dwarf.getDWARFObj().getRnglistsSection().Data,
3024 TheDwarfEmitter->emitSectionContents(
3025 Dwarf.getDWARFObj().getLoclistsSection().Data,
3031 ObjectContexts.emplace_back(LinkContext(File));
3033 if (ObjectContexts.back().File.Dwarf) {
3034 for (
const std::unique_ptr<DWARFUnit> &
CU :
3035 ObjectContexts.back().File.Dwarf->compile_units()) {
3044 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
3051 assert((Options.TargetDWARFVersion != 0) &&
3052 "TargetDWARFVersion should be set");
3056 unsigned NumObjects = ObjectContexts.size();
3068 for (LinkContext &OptContext : ObjectContexts) {
3069 if (Options.Verbose)
3070 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
3072 if (!OptContext.File.Dwarf)
3075 if (Options.VerifyInputDWARF)
3076 verifyInput(OptContext.File);
3083 !OptContext.File.Addresses->hasValidRelocs()) {
3084 if (Options.Verbose)
3085 outs() <<
"No valid relocations found. Skipping.\n";
3089 OptContext.Skip =
true;
3094 if (!OptContext.File.Dwarf)
3098 if (!OptContext.File.Dwarf->types_section_units().empty()) {
3099 reportWarning(
"type units are not currently supported: file will "
3102 OptContext.Skip =
true;
3108 OptContext.CompileUnits.reserve(
3109 OptContext.File.Dwarf->getNumCompileUnits());
3110 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
3111 auto CUDie =
CU->getUnitDIE(
true);
3112 if (Options.Verbose) {
3113 outs() <<
"Input compilation unit:";
3116 DumpOpts.
Verbose = Options.Verbose;
3117 CUDie.dump(
outs(), 0, DumpOpts);
3121 for (
auto &
CU : OptContext.ModuleUnits) {
3122 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
3123 DebugLineStrPool, StringOffsetPool))
3124 reportWarning(
toString(std::move(Err)),
CU.File);
3134 (TheDwarfEmitter ==
nullptr) ? 0
3135 : TheDwarfEmitter->getDebugInfoSectionSize();
3139 std::mutex ProcessedFilesMutex;
3140 std::condition_variable ProcessedFilesConditionVariable;
3141 BitVector ProcessedFiles(NumObjects,
false);
3145 auto AnalyzeLambda = [&](
size_t I) {
3146 auto &Context = ObjectContexts[
I];
3148 if (Context.Skip || !Context.File.Dwarf)
3151 for (
const auto &
CU : Context.File.Dwarf->compile_units()) {
3154 auto CUDie =
CU->getUnitDIE(
false);
3155 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
3158 !isClangModuleRef(CUDie, PCMFile, Context, 0,
true).first) {
3159 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
3160 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
3165 for (
auto &CurrentUnit : Context.CompileUnits) {
3166 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
3170 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
3171 ModulesEndOffset, Options.ParseableSwiftInterfaces,
3173 reportWarning(Warning, Context.File, &DIE);
3186 auto &OptContext = ObjectContexts[
I];
3187 if (OptContext.Skip || !OptContext.File.Dwarf)
3196 for (
auto &CurrentUnit : OptContext.CompileUnits)
3197 CurrentUnit->markEverythingAsKept();
3198 copyInvariantDebugSection(*OptContext.File.Dwarf);
3200 for (
auto &CurrentUnit : OptContext.CompileUnits) {
3201 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
3202 CurrentUnit->getOrigUnit().getUnitDIE(),
3203 OptContext.File, *CurrentUnit, 0);
3213 if (OptContext.File.Addresses->hasValidRelocs() ||
3215 SizeByObject[OptContext.File.FileName].Input =
3218 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
3219 OptContext.CompileUnits, Options.Update, DebugStrPool,
3220 DebugLineStrPool, StringOffsetPool)
3221 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
3222 OptContext.File.Dwarf->isLittleEndian());
3227 SizeByObject[OptContext.File.FileName].Output = *SizeOrErr;
3229 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
3231 patchFrameInfoForObject(OptContext);
3234 cleanupAuxiliarryData(OptContext);
3237 auto EmitLambda = [&]() {
3239 if (TheDwarfEmitter !=
nullptr) {
3240 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
3241 TheDwarfEmitter->emitStrings(DebugStrPool);
3242 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.
getValues(),
3243 Options.TargetDWARFVersion);
3244 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
3246 switch (TableKind) {
3248 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
3249 TheDwarfEmitter->emitAppleNames(AppleNames);
3250 TheDwarfEmitter->emitAppleTypes(AppleTypes);
3251 TheDwarfEmitter->emitAppleObjc(AppleObjc);
3258 TheDwarfEmitter->emitDebugNames(DebugNames);
3265 auto AnalyzeAll = [&]() {
3266 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3269 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3270 ProcessedFiles.
set(
I);
3271 ProcessedFilesConditionVariable.notify_one();
3276 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3278 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3279 if (!ProcessedFiles[
I]) {
3280 ProcessedFilesConditionVariable.wait(
3281 LockGuard, [&]() {
return ProcessedFiles[
I]; });
3297 if (Options.Threads == 1) {
3298 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3308 Pool.
async(AnalyzeAll);
3309 Pool.
async(CloneAll, std::reference_wrapper<Error>(CE));
3316 if (Options.Statistics) {
3318 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
3319 for (
auto &
E : SizeByObject)
3320 Sorted.emplace_back(
E.first(),
E.second);
3322 return LHS.second.Output >
RHS.second.Output;
3325 auto ComputePercentange = [](int64_t
Input, int64_t Output) ->
float {
3326 const float Difference = Output -
Input;
3327 const float Sum =
Input + Output;
3330 return (Difference / (Sum / 2));
3333 int64_t InputTotal = 0;
3334 int64_t OutputTotal = 0;
3335 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
3338 outs() <<
".debug_info section size (in bytes)\n";
3339 outs() <<
"----------------------------------------------------------------"
3340 "---------------\n";
3341 outs() <<
"Filename Object "
3343 outs() <<
"----------------------------------------------------------------"
3344 "---------------\n";
3347 for (
auto &
E : Sorted) {
3348 InputTotal +=
E.second.Input;
3349 OutputTotal +=
E.second.Output;
3352 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
3355 outs() <<
"----------------------------------------------------------------"
3356 "---------------\n";
3358 ComputePercentange(InputTotal, OutputTotal));
3359 outs() <<
"----------------------------------------------------------------"
3360 "---------------\n\n";
3366Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3372 assert(Unit.Unit.get() !=
nullptr);
3374 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3379 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3384 &ODRContexts.
getRoot(), ODRContexts, 0,
3385 Options.ParseableSwiftInterfaces,
3387 reportWarning(Warning, Context.File, &DIE);
3390 Unit.Unit->markEverythingAsKept();
3394 CompileUnits.emplace_back(std::move(Unit.Unit));
3397 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3398 Options.Update, DebugStrPool, DebugLineStrPool,
3400 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3401 Unit.File.Dwarf->isLittleEndian());
3407void DWARFLinker::verifyInput(
const DWARFFile &File) {
3414 if (
Options.InputVerificationHandler)
3415 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.
LLVM_ABI DIEValue findAttribute(dwarf::Attribute Attribute) const
Find a value in the DIE with the attribute given.
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 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?