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);
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();
868 for (
const auto &AttrSpec : Abbrev->attributes()) {
869 DWARFFormValue Val(AttrSpec.Form);
871 AttrSpec.Attr == dwarf::DW_AT_sibling) {
873 Unit.getFormParams());
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) {
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) {
1246 uint32_t NewRefOffset =
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();
1276 uint64_t OpOffset = 0;
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(
1336 OutputBuffer.push_back(dwarf::DW_OP_addr);
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) {
1370 OutputBuffer.push_back(*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);
1384 OutputBuffer.append(Bytes.begin(), Bytes.end());
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;
1449 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
1450 dwarf::Form(AttrSpec.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())
1504 *Addr +=
Info.PCOffset;
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()) {
1537 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacinfo();
1543 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1544 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1545 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacro();
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();
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();
1849 uint64_t NextOffset = (Idx + 1 <
U.getNumDIEs())
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();
1895 for (
const auto &AttrSpec : Abbrev->attributes()) {
1902 AttributeLinkedOffsetFixup CurAttrFixup;
1904 CurAttrFixup.LinkedOffsetFixupVal =
1905 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1907 DWARFFormValue Val = AttrSpec.getFormValue();
1908 uint64_t AttrSize =
Offset;
1909 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1911 AttrSize =
Offset - AttrSize;
1913 uint64_t FinalAttrSize =
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);
1966 uint64_t RuntimeLang =
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())
2070 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
2073 std::optional<PatchLocation> UnitRngListAttribute =
2074 Unit.getUnitRangesAttribute();
2076 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
2077 std::optional<AddressRangeValuePair> CachedRange;
2078 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
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);
2109 TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2110 Unit, LinkedRanges, AttributePatch, AddrPool);
2114 if (UnitRngListAttribute.has_value())
2115 TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2116 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);
2119 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
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)) {
2356 uint64_t StopAddress =
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);
2430 const uint64_t InvalidOffset =
2431 Unit.getOrigUnit().getFormParams().getDwarfMaxOffset();
2435 if (OrigRowIter == SeqOffToOrigRow.end()) {
2436 StmtSeq.set(InvalidOffset);
2439 size_t OrigRowIndex = OrigRowIter->second;
2442 auto NewRowIter = OrigRowToNewRow.find(OrigRowIndex);
2443 if (NewRowIter == OrigRowToNewRow.end()) {
2446 StmtSeq.set(InvalidOffset);
2451 assert(NewRowIter->second < OutputRowOffsets.size() &&
2452 "New row index out of bounds");
2453 uint64_t NewStmtSeqOffset = OutputRowOffsets[NewRowIter->second];
2456 StmtSeq.set(NewStmtSeqOffset);
2462 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2465void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2470 for (
const auto &Namespace :
Unit.getNamespaces())
2472 Unit.getStartOffset());
2474 for (
const auto &Pubname :
Unit.getPubnames())
2475 AppleNames.addName(Pubname.Name,
2476 Pubname.Die->getOffset() +
Unit.getStartOffset());
2478 for (
const auto &Pubtype :
Unit.getPubtypes())
2480 Pubtype.Name, Pubtype.Die->getOffset() +
Unit.getStartOffset(),
2481 Pubtype.Die->getTag(),
2484 Pubtype.QualifiedNameHash);
2486 for (
const auto &ObjC :
Unit.getObjC())
2487 AppleObjc.addName(ObjC.Name,
2488 ObjC.Die->getOffset() +
Unit.getStartOffset());
2491 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2492 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2495 for (
const auto &Namespace :
Unit.getNamespaces())
2500 Unit.getTag() == dwarf::DW_TAG_type_unit);
2501 for (
const auto &Pubname :
Unit.getPubnames())
2503 Pubname.Name, Pubname.Die->getOffset(),
2505 Pubname.Die->getTag(),
Unit.getUniqueID(),
2506 Unit.getTag() == dwarf::DW_TAG_type_unit);
2507 for (
const auto &Pubtype :
Unit.getPubtypes())
2509 Pubtype.Name, Pubtype.Die->getOffset(),
2511 Pubtype.Die->getTag(),
Unit.getUniqueID(),
2512 Unit.getTag() == dwarf::DW_TAG_type_unit);
2524void DWARFLinker::patchFrameInfoForObject(LinkContext &
Context) {
2525 DWARFContext &OrigDwarf = *
Context.File.Dwarf;
2526 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2528 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2533 for (std::unique_ptr<CompileUnit> &Unit :
Context.CompileUnits) {
2534 for (
auto CurRange :
Unit->getFunctionRanges())
2535 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
2538 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian(), 0);
2539 uint64_t InputOffset = 0;
2543 DenseMap<uint64_t, StringRef> LocalCIES;
2545 while (
Data.isValidOffset(InputOffset)) {
2546 uint64_t EntryOffset = InputOffset;
2547 uint32_t InitialLength =
Data.getU32(&InputOffset);
2548 if (InitialLength == 0xFFFFFFFF)
2549 return reportWarning(
"Dwarf64 bits no supported",
Context.File);
2551 uint32_t CIEId =
Data.getU32(&InputOffset);
2552 if (CIEId == 0xFFFFFFFF) {
2554 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2555 LocalCIES[EntryOffset] = CIEData;
2557 InputOffset += InitialLength - 4;
2561 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2567 std::optional<AddressRangeValuePair>
Range =
2568 AllUnitsRanges.getRangeThatContains(Loc);
2571 InputOffset = EntryOffset + InitialLength + 4;
2577 StringRef CIEData = LocalCIES[CIEId];
2578 if (CIEData.empty())
2579 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2584 auto IteratorInserted = EmittedCIEs.insert(
2585 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2587 if (IteratorInserted.second) {
2588 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2589 IteratorInserted.first->getValue() = LastCIEOffset;
2590 TheDwarfEmitter->emitCIE(CIEData);
2596 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2597 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2599 FrameData.substr(InputOffset, FDERemainingBytes));
2600 InputOffset += FDERemainingBytes;
2604uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2606 const DWARFFile &File,
2607 int ChildRecurseDepth) {
2608 const char *
Name =
nullptr;
2609 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2610 CompileUnit *CU = &
U;
2611 std::optional<DWARFFormValue>
Ref;
2617 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2618 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2626 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2628 OrigUnit = &RefCU->getOrigUnit();
2633 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2634 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2635 Name =
"(anonymous namespace)";
2637 if (CU->getInfo(Idx).ParentIdx == 0 ||
2639 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
2640 dwarf::DW_TAG_module)
2641 return djbHash(Name ? Name :
"",
djbHash(ChildRecurseDepth ?
"" :
"::"));
2643 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
2652 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2661 if (ObjectPrefixMap.empty())
2665 for (
const auto &Entry : ObjectPrefixMap)
2668 return p.str().str();
2675 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2677 if (PCMFile.empty())
2680 if (ObjectPrefixMap)
2681 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2686std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2687 std::string &PCMFile,
2688 LinkContext &Context,
2691 if (PCMFile.empty())
2692 return std::make_pair(
false,
false);
2697 std::string Name =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2700 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2702 return std::make_pair(
true,
true);
2705 if (!
Quiet && Options.Verbose) {
2707 outs() <<
"Found clang module reference " << PCMFile;
2710 auto Cached = ClangModules.find(PCMFile);
2711 if (Cached != ClangModules.end()) {
2715 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2716 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2717 "different version of the module ") +
2720 if (!
Quiet && Options.Verbose)
2721 outs() <<
" [cached].\n";
2722 return std::make_pair(
true,
true);
2725 return std::make_pair(
true,
false);
2728bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2733 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2734 std::pair<bool, bool> IsClangModuleRef =
2735 isClangModuleRef(CUDie, PCMFile,
Context, Indent,
false);
2737 if (!IsClangModuleRef.first)
2740 if (IsClangModuleRef.second)
2743 if (Options.Verbose)
2748 ClangModules.insert({PCMFile,
getDwoId(CUDie)});
2750 if (
Error E = loadClangModule(Loader, CUDie, PCMFile,
Context, OnCUDieLoaded,
2758Error DWARFLinker::loadClangModule(
2759 ObjFileLoaderTy Loader,
const DWARFDie &CUDie,
const std::string &PCMFile,
2763 std::string ModuleName =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2766 SmallString<0>
Path(Options.PrependPath);
2773 if (Loader ==
nullptr) {
2774 reportError(
"Could not load clang module: loader is not specified.\n",
2779 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2783 std::unique_ptr<CompileUnit>
Unit;
2784 for (
const auto &CU : ErrOrObj->Dwarf->compile_units()) {
2787 auto ChildCUDie = CU->getUnitDIE();
2790 if (!registerModuleReference(ChildCUDie,
Context, Loader, OnCUDieLoaded,
2795 ": Clang modules are expected to have exactly 1 compile unit.\n");
2796 reportError(Err,
Context.File);
2802 uint64_t PCMDwoId =
getDwoId(ChildCUDie);
2803 if (PCMDwoId != DwoId) {
2804 if (Options.Verbose)
2806 Twine(
"hash mismatch: this object file was built against a "
2807 "different version of the module ") +
2811 ClangModules[PCMFile] = PCMDwoId;
2815 Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR,
2821 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2826uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2827 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2828 uint64_t OutputDebugInfoSize =
2830 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2832 for (
auto &CurrentUnit : CompileUnits) {
2833 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2834 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2835 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2836 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2838 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2841 if (CurrentUnit->getInfo(0).Keep) {
2844 CurrentUnit->createOutputDIE();
2845 rememberUnitForMacroOffset(*CurrentUnit);
2846 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2847 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2850 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2854 generateLineTableForUnit(*CurrentUnit);
2856 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2861 Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);
2863 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2864 SmallVectorImpl<uint8_t> &OutBytes,
2865 int64_t RelocAdjustment) {
2866 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2867 DataExtractor
Data(SrcBytes, IsLittleEndian,
2868 OrigUnit.getAddressByteSize());
2869 cloneExpression(
Data,
2870 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2871 OrigUnit.getFormParams().Format),
2872 File, *CurrentUnit, OutBytes, RelocAdjustment,
2875 generateUnitLocations(*CurrentUnit, File, ProcessExpr);
2876 emitDebugAddrSection(*CurrentUnit, DwarfVersion);
2884 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2887 for (
auto &CurrentUnit : CompileUnits) {
2888 CurrentUnit->fixupForwardReferences();
2890 if (!CurrentUnit->getOutputUnitDIE())
2893 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2896 CurrentUnit->getStartOffset());
2897 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2898 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2900 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2904 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2907void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2908 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getLocSection().Data,
2910 TheDwarfEmitter->emitSectionContents(
2911 Dwarf.getDWARFObj().getRangesSection().Data,
2913 TheDwarfEmitter->emitSectionContents(
2915 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getArangesSection(),
2917 TheDwarfEmitter->emitSectionContents(
2919 TheDwarfEmitter->emitSectionContents(
2920 Dwarf.getDWARFObj().getRnglistsSection().Data,
2922 TheDwarfEmitter->emitSectionContents(
2923 Dwarf.getDWARFObj().getLoclistsSection().Data,
2929 ObjectContexts.emplace_back(LinkContext(File));
2931 if (ObjectContexts.back().File.Dwarf) {
2932 for (
const std::unique_ptr<DWARFUnit> &
CU :
2933 ObjectContexts.back().File.Dwarf->compile_units()) {
2942 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
2949 assert((Options.TargetDWARFVersion != 0) &&
2950 "TargetDWARFVersion should be set");
2954 unsigned NumObjects = ObjectContexts.size();
2966 for (LinkContext &OptContext : ObjectContexts) {
2967 if (Options.Verbose)
2968 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
2970 if (!OptContext.File.Dwarf)
2973 if (Options.VerifyInputDWARF)
2974 verifyInput(OptContext.File);
2981 !OptContext.File.Addresses->hasValidRelocs()) {
2982 if (Options.Verbose)
2983 outs() <<
"No valid relocations found. Skipping.\n";
2987 OptContext.Skip =
true;
2992 if (!OptContext.File.Dwarf)
2996 if (!OptContext.File.Dwarf->types_section_units().empty()) {
2997 reportWarning(
"type units are not currently supported: file will "
3000 OptContext.Skip =
true;
3006 OptContext.CompileUnits.reserve(
3007 OptContext.File.Dwarf->getNumCompileUnits());
3008 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
3009 auto CUDie =
CU->getUnitDIE(
true);
3010 if (Options.Verbose) {
3011 outs() <<
"Input compilation unit:";
3014 DumpOpts.
Verbose = Options.Verbose;
3015 CUDie.dump(
outs(), 0, DumpOpts);
3019 for (
auto &
CU : OptContext.ModuleUnits) {
3020 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
3021 DebugLineStrPool, StringOffsetPool))
3022 reportWarning(
toString(std::move(Err)),
CU.File);
3032 (TheDwarfEmitter ==
nullptr) ? 0
3033 : TheDwarfEmitter->getDebugInfoSectionSize();
3037 std::mutex ProcessedFilesMutex;
3038 std::condition_variable ProcessedFilesConditionVariable;
3039 BitVector ProcessedFiles(NumObjects,
false);
3043 auto AnalyzeLambda = [&](
size_t I) {
3044 auto &Context = ObjectContexts[
I];
3046 if (Context.Skip || !Context.File.Dwarf)
3049 for (
const auto &
CU : Context.File.Dwarf->compile_units()) {
3052 auto CUDie =
CU->getUnitDIE(
false);
3053 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
3056 !isClangModuleRef(CUDie, PCMFile, Context, 0,
true).first) {
3057 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
3058 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
3063 for (
auto &CurrentUnit : Context.CompileUnits) {
3064 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
3068 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
3069 ModulesEndOffset, Options.ParseableSwiftInterfaces,
3071 reportWarning(Warning, Context.File, &DIE);
3083 auto CloneLambda = [&](
size_t I) {
3084 auto &OptContext = ObjectContexts[
I];
3085 if (OptContext.Skip || !OptContext.File.Dwarf)
3094 for (
auto &CurrentUnit : OptContext.CompileUnits)
3095 CurrentUnit->markEverythingAsKept();
3096 copyInvariantDebugSection(*OptContext.File.Dwarf);
3098 for (
auto &CurrentUnit : OptContext.CompileUnits) {
3099 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
3100 CurrentUnit->getOrigUnit().getUnitDIE(),
3101 OptContext.File, *CurrentUnit, 0);
3111 if (OptContext.File.Addresses->hasValidRelocs() ||
3113 SizeByObject[OptContext.File.FileName].Input =
3115 SizeByObject[OptContext.File.FileName].Output =
3116 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
3117 OptContext.CompileUnits, Options.Update, DebugStrPool,
3118 DebugLineStrPool, StringOffsetPool)
3119 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
3120 OptContext.File.Dwarf->isLittleEndian());
3122 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
3124 patchFrameInfoForObject(OptContext);
3127 cleanupAuxiliarryData(OptContext);
3130 auto EmitLambda = [&]() {
3132 if (TheDwarfEmitter !=
nullptr) {
3133 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
3134 TheDwarfEmitter->emitStrings(DebugStrPool);
3135 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.
getValues(),
3136 Options.TargetDWARFVersion);
3137 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
3139 switch (TableKind) {
3141 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
3142 TheDwarfEmitter->emitAppleNames(AppleNames);
3143 TheDwarfEmitter->emitAppleTypes(AppleTypes);
3144 TheDwarfEmitter->emitAppleObjc(AppleObjc);
3151 TheDwarfEmitter->emitDebugNames(DebugNames);
3158 auto AnalyzeAll = [&]() {
3159 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3162 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3163 ProcessedFiles.
set(
I);
3164 ProcessedFilesConditionVariable.notify_one();
3168 auto CloneAll = [&]() {
3169 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3171 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3172 if (!ProcessedFiles[
I]) {
3173 ProcessedFilesConditionVariable.wait(
3174 LockGuard, [&]() {
return ProcessedFiles[
I]; });
3186 if (Options.Threads == 1) {
3187 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3194 Pool.
async(AnalyzeAll);
3195 Pool.
async(CloneAll);
3199 if (Options.Statistics) {
3201 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
3202 for (
auto &
E : SizeByObject)
3203 Sorted.emplace_back(
E.first(),
E.second);
3205 return LHS.second.Output >
RHS.second.Output;
3208 auto ComputePercentange = [](int64_t
Input, int64_t Output) ->
float {
3209 const float Difference = Output -
Input;
3210 const float Sum =
Input + Output;
3213 return (Difference / (Sum / 2));
3216 int64_t InputTotal = 0;
3217 int64_t OutputTotal = 0;
3218 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
3221 outs() <<
".debug_info section size (in bytes)\n";
3222 outs() <<
"----------------------------------------------------------------"
3223 "---------------\n";
3224 outs() <<
"Filename Object "
3226 outs() <<
"----------------------------------------------------------------"
3227 "---------------\n";
3230 for (
auto &
E : Sorted) {
3231 InputTotal +=
E.second.Input;
3232 OutputTotal +=
E.second.Output;
3235 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
3238 outs() <<
"----------------------------------------------------------------"
3239 "---------------\n";
3241 ComputePercentange(InputTotal, OutputTotal));
3242 outs() <<
"----------------------------------------------------------------"
3243 "---------------\n\n";
3249Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3255 assert(Unit.Unit.get() !=
nullptr);
3257 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3262 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3267 &ODRContexts.
getRoot(), ODRContexts, 0,
3268 Options.ParseableSwiftInterfaces,
3270 reportWarning(Warning, Context.File, &DIE);
3273 Unit.Unit->markEverythingAsKept();
3277 CompileUnits.emplace_back(std::move(Unit.Unit));
3279 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3280 Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
3281 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3282 Unit.File.Dwarf->isLittleEndian());
3286void DWARFLinker::verifyInput(
const DWARFFile &File) {
3293 if (
Options.InputVerificationHandler)
3294 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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#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))
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.
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.
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",...
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - 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 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
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.
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.
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.
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
StringMapEntry< std::nullopt_t > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
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.
FunctionAddr VTableAddr Value
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)
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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)
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.
void consumeError(Error Err)
Consume a Error without doing anything.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
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)
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.
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?