43using namespace dwarf_linker;
44using namespace dwarf_linker::classic;
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:
154bool DWARFLinker::DIECloner::getDIENames(
const DWARFDie &Die,
155 AttributesInfo &
Info,
157 bool StripTemplate) {
161 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
164 if (!
Info.MangledName)
165 if (
const char *MangledName = Die.getLinkageName())
166 Info.MangledName = StringPool.getEntry(MangledName);
169 if (
const char *
Name = Die.getShortName())
170 Info.Name = StringPool.getEntry(
Name);
172 if (!
Info.MangledName)
175 if (StripTemplate &&
Info.Name &&
Info.MangledName !=
Info.Name) {
176 StringRef
Name =
Info.Name.getString();
178 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
181 return Info.Name ||
Info.MangledName;
195 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
196 if (
CU.getLanguage() != dwarf::DW_LANG_Swift)
199 if (!ParseableSwiftInterfaces)
203 if (!Path.ends_with(
".swiftinterface"))
208 SysRoot =
CU.getSysRoot();
209 if (!SysRoot.
empty() && Path.starts_with(SysRoot))
214 if (!DeveloperDir.
empty() && Path.starts_with(DeveloperDir))
218 std::optional<const char *>
Name =
222 auto &Entry = (*ParseableSwiftInterfaces)[*
Name];
224 DWARFDie CUDie =
CU.getOrigUnit().getUnitDIE();
229 if (!Entry.empty() && Entry != ResolvedPath)
230 ReportWarning(
Twine(
"Conflicting parseable interfaces for Swift Module ") +
231 *
Name +
": " + Entry +
" and " + Path,
233 Entry = std::string(ResolvedPath);
259 : Die(Die), ParentIdx(0), OtherInfo(OtherInfo),
Type(
T),
260 InImportedModule(
false) {}
263 bool InImportedModule)
266 InImportedModule(InImportedModule) {}
276 Info.Prune &= (Die.
getTag() == dwarf::DW_TAG_module) ||
282 if (ModulesEndOffset == 0)
283 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset();
285 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset() > 0 &&
286 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
310 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
312 std::vector<ContextWorklistItem> Worklist;
313 Worklist.emplace_back(
DIE, CurrentDeclContext, ParentIdx,
false);
315 while (!Worklist.empty()) {
319 switch (Current.
Type) {
330 unsigned Idx =
CU.getOrigUnit().getDIEIndex(Current.
Die);
345 if (Current.
Die.
getTag() == dwarf::DW_TAG_module &&
348 CU.getClangModuleName()) {
356 if (
CU.hasODR() ||
Info.InModuleScope) {
360 Current.
Context = PtrInvalidPair.getPointer();
362 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
364 Info.Ctxt->setDefinedInClangModule(
Info.InModuleScope);
375 Worklist.emplace_back(
377 Worklist.emplace_back(Child, Current.
Context,
Idx,
387 case dwarf::DW_TAG_class_type:
388 case dwarf::DW_TAG_common_block:
389 case dwarf::DW_TAG_lexical_block:
390 case dwarf::DW_TAG_structure_type:
391 case dwarf::DW_TAG_subprogram:
392 case dwarf::DW_TAG_subroutine_type:
393 case dwarf::DW_TAG_union_type:
399void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
402 for (DIEBlock *
I : DIEBlocks)
404 for (DIELoc *
I : DIELocs)
413 return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
414 DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
422 std::map<uint64_t, unsigned> LineTableMapping;
430 auto StmtAttrs = Unit.getStmtSeqListAttributes();
432 return A.get() <
B.get();
435 std::vector<unsigned> SeqStartRows;
436 SeqStartRows.push_back(0);
439 SeqStartRows.push_back(
I + 1);
471 ArrayRef SeqStartRowsRef(SeqStartRows);
476 constexpr unsigned DummyVal = UINT32_MAX;
477 LineTableMapping[DummyKey] = DummyVal;
479 for (
auto [NextSeqOff, NextRow] : LineTableMapping) {
482 auto StmtAttrSmallerThanNext = [
N = NextSeqOff](
const PatchLocation &SA) {
485 auto SeqStartSmallerThanNext = [
N = NextRow](
const unsigned &Row) {
491 while (!StmtAttrsRef.
empty() && !SeqStartRowsRef.
empty() &&
492 StmtAttrSmallerThanNext(StmtAttrsRef.
front()) &&
493 SeqStartSmallerThanNext(SeqStartRowsRef.
front())) {
500 StmtAttrsRef = StmtAttrsRef.
drop_while(StmtAttrSmallerThanNext);
501 SeqStartRowsRef = SeqStartRowsRef.
drop_while(SeqStartSmallerThanNext);
504 if (NextSeqOff != DummyKey) {
505 SeqOffToOrigRow[NextSeqOff] = NextRow;
521 if (!StmtAttrsRef.
empty() && StmtAttrsRef.
front().get() == NextSeqOff)
523 if (!SeqStartRowsRef.
empty() && SeqStartRowsRef.
front() == NextRow)
528std::pair<bool, std::optional<int64_t>>
529DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
530 const DWARFDie &DIE) {
531 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
532 DIE.getTag() == dwarf::DW_TAG_constant) &&
533 "Wrong type of input die");
535 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
538 DWARFUnit *U = DIE.getDwarfUnit();
539 std::optional<uint32_t> LocationIdx =
540 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
542 return std::make_pair(
false, std::nullopt);
546 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
549 std::optional<DWARFFormValue> LocationValue =
550 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
552 return std::make_pair(
false, std::nullopt);
557 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
559 return std::make_pair(
false, std::nullopt);
562 DataExtractor
Data(toStringRef(*Expr), U->getContext().isLittleEndian(),
563 U->getAddressByteSize());
564 DWARFExpression Expression(
Data, U->getAddressByteSize(),
565 U->getFormParams().Format);
567 bool HasLocationAddress =
false;
569 for (DWARFExpression::iterator It = Expression.begin();
570 It != Expression.end(); ++It) {
571 DWARFExpression::iterator NextIt = It;
574 const DWARFExpression::Operation &
Op = *It;
576 case dwarf::DW_OP_const2u:
577 case dwarf::DW_OP_const4u:
578 case dwarf::DW_OP_const8u:
579 case dwarf::DW_OP_const2s:
580 case dwarf::DW_OP_const4s:
581 case dwarf::DW_OP_const8s:
585 case dwarf::DW_OP_addr: {
586 HasLocationAddress =
true;
588 if (std::optional<int64_t> RelocAdjustment =
589 RelocMgr.getExprOpAddressRelocAdjustment(
590 *U,
Op, AttrOffset + CurExprOffset,
592 return std::make_pair(HasLocationAddress, *RelocAdjustment);
594 case dwarf::DW_OP_constx:
595 case dwarf::DW_OP_addrx: {
596 HasLocationAddress =
true;
597 if (std::optional<uint64_t> AddressOffset =
598 DIE.getDwarfUnit()->getIndexedAddressOffset(
601 if (std::optional<int64_t> RelocAdjustment =
602 RelocMgr.getExprOpAddressRelocAdjustment(
603 *U,
Op, *AddressOffset,
604 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
606 return std::make_pair(HasLocationAddress, *RelocAdjustment);
616 return std::make_pair(HasLocationAddress, std::nullopt);
621unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
623 CompileUnit::DIEInfo &MyInfo,
625 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
628 if (!(Flags & TF_InFunctionScope) &&
629 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
630 MyInfo.InDebugMap =
true;
631 return Flags | TF_Keep;
639 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
640 getVariableRelocAdjustment(RelocMgr, DIE);
642 if (LocExprAddrAndRelocAdjustment.first)
643 MyInfo.HasLocationExpressionAddr =
true;
645 if (!LocExprAddrAndRelocAdjustment.second)
648 MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second;
649 MyInfo.InDebugMap =
true;
651 if (((Flags & TF_InFunctionScope) &&
655 if (Options.Verbose) {
656 outs() <<
"Keeping variable DIE:";
657 DIDumpOptions DumpOpts;
658 DumpOpts.ChildRecurseDepth = 0;
659 DumpOpts.Verbose = Options.Verbose;
660 DIE.dump(
outs(), 8 , DumpOpts);
663 return Flags | TF_Keep;
668unsigned DWARFLinker::shouldKeepSubprogramDIE(
669 AddressesMap &RelocMgr,
const DWARFDie &DIE,
const DWARFFile &File,
670 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
671 Flags |= TF_InFunctionScope;
677 assert(LowPc &&
"low_pc attribute is not an address.");
678 std::optional<int64_t> RelocAdjustment =
679 RelocMgr.getSubprogramRelocAdjustment(DIE, Options.Verbose);
680 if (!RelocAdjustment)
683 MyInfo.AddrAdjust = *RelocAdjustment;
684 MyInfo.InDebugMap =
true;
686 if (Options.Verbose) {
687 outs() <<
"Keeping subprogram DIE:";
688 DIDumpOptions DumpOpts;
689 DumpOpts.ChildRecurseDepth = 0;
690 DumpOpts.Verbose = Options.Verbose;
691 DIE.dump(
outs(), 8 , DumpOpts);
694 if (DIE.getTag() == dwarf::DW_TAG_label) {
695 if (Unit.hasLabelAt(*LowPc))
698 DWARFUnit &OrigUnit = Unit.getOrigUnit();
706 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
707 return Flags | TF_Keep;
712 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
714 reportWarning(
"Function without high_pc. Range will be discarded.\n", File,
718 if (*LowPc > *HighPc) {
719 reportWarning(
"low_pc greater than high_pc. Range will be discarded.\n",
725 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
731unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr,
const DWARFDie &DIE,
732 const DWARFFile &File, CompileUnit &Unit,
733 CompileUnit::DIEInfo &MyInfo,
735 switch (DIE.getTag()) {
736 case dwarf::DW_TAG_constant:
737 case dwarf::DW_TAG_variable:
738 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
739 case dwarf::DW_TAG_subprogram:
740 case dwarf::DW_TAG_label:
741 return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags);
742 case dwarf::DW_TAG_base_type:
745 case dwarf::DW_TAG_imported_module:
746 case dwarf::DW_TAG_imported_declaration:
747 case dwarf::DW_TAG_imported_unit:
749 return Flags | TF_Keep;
763 case dwarf::DW_TAG_structure_type:
764 case dwarf::DW_TAG_class_type:
765 case dwarf::DW_TAG_union_type:
783 case dwarf::DW_TAG_typedef:
784 case dwarf::DW_TAG_member:
785 case dwarf::DW_TAG_reference_type:
786 case dwarf::DW_TAG_ptr_to_member_type:
787 case dwarf::DW_TAG_pointer_type:
804void DWARFLinker::lookForChildDIEsToKeep(
805 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
806 SmallVectorImpl<WorklistItem> &Worklist) {
813 Flags &= ~DWARFLinker::TF_ParentWalk;
817 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
822 for (
auto Child :
reverse(Die.children())) {
825 CompileUnit::DIEInfo &ChildInfo =
CU.getInfo(Child);
826 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateChildIncompleteness,
828 Worklist.emplace_back(Child,
CU, Flags);
835 if (!
Info.Ctxt || (Die.
getTag() == dwarf::DW_TAG_namespace))
838 if (!
CU.hasODR() && !
Info.InModuleScope)
841 return !
Info.Incomplete &&
Info.Ctxt !=
CU.getInfo(
Info.ParentIdx).Ctxt;
844void DWARFLinker::markODRCanonicalDie(
const DWARFDie &Die, CompileUnit &
CU) {
845 CompileUnit::DIEInfo &
Info =
CU.getInfo(Die);
847 Info.ODRMarkingDone =
true;
849 !
Info.Ctxt->hasCanonicalDIE())
850 Info.Ctxt->setHasCanonicalDIE();
855void DWARFLinker::lookForRefDIEsToKeep(
856 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
857 const UnitListTy &Units,
const DWARFFile &File,
858 SmallVectorImpl<WorklistItem> &Worklist) {
859 bool UseOdr = (
Flags & DWARFLinker::TF_DependencyWalk)
860 ? (Flags & DWARFLinker::TF_ODR)
862 DWARFUnit &Unit =
CU.getOrigUnit();
863 DWARFDataExtractor
Data = Unit.getDebugInfoExtractor();
864 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
867 SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs;
868 for (
const auto &AttrSpec : Abbrev->attributes()) {
869 DWARFFormValue Val(AttrSpec.Form);
871 AttrSpec.Attr == dwarf::DW_AT_sibling) {
873 Unit.getFormParams());
877 Val.extractValue(
Data, &
Offset, Unit.getFormParams(), &Unit);
878 CompileUnit *ReferencedCU;
880 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
881 CompileUnit::DIEInfo &
Info = ReferencedCU->getInfo(RefDie);
892 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
894 Info.Ctxt->hasCanonicalDIE())
899 Info.Ctxt->hasCanonicalDIE()))
901 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
905 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
909 for (
auto &
P :
reverse(ReferencedDIEs)) {
912 CompileUnit::DIEInfo &
Info =
P.second.getInfo(
P.first);
913 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateRefIncompleteness,
915 Worklist.emplace_back(
P.first,
P.second,
916 DWARFLinker::TF_Keep |
917 DWARFLinker::TF_DependencyWalk | ODRFlag);
922void DWARFLinker::lookForParentDIEsToKeep(
923 unsigned AncestorIdx, CompileUnit &
CU,
unsigned Flags,
924 SmallVectorImpl<WorklistItem> &Worklist) {
926 if (
CU.getInfo(AncestorIdx).Keep)
929 DWARFUnit &Unit =
CU.getOrigUnit();
930 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);
931 Worklist.emplace_back(
CU.getInfo(AncestorIdx).ParentIdx,
CU, Flags);
932 Worklist.emplace_back(ParentDIE,
CU, Flags);
960void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
962 const DWARFDie &Die,
const DWARFFile &File,
963 CompileUnit &Cu,
unsigned Flags) {
965 SmallVector<WorklistItem, 4> Worklist;
966 Worklist.emplace_back(Die, Cu, Flags);
968 while (!Worklist.empty()) {
969 WorklistItem Current = Worklist.pop_back_val();
972 switch (Current.Type) {
973 case WorklistItemType::UpdateChildIncompleteness:
976 case WorklistItemType::UpdateRefIncompleteness:
979 case WorklistItemType::LookForChildDIEsToKeep:
980 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
982 case WorklistItemType::LookForRefDIEsToKeep:
983 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
986 case WorklistItemType::LookForParentDIEsToKeep:
987 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
990 case WorklistItemType::MarkODRCanonicalDie:
991 markODRCanonicalDie(Current.Die, Current.CU);
993 case WorklistItemType::LookForDIEsToKeep:
997 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
998 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(
Idx);
1003 if (Current.Flags & TF_DependencyWalk)
1004 MyInfo.Prune =
false;
1011 bool AlreadyKept = MyInfo.Keep;
1012 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
1015 if (!(Current.Flags & TF_DependencyWalk))
1016 Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU,
1017 MyInfo, Current.Flags);
1022 if (!(Current.Flags & TF_DependencyWalk) ||
1023 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
1024 if (Current.CU.hasODR() || MyInfo.InModuleScope)
1025 Worklist.emplace_back(Current.Die, Current.CU,
1026 WorklistItemType::MarkODRCanonicalDie);
1032 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1033 WorklistItemType::LookForChildDIEsToKeep);
1035 if (AlreadyKept || !(Current.Flags & TF_Keep))
1044 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
1045 Current.Die.getTag() != dwarf::DW_TAG_member &&
1051 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1052 WorklistItemType::LookForRefDIEsToKeep);
1054 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
1055 : Current.CU.hasODR();
1056 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
1057 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
1060 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
1076 std::vector<DWARFDie> Worklist;
1077 Worklist.push_back(
CU.getOrigUnit().getUnitDIE());
1080 std::vector<BrokenLink> BrokenLinks;
1082 while (!Worklist.empty()) {
1083 const DWARFDie Current = Worklist.back();
1084 Worklist.pop_back();
1086 const bool CurrentDieIsKept =
CU.getInfo(Current).Keep;
1089 Worklist.push_back(Child);
1091 const bool ChildDieIsKept =
CU.getInfo(Child).Keep;
1092 if (!CurrentDieIsKept && ChildDieIsKept)
1093 BrokenLinks.emplace_back(Current, Child);
1097 if (!BrokenLinks.empty()) {
1100 "Found invalid link in keep chain between {0:x} and {1:x}\n",
1101 Link.Parent.getOffset(), Link.Child.getOffset());
1103 errs() <<
"Parent:";
1104 Link.Parent.dump(
errs(), 0, {});
1105 CU.getInfo(Link.Parent).dump();
1108 Link.Child.dump(
errs(), 2, {});
1109 CU.getInfo(Link.Child).dump();
1122void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
1124 FoldingSetNodeID
ID;
1127 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(
ID, InsertToken);
1132 Abbrev.setNumber(InSet->getNumber());
1135 Abbreviations.push_back(
1136 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
1137 for (
const auto &Attr : Abbrev.getData())
1138 Abbreviations.back()->AddAttribute(Attr);
1139 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
1141 Abbrev.setNumber(Abbreviations.size());
1142 Abbreviations.back()->setNumber(Abbreviations.size());
1146unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
1147 AttributeSpec AttrSpec,
1148 const DWARFFormValue &Val,
1150 AttributesInfo &
Info) {
1155 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
1160 if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
1161 Info.HasAppleOrigin =
true;
1162 if (std::optional<StringRef> FileName =
1163 ObjFile.Addresses->getLibraryInstallName()) {
1169 if (AttrSpec.Attr == dwarf::DW_AT_name)
1171 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
1172 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
1174 if (
U.getVersion() >= 5) {
1176 auto StringOffsetIndex =
1177 StringOffsetPool.getValueIndex(
StringEntry.getOffset());
1180 dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
1181 ->sizeOf(
U.getFormParams());
1184 AttrSpec.Form = dwarf::DW_FORM_strp;
1191unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
1192 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1193 unsigned AttrSize,
const DWARFFormValue &Val,
const DWARFFile &File,
1194 CompileUnit &Unit) {
1195 const DWARFUnit &
U = Unit.getOrigUnit();
1197 if (std::optional<uint64_t> Off = Val.getAsRelativeReference())
1198 Ref = Val.getUnit()->getOffset() + *
Off;
1199 else if (Off = Val.getAsDebugInfoReference(); Off)
1204 DIE *NewRefDie =
nullptr;
1205 CompileUnit *RefUnit =
nullptr;
1208 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
1211 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
1214 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
1219 RefInfo.Ctxt->getCanonicalDIEOffset()) {
1220 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
1221 "Offset to canonical die is set, but context is not marked");
1222 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
1224 dwarf::DW_FORM_ref_addr, Attr);
1225 return U.getRefAddrByteSize();
1228 if (!RefInfo.Clone) {
1231 RefInfo.UnclonedReference =
true;
1234 NewRefDie = RefInfo.Clone;
1236 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1244 if (
Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1247 RefUnit->getStartOffset() + NewRefDie->getOffset();
1248 Attr = NewRefOffset;
1250 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));
1254 Unit.noteForwardReference(
1255 NewRefDie, RefUnit, RefInfo.Ctxt,
1257 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
1259 return U.getRefAddrByteSize();
1263 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1268void DWARFLinker::DIECloner::cloneExpression(
1269 DataExtractor &
Data, DWARFExpression Expression,
const DWARFFile &File,
1270 CompileUnit &Unit, SmallVectorImpl<uint8_t> &
OutputBuffer,
1271 int64_t AddrRelocAdjustment,
bool IsLittleEndian) {
1274 uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize();
1277 for (
auto &
Op : Expression) {
1283 Desc.
Op[0] != Encoding::Size1))
1284 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
1288 Desc.
Op[0] == Encoding::Size1)) {
1308 if (RefOffset > 0 ||
Op.
getCode() != dwarf::DW_OP_convert) {
1309 RefOffset += Unit.getOrigUnit().getOffset();
1310 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
1311 CompileUnit::DIEInfo &
Info = Unit.getInfo(RefDie);
1312 if (DIE *Clone =
Info.Clone)
1313 Offset = Clone->getOffset();
1315 Linker.reportWarning(
1316 "base type ref doesn't point to DW_TAG_base_type.", File);
1320 if (RealSize > ULEBsize) {
1323 Linker.reportWarning(
"base type ref doesn't fit.", File);
1325 assert(RealSize == ULEBsize &&
"padding failed");
1326 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1327 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1328 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_addrx) {
1329 if (std::optional<object::SectionedAddress> SA =
1330 Unit.getOrigUnit().getAddrOffsetSectionItem(
1337 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1340 ArrayRef<uint8_t> AddressBytes(
1341 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1342 OrigAddressByteSize);
1343 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1345 Linker.reportWarning(
"cannot read DW_OP_addrx operand.", File);
1346 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_constx) {
1347 if (std::optional<object::SectionedAddress> SA =
1348 Unit.getOrigUnit().getAddrOffsetSectionItem(
1354 std::optional<uint8_t> OutOperandKind;
1355 switch (OrigAddressByteSize) {
1357 OutOperandKind = dwarf::DW_OP_const4u;
1360 OutOperandKind = dwarf::DW_OP_const8u;
1363 Linker.reportWarning(
1364 formatv((
"unsupported address size: {0}."), OrigAddressByteSize),
1369 if (OutOperandKind) {
1371 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1374 ArrayRef<uint8_t> AddressBytes(
1375 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1376 OrigAddressByteSize);
1377 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1380 Linker.reportWarning(
"cannot read DW_OP_constx operand.", File);
1390unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1391 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1392 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1393 bool IsLittleEndian) {
1396 DIELoc *Loc =
nullptr;
1397 DIEBlock *
Block =
nullptr;
1398 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1399 Loc =
new (DIEAlloc) DIELoc;
1400 Linker.DIELocs.push_back(Loc);
1402 Block =
new (DIEAlloc) DIEBlock;
1403 Linker.DIEBlocks.push_back(
Block);
1405 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1406 :
static_cast<DIEValueList *
>(
Block);
1408 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1411 SmallVector<uint8_t, 32> Buffer;
1412 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1416 DataExtractor
Data(StringRef((
const char *)Bytes.data(), Bytes.size()),
1417 IsLittleEndian, OrigUnit.getAddressByteSize());
1418 DWARFExpression Expr(
Data, OrigUnit.getAddressByteSize(),
1419 OrigUnit.getFormParams().Format);
1420 cloneExpression(
Data, Expr, File, Unit, Buffer,
1421 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);
1424 for (
auto Byte : Bytes)
1426 dwarf::DW_FORM_data1, DIEInteger(Byte));
1432 Loc->setSize(Bytes.size());
1434 Block->setSize(Bytes.size());
1442 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&
1443 (Bytes.size() > UINT8_MAX)) ||
1444 (AttrSpec.Form == dwarf::DW_FORM_block2 &&
1445 (Bytes.size() > UINT16_MAX)) ||
1446 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))
1447 AttrSpec.Form = dwarf::DW_FORM_block;
1453 return Die.addValue(DIEAlloc, Value)->sizeOf(OrigUnit.getFormParams());
1456unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1457 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1458 unsigned AttrSize,
const DWARFFormValue &Val,
const CompileUnit &Unit,
1459 AttributesInfo &
Info) {
1460 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1461 Info.HasLowPc =
true;
1465 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1481 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1485 std::optional<uint64_t>
Addr = AddrAttribute->getAsAddress();
1487 Linker.reportWarning(
"Cann't read address attribute value.", ObjFile);
1491 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1492 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1493 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
1497 }
else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1498 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1499 if (
uint64_t HighPc = Unit.getHighPc())
1507 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
1509 AttrSpec.Form, DIEInteger(*
Addr));
1510 return Unit.getOrigUnit().getAddressByteSize();
1513 auto AddrIndex = AddrPool.getValueIndex(*
Addr);
1517 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))
1518 ->sizeOf(Unit.getOrigUnit().getFormParams());
1521unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1522 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1523 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1524 unsigned AttrSize, AttributesInfo &
Info) {
1529 if (AttrSpec.Attr == dwarf::DW_AT_GNU_dwo_id ||
1530 AttrSpec.Attr == dwarf::DW_AT_dwo_id)
1535 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1536 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1543 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1544 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1551 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1555 Info.AttrStrOffsetBaseSeen =
true;
1557 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1558 dwarf::DW_FORM_sec_offset, DIEInteger(8))
1559 ->sizeOf(Unit.getOrigUnit().getFormParams());
1562 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
1565 dwarf::DW_FORM_sec_offset,
1566 DIEInteger(*Val.getAsSectionOffset()));
1569 Unit.noteStmtSeqListAttribute(Patch);
1571 return Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1575 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1576 Value = *OptionalValue;
1577 else if (
auto OptionalValue = Val.getAsSignedConstant())
1578 Value = *OptionalValue;
1579 else if (
auto OptionalValue = Val.getAsSectionOffset())
1580 Value = *OptionalValue;
1582 Linker.reportWarning(
1583 "Unsupported scalar attribute form. Dropping attribute.", File,
1587 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1588 Info.IsDeclaration =
true;
1590 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1599 [[maybe_unused]]
dwarf::Form OriginalForm = AttrSpec.Form;
1600 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1604 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1606 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1610 std::optional<uint64_t>
Offset =
1611 Unit.getOrigUnit().getRnglistOffset(*
Index);
1613 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1619 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1620 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1621 }
else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1625 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1627 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1631 std::optional<uint64_t>
Offset =
1632 Unit.getOrigUnit().getLoclistOffset(*
Index);
1634 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1640 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1641 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1642 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1643 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1644 std::optional<uint64_t> LowPC = Unit.getLowPc();
1648 Value = Unit.getHighPc() - *LowPC;
1649 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1650 Value = *Val.getAsSectionOffset();
1651 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1652 Value = *Val.getAsSignedConstant();
1653 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1654 Value = *OptionalValue;
1656 Linker.reportWarning(
1657 "Unsupported scalar attribute form. Dropping attribute.", File,
1662 DIE::value_iterator Patch =
1665 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1666 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1667 Unit.noteRangeAttribute(Die, Patch);
1668 Info.HasRanges =
true;
1672 Unit.getOrigUnit().getVersion())) {
1674 CompileUnit::DIEInfo &LocationDieInfo = Unit.getInfo(InputDIE);
1675 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
1676 ? LocationDieInfo.AddrAdjust
1678 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1679 Info.IsDeclaration =
true;
1682 assert((
Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1683 "Unhandled DW_FORM_rnglistx attribute");
1691unsigned DWARFLinker::DIECloner::cloneAttribute(
1692 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1693 CompileUnit &Unit,
const DWARFFormValue &Val,
const AttributeSpec AttrSpec,
1694 unsigned AttrSize, AttributesInfo &
Info,
bool IsLittleEndian) {
1695 const DWARFUnit &
U = Unit.getOrigUnit();
1697 switch (AttrSpec.Form) {
1698 case dwarf::DW_FORM_strp:
1699 case dwarf::DW_FORM_line_strp:
1700 case dwarf::DW_FORM_string:
1701 case dwarf::DW_FORM_strx:
1702 case dwarf::DW_FORM_strx1:
1703 case dwarf::DW_FORM_strx2:
1704 case dwarf::DW_FORM_strx3:
1705 case dwarf::DW_FORM_strx4:
1706 return cloneStringAttribute(Die, AttrSpec, Val, U,
Info);
1707 case dwarf::DW_FORM_ref_addr:
1708 case dwarf::DW_FORM_ref1:
1709 case dwarf::DW_FORM_ref2:
1710 case dwarf::DW_FORM_ref4:
1711 case dwarf::DW_FORM_ref8:
1712 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1714 case dwarf::DW_FORM_block:
1715 case dwarf::DW_FORM_block1:
1716 case dwarf::DW_FORM_block2:
1717 case dwarf::DW_FORM_block4:
1718 case dwarf::DW_FORM_exprloc:
1719 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1721 case dwarf::DW_FORM_addr:
1722 case dwarf::DW_FORM_addrx:
1723 case dwarf::DW_FORM_addrx1:
1724 case dwarf::DW_FORM_addrx2:
1725 case dwarf::DW_FORM_addrx3:
1726 case dwarf::DW_FORM_addrx4:
1727 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1729 case dwarf::DW_FORM_data1:
1730 case dwarf::DW_FORM_data2:
1731 case dwarf::DW_FORM_data4:
1732 case dwarf::DW_FORM_data8:
1733 case dwarf::DW_FORM_udata:
1734 case dwarf::DW_FORM_sdata:
1735 case dwarf::DW_FORM_sec_offset:
1736 case dwarf::DW_FORM_flag:
1737 case dwarf::DW_FORM_flag_present:
1738 case dwarf::DW_FORM_rnglistx:
1739 case dwarf::DW_FORM_loclistx:
1740 case dwarf::DW_FORM_implicit_const:
1741 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1744 Linker.reportWarning(
"Unsupported attribute form " +
1746 " in cloneAttribute. Dropping.",
1753void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1755 DwarfStringPoolEntryRef
Name,
1757 bool SkipPubSection) {
1758 std::optional<ObjCSelectorNames> Names =
1762 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),
1764 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),
1766 if (Names->ClassNameNoCategory)
1767 Unit.addObjCAccelerator(
1768 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);
1769 if (Names->MethodNameNoCategory)
1770 Unit.addNameAccelerator(
1771 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);
1778 switch (AttrSpec.
Attr) {
1781 case dwarf::DW_AT_low_pc:
1782 case dwarf::DW_AT_high_pc:
1783 case dwarf::DW_AT_ranges:
1784 return !Update && SkipPC;
1785 case dwarf::DW_AT_rnglists_base:
1791 case dwarf::DW_AT_loclists_base:
1797 case dwarf::DW_AT_location:
1798 case dwarf::DW_AT_frame_base:
1799 return !Update && SkipPC;
1809DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1811 int64_t PCOffset,
uint32_t OutOffset,
1812 unsigned Flags,
bool IsLittleEndian,
1815 unsigned Idx = U.getDIEIndex(InputDIE);
1819 if (!Unit.getInfo(
Idx).Keep)
1823 assert(!(Die &&
Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1835 (
Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1836 if (!
Info.Ctxt->hasCanonicalDIE())
1837 Info.Ctxt->setHasCanonicalDIE();
1841 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1845 DWARFDataExtractor
Data =
U.getDebugInfoExtractor();
1850 ?
U.getDIEAtIndex(
Idx + 1).getOffset()
1851 :
U.getNextUnitOffset();
1852 AttributesInfo AttrInfo;
1857 SmallString<40> DIECopy(
Data.getData().substr(
Offset, NextOffset -
Offset));
1859 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1862 ObjFile.Addresses->applyValidRelocs(DIECopy,
Offset,
Data.isLittleEndian());
1872 if (Die->
getTag() == dwarf::DW_TAG_subprogram)
1873 PCOffset =
Info.AddrAdjust;
1874 AttrInfo.PCOffset = PCOffset;
1876 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1877 Flags |= TF_InFunctionScope;
1880 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1883 if ((Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1884 Flags &= ~TF_SkipPC;
1887 else if (!
Info.InDebugMap &&
Info.HasLocationExpressionAddr &&
1892 std::optional<StringRef> LibraryInstallName =
1893 ObjFile.Addresses->getLibraryInstallName();
1894 SmallVector<AttributeLinkedOffsetFixup> AttributesFixups;
1895 for (
const auto &AttrSpec : Abbrev->attributes()) {
1902 AttributeLinkedOffsetFixup CurAttrFixup;
1904 CurAttrFixup.LinkedOffsetFixupVal =
1905 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1907 DWARFFormValue Val = AttrSpec.getFormValue();
1909 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1911 AttrSize =
Offset - AttrSize;
1914 cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
1915 AttrInfo, IsLittleEndian);
1916 if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
1917 AttributesFixups.push_back(CurAttrFixup);
1919 OutOffset += FinalAttrSize;
1925 const bool NeedsAppleOrigin = (
Tag == dwarf::DW_TAG_compile_unit) &&
1926 LibraryInstallName.has_value() &&
1927 !AttrInfo.HasAppleOrigin;
1928 if (NeedsAppleOrigin) {
1929 auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
1931 dwarf::DW_FORM_strp, DIEInteger(
StringEntry.getOffset()));
1940 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1941 Tag != dwarf::DW_TAG_compile_unit &&
1942 getDIENames(InputDIE, AttrInfo, DebugStrPool,
1943 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1944 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1945 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1946 Tag == dwarf::DW_TAG_inlined_subroutine);
1947 if (AttrInfo.Name) {
1948 if (AttrInfo.NameWithoutTemplate)
1949 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1951 Unit.addNameAccelerator(Die, AttrInfo.Name,
1952 Tag == dwarf::DW_TAG_inlined_subroutine);
1955 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,
1958 }
else if (
Tag == dwarf::DW_TAG_namespace) {
1960 AttrInfo.Name = DebugStrPool.getEntry(
"(anonymous namespace)");
1961 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1962 }
else if (
Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1963 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1964 }
else if (
isTypeTag(
Tag) && !AttrInfo.IsDeclaration) {
1965 bool Success = getDIENames(InputDIE, AttrInfo, DebugStrPool);
1969 bool ObjCClassIsImplementation =
1970 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1971 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1974 if (
Success && AttrInfo.Name && !AttrInfo.Name.getString().empty()) {
1976 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1981 if (
Success && AttrInfo.MangledName &&
1982 RuntimeLang == dwarf::DW_LANG_Swift &&
1983 !AttrInfo.MangledName.getString().empty() &&
1984 AttrInfo.MangledName != AttrInfo.Name) {
1985 auto Hash =
djbHash(AttrInfo.MangledName.getString().data());
1986 Unit.addTypeAccelerator(Die, AttrInfo.MangledName,
1987 ObjCClassIsImplementation, Hash);
1992 bool HasChildren =
false;
1993 for (
auto Child : InputDIE.
children()) {
1994 unsigned Idx =
U.getDIEIndex(Child);
1995 if (Unit.getInfo(
Idx).Keep) {
2001 if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
2002 Die->
getTag() == dwarf::DW_TAG_compile_unit) {
2004 Die->
addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
2005 dwarf::DW_FORM_sec_offset, DIEInteger(8));
2013 Linker.assignAbbrev(NewAbbrev);
2019 OutOffset += AbbrevNumberSize;
2022 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2023 F.LinkedOffsetFixupVal += AbbrevNumberSize;
2025 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2026 ObjFile.Addresses->updateAndSaveValidRelocs(
2027 Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(),
2028 F.LinkedOffsetFixupVal,
F.InputAttrStartOffset,
F.InputAttrEndOffset);
2037 for (
auto Child : InputDIE.
children()) {
2038 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
2041 OutOffset = Clone->getOffset() + Clone->getSize();
2046 OutOffset +=
sizeof(int8_t);
2055void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File,
2060 const auto &FunctionRanges = Unit.getFunctionRanges();
2063 AddressRanges LinkedFunctionRanges;
2064 for (
const AddressRangeValuePair &
Range : FunctionRanges)
2065 LinkedFunctionRanges.insert(
2069 if (!LinkedFunctionRanges.empty())
2073 std::optional<PatchLocation> UnitRngListAttribute =
2074 Unit.getUnitRangesAttribute();
2076 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
2077 std::optional<AddressRangeValuePair> CachedRange;
2082 for (PatchLocation &AttributePatch : AllRngListAttributes) {
2085 AddressRanges LinkedRanges;
2086 if (Expected<DWARFAddressRangesVector> OriginalRanges =
2087 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
2089 for (
const auto &
Range : *OriginalRanges) {
2090 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
2091 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
2095 reportWarning(
"inconsistent range data.", File);
2100 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
2101 Range.HighPC + CachedRange->Value});
2105 reportWarning(
"invalid range list ignored.", File);
2110 Unit, LinkedRanges, AttributePatch, AddrPool);
2114 if (UnitRngListAttribute.has_value())
2116 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);
2123void DWARFLinker::DIECloner::generateUnitLocations(
2124 CompileUnit &Unit,
const DWARFFile &File,
2125 ExpressionHandlerRef ExprHandler) {
2130 Unit.getLocationAttributes();
2132 if (AllLocListAttributes.empty())
2138 for (
auto &CurLocAttr : AllLocListAttributes) {
2141 Expected<DWARFLocationExpressionsVector> OriginalLocations =
2142 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
2144 if (!OriginalLocations) {
2146 Linker.reportWarning(
"Invalid location attribute ignored.", File);
2151 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
2152 DWARFLocationExpression LinkedExpression;
2154 if (CurExpression.Range) {
2156 LinkedExpression.Range = {
2157 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
2158 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
2162 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
2163 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
2164 CurLocAttr.RelocAdjustment);
2166 LinkedLocationExpressions.push_back(LinkedExpression);
2170 Emitter->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions,
2171 CurLocAttr, AddrPool);
2175 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
2179 for (
auto &V : Die.
values())
2180 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
2188void DWARFLinker::DIECloner::emitDebugAddrSection(
2189 CompileUnit &Unit,
const uint16_t DwarfVersion)
const {
2194 if (DwarfVersion < 5)
2197 if (AddrPool.getValues().empty())
2200 MCSymbol *EndLabel =
Emitter->emitDwarfDebugAddrsHeader(Unit);
2202 DIEInteger(
Emitter->getDebugAddrSectionSize()));
2203 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),
2204 Unit.getOrigUnit().getAddressByteSize());
2205 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
2221 std::vector<TrackedRow> &Rows) {
2227 Seq.front().isStartSeqInOutput =
true;
2229 if (!Rows.empty() && Rows.back().Row.Address < Seq.front().Row.Address) {
2237 Rows, [=](
const TrackedRow &O) {
return O.Row.Address < Front; });
2243 if (InsertPoint != Rows.end() && InsertPoint->Row.Address == Front &&
2244 InsertPoint->Row.EndSequence) {
2245 *InsertPoint = Seq.front();
2246 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
2248 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
2255 for (
auto &V : Die.
values())
2256 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2264void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2265 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2266 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2268 if (std::optional<uint64_t> MacroAttr =
2270 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2274 if (std::optional<uint64_t> MacroAttr =
2276 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2281void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2286 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
2292 if (
auto *OutputDIE = Unit.getOutputUnitDIE())
2295 if (
const DWARFDebugLine::LineTable *LT =
2296 ObjFile.Dwarf->getLineTableForUnit(&Unit.getOrigUnit())) {
2298 DWARFDebugLine::LineTable LineTable;
2301 LineTable.Prologue =
LT->Prologue;
2304 if (Linker.Options.Update) {
2305 LineTable.Rows =
LT->Rows;
2308 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2309 LineTable.Rows.clear();
2311 LineTable.Sequences =
LT->Sequences;
2313 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2317 std::vector<TrackedRow> InputRows;
2318 InputRows.reserve(
LT->Rows.size());
2319 for (
size_t i = 0; i <
LT->Rows.size(); i++)
2320 InputRows.emplace_back(TrackedRow{LT->Rows[i], i, false});
2323 std::vector<TrackedRow> OutputRows;
2324 OutputRows.reserve(InputRows.size());
2328 std::vector<TrackedRow> Seq;
2329 Seq.reserve(InputRows.size());
2331 const auto &FunctionRanges = Unit.getFunctionRanges();
2332 std::optional<AddressRangeValuePair> CurrRange;
2345 for (
size_t i = 0; i < InputRows.size(); i++) {
2346 TrackedRow TR = InputRows[i];
2353 if (!CurrRange || !CurrRange->Range.contains(TR.Row.Address.Address)) {
2357 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2359 FunctionRanges.getRangeThatContains(TR.Row.Address.Address);
2360 if (StopAddress != -1ULL && !Seq.empty()) {
2363 auto NextLine = Seq.back();
2364 NextLine.Row.Address.Address = StopAddress;
2365 NextLine.Row.EndSequence = 1;
2366 NextLine.Row.PrologueEnd = 0;
2367 NextLine.Row.BasicBlock = 0;
2368 NextLine.Row.EpilogueBegin = 0;
2369 Seq.push_back(NextLine);
2378 if (TR.Row.EndSequence && Seq.empty())
2382 TR.Row.Address.Address += CurrRange->Value;
2385 if (TR.Row.EndSequence)
2390 LineTable.Rows.clear();
2391 LineTable.Rows.reserve(OutputRows.size());
2392 for (
auto &TR : OutputRows)
2393 LineTable.Rows.push_back(TR.Row);
2397 std::vector<uint64_t> OutputRowOffsets;
2401 bool hasStmtSeq = Unit.getStmtSeqListAttributes().size() > 0;
2402 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2404 hasStmtSeq ? &OutputRowOffsets :
nullptr);
2407 assert(OutputRowOffsets.size() == OutputRows.size() &&
2408 "must have an offset for each row");
2411 DenseMap<uint64_t, unsigned> SeqOffToOrigRow;
2416 if (!
LT->Rows.empty())
2420 DenseMap<size_t, size_t> OrigRowToNewRow;
2421 for (
size_t i = 0; i < OutputRows.size(); ++i)
2422 OrigRowToNewRow[OutputRows[i].OriginalRowIndex] = i;
2426 for (
const auto &StmtSeq : Unit.getStmtSeqListAttributes()) {
2427 uint64_t OrigStmtSeq = StmtSeq.get();
2429 auto OrigRowIter = SeqOffToOrigRow.find(OrigStmtSeq);
2433 if (OrigRowIter == SeqOffToOrigRow.end()) {
2437 size_t OrigRowIndex = OrigRowIter->second;
2440 auto NewRowIter = OrigRowToNewRow.find(OrigRowIndex);
2441 if (NewRowIter == OrigRowToNewRow.end()) {
2449 assert(NewRowIter->second < OutputRowOffsets.size() &&
2450 "New row index out of bounds");
2451 uint64_t NewStmtSeqOffset = OutputRowOffsets[NewRowIter->second];
2454 StmtSeq.set(NewStmtSeqOffset);
2460 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2463void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2468 for (
const auto &Namespace : Unit.getNamespaces())
2469 AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() +
2470 Unit.getStartOffset());
2472 for (
const auto &Pubname : Unit.getPubnames())
2473 AppleNames.addName(Pubname.Name,
2474 Pubname.Die->getOffset() + Unit.getStartOffset());
2476 for (
const auto &Pubtype : Unit.getPubtypes())
2478 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
2479 Pubtype.Die->getTag(),
2482 Pubtype.QualifiedNameHash);
2484 for (
const auto &ObjC : Unit.getObjC())
2485 AppleObjc.addName(ObjC.Name,
2486 ObjC.Die->getOffset() + Unit.getStartOffset());
2493 for (
const auto &Namespace : Unit.getNamespaces())
2495 Namespace.Name, Namespace.Die->getOffset(),
2497 Namespace.Die->getTag(), Unit.getUniqueID(),
2498 Unit.getTag() == dwarf::DW_TAG_type_unit);
2499 for (
const auto &Pubname : Unit.getPubnames())
2501 Pubname.Name, Pubname.Die->getOffset(),
2503 Pubname.Die->getTag(), Unit.getUniqueID(),
2504 Unit.getTag() == dwarf::DW_TAG_type_unit);
2505 for (
const auto &Pubtype : Unit.getPubtypes())
2507 Pubtype.Name, Pubtype.Die->getOffset(),
2509 Pubtype.Die->getTag(), Unit.getUniqueID(),
2510 Unit.getTag() == dwarf::DW_TAG_type_unit);
2522void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) {
2523 DWARFContext &OrigDwarf = *
Context.File.Dwarf;
2524 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2526 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2531 for (std::unique_ptr<CompileUnit> &Unit :
Context.CompileUnits) {
2532 for (
auto CurRange : Unit->getFunctionRanges())
2533 AllUnitsRanges.
insert(CurRange.Range, CurRange.Value);
2536 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian(), 0);
2541 DenseMap<uint64_t, StringRef> LocalCIES;
2543 while (
Data.isValidOffset(InputOffset)) {
2544 uint64_t EntryOffset = InputOffset;
2546 if (InitialLength == 0xFFFFFFFF)
2547 return reportWarning(
"Dwarf64 bits no supported",
Context.File);
2550 if (CIEId == 0xFFFFFFFF) {
2552 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2553 LocalCIES[EntryOffset] = CIEData;
2555 InputOffset += InitialLength - 4;
2559 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2565 std::optional<AddressRangeValuePair>
Range =
2566 AllUnitsRanges.getRangeThatContains(Loc);
2569 InputOffset = EntryOffset + InitialLength + 4;
2575 StringRef CIEData = LocalCIES[CIEId];
2576 if (CIEData.empty())
2577 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2582 auto IteratorInserted = EmittedCIEs.
insert(
2585 if (IteratorInserted.second) {
2587 IteratorInserted.first->getValue() = LastCIEOffset;
2588 TheDwarfEmitter->
emitCIE(CIEData);
2594 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2595 TheDwarfEmitter->
emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2597 FrameData.substr(InputOffset, FDERemainingBytes));
2598 InputOffset += FDERemainingBytes;
2602uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2604 const DWARFFile &File,
2605 int ChildRecurseDepth) {
2606 const char *
Name =
nullptr;
2607 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2608 CompileUnit *
CU = &
U;
2609 std::optional<DWARFFormValue>
Ref;
2615 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2616 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2624 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2626 OrigUnit = &RefCU->getOrigUnit();
2631 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2632 if (!
Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2633 Name =
"(anonymous namespace)";
2635 if (
CU->getInfo(
Idx).ParentIdx == 0 ||
2637 CU->getOrigUnit().getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx).getTag() ==
2638 dwarf::DW_TAG_module)
2641 DWARFDie Die = OrigUnit->getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx);
2650 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2659 if (ObjectPrefixMap.empty())
2663 for (
const auto &Entry : ObjectPrefixMap)
2666 return p.str().str();
2673 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2675 if (PCMFile.empty())
2678 if (ObjectPrefixMap)
2679 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2684std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2685 std::string &PCMFile,
2686 LinkContext &Context,
2689 if (PCMFile.empty())
2690 return std::make_pair(
false,
false);
2698 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2700 return std::make_pair(
true,
true);
2703 if (!
Quiet && Options.Verbose) {
2705 outs() <<
"Found clang module reference " << PCMFile;
2708 auto Cached = ClangModules.
find(PCMFile);
2709 if (Cached != ClangModules.
end()) {
2713 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2714 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2715 "different version of the module ") +
2718 if (!
Quiet && Options.Verbose)
2719 outs() <<
" [cached].\n";
2720 return std::make_pair(
true,
true);
2723 return std::make_pair(
true,
false);
2726bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2727 LinkContext &Context,
2728 ObjFileLoaderTy Loader,
2729 CompileUnitHandlerTy OnCUDieLoaded,
2731 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2732 std::pair<bool, bool> IsClangModuleRef =
2733 isClangModuleRef(CUDie, PCMFile, Context, Indent,
false);
2735 if (!IsClangModuleRef.first)
2738 if (IsClangModuleRef.second)
2741 if (Options.Verbose)
2748 if (Error
E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded,
2756Error DWARFLinker::loadClangModule(
2757 ObjFileLoaderTy Loader,
const DWARFDie &CUDie,
const std::string &PCMFile,
2758 LinkContext &Context, CompileUnitHandlerTy OnCUDieLoaded,
unsigned Indent) {
2764 SmallString<0>
Path(Options.PrependPath);
2771 if (Loader ==
nullptr) {
2772 reportError(
"Could not load clang module: loader is not specified.\n",
2777 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2781 std::unique_ptr<CompileUnit> Unit;
2782 for (
const auto &
CU : ErrOrObj->Dwarf->compile_units()) {
2785 auto ChildCUDie =
CU->getUnitDIE();
2788 if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded,
2793 ": Clang modules are expected to have exactly 1 compile unit.\n");
2794 reportError(Err,
Context.File);
2801 if (PCMDwoId != DwoId) {
2802 if (Options.Verbose)
2804 Twine(
"hash mismatch: this object file was built against a "
2805 "different version of the module ") +
2809 ClangModules[PCMFile] = PCMDwoId;
2813 Unit = std::make_unique<CompileUnit>(*
CU, UniqueUnitID++, !Options.NoODR,
2819 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2824uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2825 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2828 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2830 for (
auto &CurrentUnit : CompileUnits) {
2831 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2832 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2833 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2834 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2836 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2839 if (CurrentUnit->getInfo(0).Keep) {
2842 CurrentUnit->createOutputDIE();
2843 rememberUnitForMacroOffset(*CurrentUnit);
2844 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2845 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2848 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2852 generateLineTableForUnit(*CurrentUnit);
2854 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2859 Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);
2861 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2862 SmallVectorImpl<uint8_t> &OutBytes,
2863 int64_t RelocAdjustment) {
2864 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2865 DataExtractor
Data(SrcBytes, IsLittleEndian,
2866 OrigUnit.getAddressByteSize());
2867 cloneExpression(
Data,
2868 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2869 OrigUnit.getFormParams().Format),
2870 File, *CurrentUnit, OutBytes, RelocAdjustment,
2873 generateUnitLocations(*CurrentUnit, File, ProcessExpr);
2874 emitDebugAddrSection(*CurrentUnit, DwarfVersion);
2882 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2885 for (
auto &CurrentUnit : CompileUnits) {
2886 CurrentUnit->fixupForwardReferences();
2888 if (!CurrentUnit->getOutputUnitDIE())
2891 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2894 CurrentUnit->getStartOffset());
2895 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2896 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2898 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2902 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2905void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2909 Dwarf.getDWARFObj().getRangesSection().Data,
2918 Dwarf.getDWARFObj().getRnglistsSection().Data,
2921 Dwarf.getDWARFObj().getLoclistsSection().Data,
2927 ObjectContexts.emplace_back(LinkContext(File));
2929 if (ObjectContexts.back().File.Dwarf) {
2930 for (
const std::unique_ptr<DWARFUnit> &
CU :
2931 ObjectContexts.back().File.Dwarf->compile_units()) {
2940 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
2947 assert((Options.TargetDWARFVersion != 0) &&
2948 "TargetDWARFVersion should be set");
2952 unsigned NumObjects = ObjectContexts.size();
2964 for (LinkContext &OptContext : ObjectContexts) {
2965 if (Options.Verbose)
2966 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
2968 if (!OptContext.File.Dwarf)
2971 if (Options.VerifyInputDWARF)
2972 verifyInput(OptContext.File);
2979 !OptContext.File.Addresses->hasValidRelocs()) {
2980 if (Options.Verbose)
2981 outs() <<
"No valid relocations found. Skipping.\n";
2985 OptContext.Skip =
true;
2990 if (!OptContext.File.Dwarf)
2994 if (!OptContext.File.Dwarf->types_section_units().empty()) {
2995 reportWarning(
"type units are not currently supported: file will "
2998 OptContext.Skip =
true;
3004 OptContext.CompileUnits.reserve(
3005 OptContext.File.Dwarf->getNumCompileUnits());
3006 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
3007 auto CUDie =
CU->getUnitDIE(
true);
3008 if (Options.Verbose) {
3009 outs() <<
"Input compilation unit:";
3012 DumpOpts.
Verbose = Options.Verbose;
3013 CUDie.dump(
outs(), 0, DumpOpts);
3017 for (
auto &
CU : OptContext.ModuleUnits) {
3018 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
3019 DebugLineStrPool, StringOffsetPool))
3020 reportWarning(
toString(std::move(Err)),
CU.File);
3030 (TheDwarfEmitter ==
nullptr) ? 0
3035 std::mutex ProcessedFilesMutex;
3036 std::condition_variable ProcessedFilesConditionVariable;
3037 BitVector ProcessedFiles(NumObjects,
false);
3041 auto AnalyzeLambda = [&](
size_t I) {
3047 for (
const auto &
CU :
Context.File.Dwarf->compile_units()) {
3050 auto CUDie =
CU->getUnitDIE(
false);
3051 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
3054 !isClangModuleRef(CUDie, PCMFile,
Context, 0,
true).first) {
3055 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
3056 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
3061 for (
auto &CurrentUnit :
Context.CompileUnits) {
3062 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
3066 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
3067 ModulesEndOffset, Options.ParseableSwiftInterfaces,
3069 reportWarning(Warning, Context.File, &DIE);
3081 auto CloneLambda = [&](
size_t I) {
3082 auto &OptContext = ObjectContexts[
I];
3083 if (OptContext.Skip || !OptContext.File.Dwarf)
3092 for (
auto &CurrentUnit : OptContext.CompileUnits)
3093 CurrentUnit->markEverythingAsKept();
3094 copyInvariantDebugSection(*OptContext.File.Dwarf);
3096 for (
auto &CurrentUnit : OptContext.CompileUnits) {
3097 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
3098 CurrentUnit->getOrigUnit().getUnitDIE(),
3099 OptContext.File, *CurrentUnit, 0);
3109 if (OptContext.File.Addresses->hasValidRelocs() ||
3111 SizeByObject[OptContext.File.FileName].Input =
3113 SizeByObject[OptContext.File.FileName].Output =
3114 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
3115 OptContext.CompileUnits, Options.Update, DebugStrPool,
3116 DebugLineStrPool, StringOffsetPool)
3117 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
3118 OptContext.File.Dwarf->isLittleEndian());
3120 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
3122 patchFrameInfoForObject(OptContext);
3125 cleanupAuxiliarryData(OptContext);
3128 auto EmitLambda = [&]() {
3130 if (TheDwarfEmitter !=
nullptr) {
3131 TheDwarfEmitter->
emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
3134 Options.TargetDWARFVersion);
3137 switch (TableKind) {
3156 auto AnalyzeAll = [&]() {
3157 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3160 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3161 ProcessedFiles.
set(
I);
3162 ProcessedFilesConditionVariable.notify_one();
3166 auto CloneAll = [&]() {
3167 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3169 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3170 if (!ProcessedFiles[
I]) {
3171 ProcessedFilesConditionVariable.wait(
3172 LockGuard, [&]() {
return ProcessedFiles[
I]; });
3184 if (Options.Threads == 1) {
3185 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3192 Pool.
async(AnalyzeAll);
3193 Pool.
async(CloneAll);
3197 if (Options.Statistics) {
3199 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
3200 for (
auto &
E : SizeByObject)
3201 Sorted.emplace_back(
E.first(),
E.second);
3203 return LHS.second.Output >
RHS.second.Output;
3206 auto ComputePercentange = [](int64_t Input, int64_t Output) ->
float {
3207 const float Difference = Output - Input;
3208 const float Sum = Input + Output;
3211 return (Difference / (Sum / 2));
3214 int64_t InputTotal = 0;
3215 int64_t OutputTotal = 0;
3216 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
3219 outs() <<
".debug_info section size (in bytes)\n";
3220 outs() <<
"----------------------------------------------------------------"
3221 "---------------\n";
3222 outs() <<
"Filename Object "
3224 outs() <<
"----------------------------------------------------------------"
3225 "---------------\n";
3228 for (
auto &
E : Sorted) {
3229 InputTotal +=
E.second.Input;
3230 OutputTotal +=
E.second.Output;
3233 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
3236 outs() <<
"----------------------------------------------------------------"
3237 "---------------\n";
3239 ComputePercentange(InputTotal, OutputTotal));
3240 outs() <<
"----------------------------------------------------------------"
3241 "---------------\n\n";
3247Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3253 assert(Unit.Unit.get() !=
nullptr);
3255 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3258 if (Options.Verbose) {
3260 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3265 &ODRContexts.
getRoot(), ODRContexts, 0,
3266 Options.ParseableSwiftInterfaces,
3268 reportWarning(Warning, Context.File, &DIE);
3271 Unit.Unit->markEverythingAsKept();
3275 CompileUnits.emplace_back(std::move(Unit.Unit));
3277 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3278 Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
3279 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3280 Unit.File.Dwarf->isLittleEndian());
3284void DWARFLinker::verifyInput(
const DWARFFile &File) {
3291 if (Options.InputVerificationHandler)
3292 Options.InputVerificationHandler(File,
OS.str());
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
dxil DXContainer Global Emitter
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Provides ErrorOr<T> smart pointer.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
void addName(DwarfStringPoolEntryRef Name, Types &&... Args)
void insert(AddressRange Range, int64_t Value)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_while(PredicateT Pred) const
Return a copy of *this with the first N elements satisfying the given predicate removed.
const T & front() const
front - Get the first element.
ArrayRef< T > drop_back(size_t N=1) const
Drop the last N elements of the array.
bool empty() const
empty - Check if the array is empty.
const T & consume_front()
consume_front() - Returns the first element and drops it from ArrayRef.
void Reset()
Deallocate all but the current slab and reset the current pointer to the beginning of it,...
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.
A non-threaded implementation.
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...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef take_back(size_t N=1) const
Return a StringRef equal to 'this' but with only the last N elements remaining.
Helper for making strong types.
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...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
This class represents DWARF information for source file and it's address map.
std::map< std::string, std::string > ObjectPrefixMapTy
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.
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.
virtual void emitPubTypesForUnit(const CompileUnit &Unit)=0
Emit the .debug_pubtypes contribution for Unit.
virtual void emitSectionContents(StringRef SecData, DebugSectionKind SecKind)=0
Emit section named SecName with data SecData.
virtual void emitDwarfDebugRangeListFragment(const CompileUnit &Unit, const AddressRanges &LinkedRanges, PatchLocation Patch, DebugDieValuePool &AddrPool)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
virtual void emitDwarfDebugArangesTable(const CompileUnit &Unit, const AddressRanges &LinkedRanges)=0
Emit .debug_aranges entries for Unit.
virtual uint64_t getDebugInfoSectionSize() const =0
Returns size of generated .debug_info section.
virtual void emitCIE(StringRef CIEBytes)=0
Emit a CIE.
virtual uint64_t getFrameSectionSize() const =0
Returns size of generated .debug_frame section.
virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address, StringRef Bytes)=0
Emit an FDE with data Bytes.
virtual void emitAppleNamespaces(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple namespaces accelerator table.
virtual void emitAppleObjc(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple Objective-C accelerator table.
virtual void emitDebugNames(DWARF5AccelTable &Table)=0
Emit DWARF debug names.
virtual void emitAppleTypes(AccelTable< AppleAccelTableStaticTypeData > &Table)=0
Emit Apple type accelerator table.
virtual void emitPubNamesForUnit(const CompileUnit &Unit)=0
Emit the .debug_pubnames contribution for Unit.
virtual void emitAppleNames(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple names accelerator table.
virtual void emitAbbrevs(const std::vector< std::unique_ptr< DIEAbbrev > > &Abbrevs, unsigned DwarfVersion)=0
Emit the abbreviation table Abbrevs to the .debug_abbrev section.
virtual MCSymbol * emitDwarfDebugRangeListHeader(const CompileUnit &Unit)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) header.
virtual void emitStrings(const NonRelocatableStringpool &Pool)=0
Emit the string table described by Pool into .debug_str table.
virtual void emitLineStrings(const NonRelocatableStringpool &Pool)=0
Emit the string table described by Pool into .debug_line_str table.
virtual void emitStringOffsets(const SmallVector< uint64_t > &StringOffsets, uint16_t TargetDWARFVersion)=0
Emit the debug string offset table described by StringOffsets into the .debug_str_offsets table.
virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, MCSymbol *EndLabel)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
An efficient, type-erasing, non-owning reference to a callable.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
LLVM_ABI StringRef FormEncodingString(unsigned Encoding)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
SmallVector< PatchLocation > RngListAttributesTy
IndexedValuesMap< uint64_t > DebugDieValuePool
SmallVector< PatchLocation > LocListAttributesTy
std::vector< std::unique_ptr< CompileUnit > > UnitListTy
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
StringMapEntry< std::nullopt_t > 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.
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...
static bool isTlsAddressCode(uint8_t DW_OP_Code)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
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)
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...
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.
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)
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
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.
StrongType< NonRelocatableStringpool, OffsetsTag > OffsetsStringPool
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)
static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, uint64_t ModulesEndOffset)
@ Success
The lock was released successfully.
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...
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.
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)
static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU)
const char * toString(DWARFSectionKind Kind)
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.
void consumeError(Error Err)
Consume a Error without doing anything.
static bool isODRAttribute(uint16_t Attr)
static void constructSeqOffsettoOrigRowMapping(CompileUnit &Unit, const DWARFDebugLine::LineTable <, DenseMap< uint64_t, unsigned > &SeqOffToOrigRow)
static void patchStmtList(DIE &Die, DIEInteger Offset)
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.
Represents a series of contiguous machine instructions.
uint64_t StmtSeqOffset
The offset into the line table where this sequence begins.
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?