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) {
80 uint64_t RefOffset = *RefValue.getAsReference();
82 if (
const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
89 reportWarning(
"could not find referenced DIE", File, &DIE);
99 case dwarf::DW_AT_type:
100 case dwarf::DW_AT_containing_type:
101 case dwarf::DW_AT_specification:
102 case dwarf::DW_AT_abstract_origin:
103 case dwarf::DW_AT_import:
111 case dwarf::DW_TAG_array_type:
112 case dwarf::DW_TAG_class_type:
113 case dwarf::DW_TAG_enumeration_type:
114 case dwarf::DW_TAG_pointer_type:
115 case dwarf::DW_TAG_reference_type:
116 case dwarf::DW_TAG_string_type:
117 case dwarf::DW_TAG_structure_type:
118 case dwarf::DW_TAG_subroutine_type:
119 case dwarf::DW_TAG_template_alias:
120 case dwarf::DW_TAG_typedef:
121 case dwarf::DW_TAG_union_type:
122 case dwarf::DW_TAG_ptr_to_member_type:
123 case dwarf::DW_TAG_set_type:
124 case dwarf::DW_TAG_subrange_type:
125 case dwarf::DW_TAG_base_type:
126 case dwarf::DW_TAG_const_type:
127 case dwarf::DW_TAG_constant:
128 case dwarf::DW_TAG_file_type:
129 case dwarf::DW_TAG_namelist:
130 case dwarf::DW_TAG_packed_type:
131 case dwarf::DW_TAG_volatile_type:
132 case dwarf::DW_TAG_restrict_type:
133 case dwarf::DW_TAG_atomic_type:
134 case dwarf::DW_TAG_interface_type:
135 case dwarf::DW_TAG_unspecified_type:
136 case dwarf::DW_TAG_shared_type:
137 case dwarf::DW_TAG_immutable_type:
145bool DWARFLinker::DIECloner::getDIENames(
const DWARFDie &Die,
146 AttributesInfo &
Info,
148 bool StripTemplate) {
152 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
155 if (!
Info.MangledName)
156 if (
const char *MangledName = Die.getLinkageName())
157 Info.MangledName = StringPool.getEntry(MangledName);
160 if (
const char *
Name = Die.getShortName())
161 Info.Name = StringPool.getEntry(
Name);
163 if (!
Info.MangledName)
166 if (StripTemplate &&
Info.Name &&
Info.MangledName !=
Info.Name) {
167 StringRef
Name =
Info.Name.getString();
169 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
172 return Info.Name ||
Info.MangledName;
186 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
187 if (
CU.getLanguage() != dwarf::DW_LANG_Swift)
190 if (!ParseableSwiftInterfaces)
194 if (!Path.ends_with(
".swiftinterface"))
199 SysRoot =
CU.getSysRoot();
200 if (!SysRoot.
empty() && Path.starts_with(SysRoot))
205 if (!DeveloperDir.
empty() && Path.starts_with(DeveloperDir))
209 std::optional<const char *>
Name =
213 auto &Entry = (*ParseableSwiftInterfaces)[*
Name];
215 DWARFDie CUDie =
CU.getOrigUnit().getUnitDIE();
220 if (!Entry.empty() && Entry != ResolvedPath)
221 ReportWarning(
Twine(
"Conflicting parseable interfaces for Swift Module ") +
222 *
Name +
": " + Entry +
" and " + Path,
224 Entry = std::string(ResolvedPath);
250 : Die(Die), ParentIdx(0), OtherInfo(OtherInfo),
Type(
T),
251 InImportedModule(
false) {}
254 bool InImportedModule)
255 : Die(Die), ParentIdx(ParentIdx), Context(Context),
257 InImportedModule(InImportedModule) {}
267 Info.Prune &= (Die.
getTag() == dwarf::DW_TAG_module) ||
273 if (ModulesEndOffset == 0)
274 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset();
276 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset() > 0 &&
277 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
301 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
303 std::vector<ContextWorklistItem> Worklist;
304 Worklist.emplace_back(
DIE, CurrentDeclContext, ParentIdx,
false);
306 while (!Worklist.empty()) {
310 switch (Current.
Type) {
321 unsigned Idx =
CU.getOrigUnit().getDIEIndex(Current.
Die);
336 if (Current.
Die.
getTag() == dwarf::DW_TAG_module &&
339 CU.getClangModuleName()) {
347 if (
CU.hasODR() ||
Info.InModuleScope) {
351 Current.
Context = PtrInvalidPair.getPointer();
353 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
355 Info.Ctxt->setDefinedInClangModule(
Info.InModuleScope);
366 Worklist.emplace_back(
368 Worklist.emplace_back(Child, Current.
Context,
Idx,
378 case dwarf::DW_TAG_class_type:
379 case dwarf::DW_TAG_common_block:
380 case dwarf::DW_TAG_lexical_block:
381 case dwarf::DW_TAG_structure_type:
382 case dwarf::DW_TAG_subprogram:
383 case dwarf::DW_TAG_subroutine_type:
384 case dwarf::DW_TAG_union_type:
390void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
393 for (DIEBlock *
I : DIEBlocks)
395 for (DIELoc *
I : DIELocs)
404 return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
405 DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
408std::pair<bool, std::optional<int64_t>>
409DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
410 const DWARFDie &DIE) {
411 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
412 DIE.getTag() == dwarf::DW_TAG_constant) &&
413 "Wrong type of input die");
415 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
418 DWARFUnit *U = DIE.getDwarfUnit();
419 std::optional<uint32_t> LocationIdx =
420 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
422 return std::make_pair(
false, std::nullopt);
426 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
429 std::optional<DWARFFormValue> LocationValue =
430 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
432 return std::make_pair(
false, std::nullopt);
437 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
439 return std::make_pair(
false, std::nullopt);
442 DataExtractor
Data(
toStringRef(*Expr), U->getContext().isLittleEndian(),
443 U->getAddressByteSize());
444 DWARFExpression Expression(
Data, U->getAddressByteSize(),
445 U->getFormParams().Format);
447 bool HasLocationAddress =
false;
449 for (DWARFExpression::iterator It = Expression.begin();
450 It != Expression.end(); ++It) {
451 DWARFExpression::iterator NextIt = It;
454 const DWARFExpression::Operation &
Op = *It;
456 case dwarf::DW_OP_const2u:
457 case dwarf::DW_OP_const4u:
458 case dwarf::DW_OP_const8u:
459 case dwarf::DW_OP_const2s:
460 case dwarf::DW_OP_const4s:
461 case dwarf::DW_OP_const8s:
465 case dwarf::DW_OP_addr: {
466 HasLocationAddress =
true;
468 if (std::optional<int64_t> RelocAdjustment =
469 RelocMgr.getExprOpAddressRelocAdjustment(
470 *U,
Op, AttrOffset + CurExprOffset,
472 return std::make_pair(HasLocationAddress, *RelocAdjustment);
474 case dwarf::DW_OP_constx:
475 case dwarf::DW_OP_addrx: {
476 HasLocationAddress =
true;
477 if (std::optional<uint64_t> AddressOffset =
478 DIE.getDwarfUnit()->getIndexedAddressOffset(
481 if (std::optional<int64_t> RelocAdjustment =
482 RelocMgr.getExprOpAddressRelocAdjustment(
483 *U,
Op, *AddressOffset,
484 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
486 return std::make_pair(HasLocationAddress, *RelocAdjustment);
496 return std::make_pair(HasLocationAddress, std::nullopt);
501unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
503 CompileUnit::DIEInfo &MyInfo,
505 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
508 if (!(Flags & TF_InFunctionScope) &&
509 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
510 MyInfo.InDebugMap =
true;
511 return Flags | TF_Keep;
519 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
520 getVariableRelocAdjustment(RelocMgr, DIE);
522 if (LocExprAddrAndRelocAdjustment.first)
523 MyInfo.HasLocationExpressionAddr =
true;
525 if (!LocExprAddrAndRelocAdjustment.second)
528 MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second;
529 MyInfo.InDebugMap =
true;
531 if (((Flags & TF_InFunctionScope) &&
535 if (Options.Verbose) {
536 outs() <<
"Keeping variable DIE:";
537 DIDumpOptions DumpOpts;
538 DumpOpts.ChildRecurseDepth = 0;
539 DumpOpts.Verbose = Options.Verbose;
540 DIE.dump(
outs(), 8 , DumpOpts);
543 return Flags | TF_Keep;
548unsigned DWARFLinker::shouldKeepSubprogramDIE(
549 AddressesMap &RelocMgr,
const DWARFDie &DIE,
const DWARFFile &File,
550 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
551 Flags |= TF_InFunctionScope;
557 assert(LowPc &&
"low_pc attribute is not an address.");
558 std::optional<int64_t> RelocAdjustment =
559 RelocMgr.getSubprogramRelocAdjustment(DIE, Options.Verbose);
560 if (!RelocAdjustment)
563 MyInfo.AddrAdjust = *RelocAdjustment;
564 MyInfo.InDebugMap =
true;
566 if (Options.Verbose) {
567 outs() <<
"Keeping subprogram DIE:";
568 DIDumpOptions DumpOpts;
569 DumpOpts.ChildRecurseDepth = 0;
570 DumpOpts.Verbose = Options.Verbose;
571 DIE.dump(
outs(), 8 , DumpOpts);
574 if (DIE.getTag() == dwarf::DW_TAG_label) {
575 if (Unit.hasLabelAt(*LowPc))
578 DWARFUnit &OrigUnit = Unit.getOrigUnit();
586 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
587 return Flags | TF_Keep;
592 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
594 reportWarning(
"Function without high_pc. Range will be discarded.\n", File,
598 if (*LowPc > *HighPc) {
599 reportWarning(
"low_pc greater than high_pc. Range will be discarded.\n",
605 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
611unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr,
const DWARFDie &DIE,
612 const DWARFFile &File, CompileUnit &Unit,
613 CompileUnit::DIEInfo &MyInfo,
615 switch (DIE.getTag()) {
616 case dwarf::DW_TAG_constant:
617 case dwarf::DW_TAG_variable:
618 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
619 case dwarf::DW_TAG_subprogram:
620 case dwarf::DW_TAG_label:
621 return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags);
622 case dwarf::DW_TAG_base_type:
625 case dwarf::DW_TAG_imported_module:
626 case dwarf::DW_TAG_imported_declaration:
627 case dwarf::DW_TAG_imported_unit:
629 return Flags | TF_Keep;
643 case dwarf::DW_TAG_structure_type:
644 case dwarf::DW_TAG_class_type:
645 case dwarf::DW_TAG_union_type:
663 case dwarf::DW_TAG_typedef:
664 case dwarf::DW_TAG_member:
665 case dwarf::DW_TAG_reference_type:
666 case dwarf::DW_TAG_ptr_to_member_type:
667 case dwarf::DW_TAG_pointer_type:
684void DWARFLinker::lookForChildDIEsToKeep(
685 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
686 SmallVectorImpl<WorklistItem> &Worklist) {
693 Flags &= ~DWARFLinker::TF_ParentWalk;
697 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
702 for (
auto Child :
reverse(Die.children())) {
705 CompileUnit::DIEInfo &ChildInfo =
CU.getInfo(Child);
706 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateChildIncompleteness,
708 Worklist.emplace_back(Child,
CU, Flags);
715 if (!
Info.Ctxt || (Die.
getTag() == dwarf::DW_TAG_namespace))
718 if (!
CU.hasODR() && !
Info.InModuleScope)
721 return !
Info.Incomplete &&
Info.Ctxt !=
CU.getInfo(
Info.ParentIdx).Ctxt;
724void DWARFLinker::markODRCanonicalDie(
const DWARFDie &Die, CompileUnit &
CU) {
725 CompileUnit::DIEInfo &
Info =
CU.getInfo(Die);
727 Info.ODRMarkingDone =
true;
729 !
Info.Ctxt->hasCanonicalDIE())
730 Info.Ctxt->setHasCanonicalDIE();
735void DWARFLinker::lookForRefDIEsToKeep(
736 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
737 const UnitListTy &Units,
const DWARFFile &File,
738 SmallVectorImpl<WorklistItem> &Worklist) {
739 bool UseOdr = (
Flags & DWARFLinker::TF_DependencyWalk)
740 ? (Flags & DWARFLinker::TF_ODR)
742 DWARFUnit &Unit =
CU.getOrigUnit();
743 DWARFDataExtractor
Data = Unit.getDebugInfoExtractor();
744 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
747 SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs;
748 for (
const auto &AttrSpec : Abbrev->attributes()) {
749 DWARFFormValue Val(AttrSpec.Form);
751 AttrSpec.Attr == dwarf::DW_AT_sibling) {
753 Unit.getFormParams());
757 Val.extractValue(
Data, &
Offset, Unit.getFormParams(), &Unit);
758 CompileUnit *ReferencedCU;
760 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
761 CompileUnit::DIEInfo &
Info = ReferencedCU->getInfo(RefDie);
772 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
774 Info.Ctxt->hasCanonicalDIE())
779 Info.Ctxt->hasCanonicalDIE()))
781 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
785 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
789 for (
auto &
P :
reverse(ReferencedDIEs)) {
792 CompileUnit::DIEInfo &
Info =
P.second.getInfo(
P.first);
793 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateRefIncompleteness,
795 Worklist.emplace_back(
P.first,
P.second,
796 DWARFLinker::TF_Keep |
797 DWARFLinker::TF_DependencyWalk | ODRFlag);
802void DWARFLinker::lookForParentDIEsToKeep(
803 unsigned AncestorIdx, CompileUnit &
CU,
unsigned Flags,
804 SmallVectorImpl<WorklistItem> &Worklist) {
806 if (
CU.getInfo(AncestorIdx).Keep)
809 DWARFUnit &Unit =
CU.getOrigUnit();
810 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);
811 Worklist.emplace_back(
CU.getInfo(AncestorIdx).ParentIdx,
CU, Flags);
812 Worklist.emplace_back(ParentDIE,
CU, Flags);
840void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
842 const DWARFDie &Die,
const DWARFFile &File,
843 CompileUnit &Cu,
unsigned Flags) {
845 SmallVector<WorklistItem, 4> Worklist;
846 Worklist.emplace_back(Die, Cu, Flags);
848 while (!Worklist.empty()) {
849 WorklistItem Current = Worklist.pop_back_val();
852 switch (Current.Type) {
853 case WorklistItemType::UpdateChildIncompleteness:
856 case WorklistItemType::UpdateRefIncompleteness:
859 case WorklistItemType::LookForChildDIEsToKeep:
860 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
862 case WorklistItemType::LookForRefDIEsToKeep:
863 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
866 case WorklistItemType::LookForParentDIEsToKeep:
867 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
870 case WorklistItemType::MarkODRCanonicalDie:
871 markODRCanonicalDie(Current.Die, Current.CU);
873 case WorklistItemType::LookForDIEsToKeep:
877 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
878 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(
Idx);
883 if (Current.Flags & TF_DependencyWalk)
884 MyInfo.Prune =
false;
891 bool AlreadyKept = MyInfo.Keep;
892 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
895 if (!(Current.Flags & TF_DependencyWalk))
896 Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU,
897 MyInfo, Current.Flags);
902 if (!(Current.Flags & TF_DependencyWalk) ||
903 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
904 if (Current.CU.hasODR() || MyInfo.InModuleScope)
905 Worklist.emplace_back(Current.Die, Current.CU,
906 WorklistItemType::MarkODRCanonicalDie);
912 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
913 WorklistItemType::LookForChildDIEsToKeep);
915 if (AlreadyKept || !(Current.Flags & TF_Keep))
924 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
925 Current.Die.getTag() != dwarf::DW_TAG_member &&
931 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
932 WorklistItemType::LookForRefDIEsToKeep);
934 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
935 : Current.CU.hasODR();
936 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
937 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
940 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
956 std::vector<DWARFDie> Worklist;
957 Worklist.push_back(
CU.getOrigUnit().getUnitDIE());
960 std::vector<BrokenLink> BrokenLinks;
962 while (!Worklist.empty()) {
963 const DWARFDie Current = Worklist.back();
966 const bool CurrentDieIsKept =
CU.getInfo(Current).Keep;
969 Worklist.push_back(Child);
971 const bool ChildDieIsKept =
CU.getInfo(Child).Keep;
972 if (!CurrentDieIsKept && ChildDieIsKept)
973 BrokenLinks.emplace_back(Current, Child);
977 if (!BrokenLinks.empty()) {
980 "Found invalid link in keep chain between {0:x} and {1:x}\n",
981 Link.Parent.getOffset(), Link.Child.getOffset());
984 Link.Parent.dump(
errs(), 0, {});
985 CU.getInfo(Link.Parent).dump();
988 Link.Child.dump(
errs(), 2, {});
989 CU.getInfo(Link.Child).dump();
1002void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
1004 FoldingSetNodeID
ID;
1007 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(
ID, InsertToken);
1012 Abbrev.setNumber(InSet->getNumber());
1015 Abbreviations.push_back(
1016 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
1017 for (
const auto &Attr : Abbrev.getData())
1018 Abbreviations.back()->AddAttribute(Attr);
1019 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
1021 Abbrev.setNumber(Abbreviations.size());
1022 Abbreviations.back()->setNumber(Abbreviations.size());
1026unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
1027 AttributeSpec AttrSpec,
1028 const DWARFFormValue &Val,
1030 AttributesInfo &
Info) {
1035 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
1040 if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
1041 Info.HasAppleOrigin =
true;
1042 if (std::optional<StringRef> FileName =
1043 ObjFile.Addresses->getLibraryInstallName()) {
1049 if (AttrSpec.Attr == dwarf::DW_AT_name)
1051 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
1052 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
1054 if (
U.getVersion() >= 5) {
1056 auto StringOffsetIndex =
1057 StringOffsetPool.getValueIndex(
StringEntry.getOffset());
1060 dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
1061 ->sizeOf(
U.getFormParams());
1064 AttrSpec.Form = dwarf::DW_FORM_strp;
1071unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
1072 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1073 unsigned AttrSize,
const DWARFFormValue &Val,
const DWARFFile &File,
1074 CompileUnit &Unit) {
1075 const DWARFUnit &
U = Unit.getOrigUnit();
1078 DIE *NewRefDie =
nullptr;
1079 CompileUnit *RefUnit =
nullptr;
1082 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
1085 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
1088 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
1093 RefInfo.Ctxt->getCanonicalDIEOffset()) {
1094 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
1095 "Offset to canonical die is set, but context is not marked");
1096 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
1098 dwarf::DW_FORM_ref_addr, Attr);
1099 return U.getRefAddrByteSize();
1102 if (!RefInfo.Clone) {
1105 RefInfo.UnclonedReference =
true;
1108 NewRefDie = RefInfo.Clone;
1110 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1118 if (
Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1121 RefUnit->getStartOffset() + NewRefDie->getOffset();
1122 Attr = NewRefOffset;
1124 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));
1128 Unit.noteForwardReference(
1129 NewRefDie, RefUnit, RefInfo.Ctxt,
1131 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
1133 return U.getRefAddrByteSize();
1137 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1142void DWARFLinker::DIECloner::cloneExpression(
1143 DataExtractor &
Data, DWARFExpression Expression,
const DWARFFile &File,
1144 CompileUnit &Unit, SmallVectorImpl<uint8_t> &
OutputBuffer,
1145 int64_t AddrRelocAdjustment,
bool IsLittleEndian) {
1148 uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize();
1151 for (
auto &
Op : Expression) {
1157 Desc.
Op[0] != Encoding::Size1))
1158 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
1162 Desc.
Op[0] == Encoding::Size1)) {
1182 if (RefOffset > 0 ||
Op.
getCode() != dwarf::DW_OP_convert) {
1183 RefOffset += Unit.getOrigUnit().getOffset();
1184 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
1185 CompileUnit::DIEInfo &
Info = Unit.getInfo(RefDie);
1186 if (DIE *Clone =
Info.Clone)
1187 Offset = Clone->getOffset();
1189 Linker.reportWarning(
1190 "base type ref doesn't point to DW_TAG_base_type.", File);
1194 if (RealSize > ULEBsize) {
1197 Linker.reportWarning(
"base type ref doesn't fit.", File);
1199 assert(RealSize == ULEBsize &&
"padding failed");
1200 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1201 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1202 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_addrx) {
1203 if (std::optional<object::SectionedAddress> SA =
1204 Unit.getOrigUnit().getAddrOffsetSectionItem(
1211 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1214 ArrayRef<uint8_t> AddressBytes(
1215 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1216 OrigAddressByteSize);
1217 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1219 Linker.reportWarning(
"cannot read DW_OP_addrx operand.", File);
1220 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_constx) {
1221 if (std::optional<object::SectionedAddress> SA =
1222 Unit.getOrigUnit().getAddrOffsetSectionItem(
1228 std::optional<uint8_t> OutOperandKind;
1229 switch (OrigAddressByteSize) {
1231 OutOperandKind = dwarf::DW_OP_const4u;
1234 OutOperandKind = dwarf::DW_OP_const8u;
1237 Linker.reportWarning(
1238 formatv((
"unsupported address size: {0}."), OrigAddressByteSize),
1243 if (OutOperandKind) {
1245 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1248 ArrayRef<uint8_t> AddressBytes(
1249 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1250 OrigAddressByteSize);
1251 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1254 Linker.reportWarning(
"cannot read DW_OP_constx operand.", File);
1264unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1265 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1266 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1267 bool IsLittleEndian) {
1270 DIELoc *Loc =
nullptr;
1271 DIEBlock *
Block =
nullptr;
1272 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1273 Loc =
new (DIEAlloc) DIELoc;
1274 Linker.DIELocs.push_back(Loc);
1276 Block =
new (DIEAlloc) DIEBlock;
1277 Linker.DIEBlocks.push_back(
Block);
1279 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1280 :
static_cast<DIEValueList *
>(
Block);
1282 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1285 SmallVector<uint8_t, 32> Buffer;
1286 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1290 DataExtractor
Data(StringRef((
const char *)Bytes.data(), Bytes.size()),
1291 IsLittleEndian, OrigUnit.getAddressByteSize());
1292 DWARFExpression Expr(
Data, OrigUnit.getAddressByteSize(),
1293 OrigUnit.getFormParams().Format);
1294 cloneExpression(
Data, Expr, File, Unit, Buffer,
1295 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);
1298 for (
auto Byte : Bytes)
1300 dwarf::DW_FORM_data1, DIEInteger(Byte));
1306 Loc->setSize(Bytes.size());
1308 Block->setSize(Bytes.size());
1316 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&
1317 (Bytes.size() > UINT8_MAX)) ||
1318 (AttrSpec.Form == dwarf::DW_FORM_block2 &&
1319 (Bytes.size() > UINT16_MAX)) ||
1320 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))
1321 AttrSpec.Form = dwarf::DW_FORM_block;
1327 return Die.addValue(DIEAlloc, Value)->sizeOf(OrigUnit.getFormParams());
1330unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1331 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1332 unsigned AttrSize,
const DWARFFormValue &Val,
const CompileUnit &Unit,
1333 AttributesInfo &
Info) {
1334 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1335 Info.HasLowPc =
true;
1339 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1355 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1359 std::optional<uint64_t>
Addr = AddrAttribute->getAsAddress();
1361 Linker.reportWarning(
"Cann't read address attribute value.", ObjFile);
1365 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1366 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1367 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
1371 }
else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1372 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1373 if (
uint64_t HighPc = Unit.getHighPc())
1381 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
1383 AttrSpec.Form, DIEInteger(*
Addr));
1384 return Unit.getOrigUnit().getAddressByteSize();
1387 auto AddrIndex = AddrPool.getValueIndex(*
Addr);
1391 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))
1392 ->sizeOf(Unit.getOrigUnit().getFormParams());
1395unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1396 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1397 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1398 unsigned AttrSize, AttributesInfo &
Info) {
1403 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1404 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1411 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1412 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1419 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1423 Info.AttrStrOffsetBaseSeen =
true;
1425 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1426 dwarf::DW_FORM_sec_offset, DIEInteger(8))
1427 ->sizeOf(Unit.getOrigUnit().getFormParams());
1431 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1432 Value = *OptionalValue;
1433 else if (
auto OptionalValue = Val.getAsSignedConstant())
1434 Value = *OptionalValue;
1435 else if (
auto OptionalValue = Val.getAsSectionOffset())
1436 Value = *OptionalValue;
1438 Linker.reportWarning(
1439 "Unsupported scalar attribute form. Dropping attribute.", File,
1443 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1444 Info.IsDeclaration =
true;
1446 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1455 [[maybe_unused]]
dwarf::Form OriginalForm = AttrSpec.Form;
1456 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1460 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1462 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1466 std::optional<uint64_t>
Offset =
1467 Unit.getOrigUnit().getRnglistOffset(*
Index);
1469 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1475 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1476 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1477 }
else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1481 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1483 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1487 std::optional<uint64_t>
Offset =
1488 Unit.getOrigUnit().getLoclistOffset(*
Index);
1490 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1496 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1497 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1498 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1499 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1500 std::optional<uint64_t> LowPC = Unit.getLowPc();
1504 Value = Unit.getHighPc() - *LowPC;
1505 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1506 Value = *Val.getAsSectionOffset();
1507 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1508 Value = *Val.getAsSignedConstant();
1509 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1510 Value = *OptionalValue;
1512 Linker.reportWarning(
1513 "Unsupported scalar attribute form. Dropping attribute.", File,
1518 DIE::value_iterator Patch =
1521 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1522 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1523 Unit.noteRangeAttribute(Die, Patch);
1524 Info.HasRanges =
true;
1528 Unit.getOrigUnit().getVersion())) {
1530 CompileUnit::DIEInfo &LocationDieInfo = Unit.getInfo(InputDIE);
1531 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
1532 ? LocationDieInfo.AddrAdjust
1534 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1535 Info.IsDeclaration =
true;
1538 assert((
Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1539 "Unhandled DW_FORM_rnglistx attribute");
1547unsigned DWARFLinker::DIECloner::cloneAttribute(
1548 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1549 CompileUnit &Unit,
const DWARFFormValue &Val,
const AttributeSpec AttrSpec,
1550 unsigned AttrSize, AttributesInfo &
Info,
bool IsLittleEndian) {
1551 const DWARFUnit &
U = Unit.getOrigUnit();
1553 switch (AttrSpec.Form) {
1554 case dwarf::DW_FORM_strp:
1555 case dwarf::DW_FORM_line_strp:
1556 case dwarf::DW_FORM_string:
1557 case dwarf::DW_FORM_strx:
1558 case dwarf::DW_FORM_strx1:
1559 case dwarf::DW_FORM_strx2:
1560 case dwarf::DW_FORM_strx3:
1561 case dwarf::DW_FORM_strx4:
1562 return cloneStringAttribute(Die, AttrSpec, Val, U,
Info);
1563 case dwarf::DW_FORM_ref_addr:
1564 case dwarf::DW_FORM_ref1:
1565 case dwarf::DW_FORM_ref2:
1566 case dwarf::DW_FORM_ref4:
1567 case dwarf::DW_FORM_ref8:
1568 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1570 case dwarf::DW_FORM_block:
1571 case dwarf::DW_FORM_block1:
1572 case dwarf::DW_FORM_block2:
1573 case dwarf::DW_FORM_block4:
1574 case dwarf::DW_FORM_exprloc:
1575 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1577 case dwarf::DW_FORM_addr:
1578 case dwarf::DW_FORM_addrx:
1579 case dwarf::DW_FORM_addrx1:
1580 case dwarf::DW_FORM_addrx2:
1581 case dwarf::DW_FORM_addrx3:
1582 case dwarf::DW_FORM_addrx4:
1583 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1585 case dwarf::DW_FORM_data1:
1586 case dwarf::DW_FORM_data2:
1587 case dwarf::DW_FORM_data4:
1588 case dwarf::DW_FORM_data8:
1589 case dwarf::DW_FORM_udata:
1590 case dwarf::DW_FORM_sdata:
1591 case dwarf::DW_FORM_sec_offset:
1592 case dwarf::DW_FORM_flag:
1593 case dwarf::DW_FORM_flag_present:
1594 case dwarf::DW_FORM_rnglistx:
1595 case dwarf::DW_FORM_loclistx:
1596 case dwarf::DW_FORM_implicit_const:
1597 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1600 Linker.reportWarning(
"Unsupported attribute form " +
1602 " in cloneAttribute. Dropping.",
1609void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1611 DwarfStringPoolEntryRef
Name,
1613 bool SkipPubSection) {
1614 std::optional<ObjCSelectorNames> Names =
1618 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),
1620 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),
1622 if (Names->ClassNameNoCategory)
1623 Unit.addObjCAccelerator(
1624 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);
1625 if (Names->MethodNameNoCategory)
1626 Unit.addNameAccelerator(
1627 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);
1634 switch (AttrSpec.
Attr) {
1637 case dwarf::DW_AT_low_pc:
1638 case dwarf::DW_AT_high_pc:
1639 case dwarf::DW_AT_ranges:
1640 return !Update && SkipPC;
1641 case dwarf::DW_AT_rnglists_base:
1647 case dwarf::DW_AT_loclists_base:
1653 case dwarf::DW_AT_location:
1654 case dwarf::DW_AT_frame_base:
1655 return !Update && SkipPC;
1665DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1667 int64_t PCOffset,
uint32_t OutOffset,
1668 unsigned Flags,
bool IsLittleEndian,
1671 unsigned Idx = U.getDIEIndex(InputDIE);
1675 if (!Unit.getInfo(
Idx).Keep)
1679 assert(!(Die &&
Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1691 (
Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1692 if (!
Info.Ctxt->hasCanonicalDIE())
1693 Info.Ctxt->setHasCanonicalDIE();
1697 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1701 DWARFDataExtractor
Data =
U.getDebugInfoExtractor();
1706 ?
U.getDIEAtIndex(
Idx + 1).getOffset()
1707 :
U.getNextUnitOffset();
1708 AttributesInfo AttrInfo;
1713 SmallString<40> DIECopy(
Data.getData().substr(
Offset, NextOffset -
Offset));
1715 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1718 ObjFile.Addresses->applyValidRelocs(DIECopy,
Offset,
Data.isLittleEndian());
1728 if (Die->
getTag() == dwarf::DW_TAG_subprogram)
1729 PCOffset =
Info.AddrAdjust;
1730 AttrInfo.PCOffset = PCOffset;
1732 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1733 Flags |= TF_InFunctionScope;
1736 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1739 if ((Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1740 Flags &= ~TF_SkipPC;
1743 else if (!
Info.InDebugMap &&
Info.HasLocationExpressionAddr &&
1748 std::optional<StringRef> LibraryInstallName =
1749 ObjFile.Addresses->getLibraryInstallName();
1750 SmallVector<AttributeLinkedOffsetFixup> AttributesFixups;
1751 for (
const auto &AttrSpec : Abbrev->attributes()) {
1758 AttributeLinkedOffsetFixup CurAttrFixup;
1760 CurAttrFixup.LinkedOffsetFixupVal =
1761 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1763 DWARFFormValue Val = AttrSpec.getFormValue();
1765 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1767 AttrSize =
Offset - AttrSize;
1770 cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
1771 AttrInfo, IsLittleEndian);
1772 if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
1773 AttributesFixups.push_back(CurAttrFixup);
1775 OutOffset += FinalAttrSize;
1781 const bool NeedsAppleOrigin = (
Tag == dwarf::DW_TAG_compile_unit) &&
1782 LibraryInstallName.has_value() &&
1783 !AttrInfo.HasAppleOrigin;
1784 if (NeedsAppleOrigin) {
1785 auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
1787 dwarf::DW_FORM_strp, DIEInteger(
StringEntry.getOffset()));
1796 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1797 Tag != dwarf::DW_TAG_compile_unit &&
1798 getDIENames(InputDIE, AttrInfo, DebugStrPool,
1799 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1800 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1801 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1802 Tag == dwarf::DW_TAG_inlined_subroutine);
1803 if (AttrInfo.Name) {
1804 if (AttrInfo.NameWithoutTemplate)
1805 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1807 Unit.addNameAccelerator(Die, AttrInfo.Name,
1808 Tag == dwarf::DW_TAG_inlined_subroutine);
1811 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,
1814 }
else if (
Tag == dwarf::DW_TAG_namespace) {
1816 AttrInfo.Name = DebugStrPool.getEntry(
"(anonymous namespace)");
1817 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1818 }
else if (
Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1819 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1820 }
else if (
isTypeTag(
Tag) && !AttrInfo.IsDeclaration &&
1821 getDIENames(InputDIE, AttrInfo, DebugStrPool) && AttrInfo.Name &&
1822 AttrInfo.Name.getString()[0]) {
1827 bool ObjCClassIsImplementation =
1828 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1829 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1832 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1837 bool HasChildren =
false;
1838 for (
auto Child : InputDIE.
children()) {
1839 unsigned Idx =
U.getDIEIndex(Child);
1840 if (Unit.getInfo(
Idx).Keep) {
1846 if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
1847 Die->
getTag() == dwarf::DW_TAG_compile_unit) {
1849 Die->
addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1850 dwarf::DW_FORM_sec_offset, DIEInteger(8));
1858 Linker.assignAbbrev(NewAbbrev);
1864 OutOffset += AbbrevNumberSize;
1867 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
1868 F.LinkedOffsetFixupVal += AbbrevNumberSize;
1870 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
1871 ObjFile.Addresses->updateAndSaveValidRelocs(
1872 Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(),
1873 F.LinkedOffsetFixupVal,
F.InputAttrStartOffset,
F.InputAttrEndOffset);
1882 for (
auto Child : InputDIE.
children()) {
1883 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
1886 OutOffset = Clone->getOffset() + Clone->getSize();
1891 OutOffset +=
sizeof(int8_t);
1900void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File,
1905 const auto &FunctionRanges = Unit.getFunctionRanges();
1908 AddressRanges LinkedFunctionRanges;
1909 for (
const AddressRangeValuePair &
Range : FunctionRanges)
1910 LinkedFunctionRanges.insert(
1914 if (!LinkedFunctionRanges.empty())
1918 std::optional<PatchLocation> UnitRngListAttribute =
1919 Unit.getUnitRangesAttribute();
1921 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
1922 std::optional<AddressRangeValuePair> CachedRange;
1927 for (PatchLocation &AttributePatch : AllRngListAttributes) {
1930 AddressRanges LinkedRanges;
1931 if (Expected<DWARFAddressRangesVector> OriginalRanges =
1932 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
1934 for (
const auto &
Range : *OriginalRanges) {
1935 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
1936 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
1940 reportWarning(
"inconsistent range data.", File);
1945 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
1946 Range.HighPC + CachedRange->Value});
1950 reportWarning(
"invalid range list ignored.", File);
1955 Unit, LinkedRanges, AttributePatch, AddrPool);
1959 if (UnitRngListAttribute.has_value())
1961 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);
1968void DWARFLinker::DIECloner::generateUnitLocations(
1969 CompileUnit &Unit,
const DWARFFile &File,
1970 ExpressionHandlerRef ExprHandler) {
1975 Unit.getLocationAttributes();
1977 if (AllLocListAttributes.empty())
1983 for (
auto &CurLocAttr : AllLocListAttributes) {
1986 Expected<DWARFLocationExpressionsVector> OriginalLocations =
1987 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
1989 if (!OriginalLocations) {
1991 Linker.reportWarning(
"Invalid location attribute ignored.", File);
1996 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
1997 DWARFLocationExpression LinkedExpression;
1999 if (CurExpression.Range) {
2001 LinkedExpression.Range = {
2002 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
2003 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
2007 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
2008 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
2009 CurLocAttr.RelocAdjustment);
2011 LinkedLocationExpressions.push_back(LinkedExpression);
2015 Emitter->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions,
2016 CurLocAttr, AddrPool);
2020 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
2024 for (
auto &V : Die.
values())
2025 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
2033void DWARFLinker::DIECloner::emitDebugAddrSection(
2034 CompileUnit &Unit,
const uint16_t DwarfVersion)
const {
2039 if (DwarfVersion < 5)
2042 if (AddrPool.getValues().empty())
2045 MCSymbol *EndLabel =
Emitter->emitDwarfDebugAddrsHeader(Unit);
2047 DIEInteger(
Emitter->getDebugAddrSectionSize()));
2048 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),
2049 Unit.getOrigUnit().getAddressByteSize());
2050 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
2056 std::vector<DWARFDebugLine::Row> &Rows) {
2060 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
2074 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
2075 InsertPoint->EndSequence) {
2076 *InsertPoint = Seq.front();
2077 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
2079 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
2086 for (
auto &V : Die.
values())
2087 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2095void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2096 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2097 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2099 if (std::optional<uint64_t> MacroAttr =
2101 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2105 if (std::optional<uint64_t> MacroAttr =
2107 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2112void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2117 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
2123 if (
auto *OutputDIE = Unit.getOutputUnitDIE())
2126 if (
const DWARFDebugLine::LineTable *LT =
2127 ObjFile.Dwarf->getLineTableForUnit(&Unit.getOrigUnit())) {
2129 DWARFDebugLine::LineTable LineTable;
2132 LineTable.Prologue =
LT->Prologue;
2135 if (Linker.Options.Update) {
2136 LineTable.Rows =
LT->Rows;
2139 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2140 LineTable.Rows.clear();
2142 LineTable.Sequences =
LT->Sequences;
2145 std::vector<DWARFDebugLine::Row> NewRows;
2146 NewRows.reserve(
LT->Rows.size());
2150 std::vector<DWARFDebugLine::Row> Seq;
2152 const auto &FunctionRanges = Unit.getFunctionRanges();
2153 std::optional<AddressRangeValuePair> CurrRange;
2166 for (DWARFDebugLine::Row Row :
LT->Rows) {
2172 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {
2176 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2177 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
2178 if (StopAddress != -1ULL && !Seq.empty()) {
2181 auto NextLine = Seq.back();
2182 NextLine.Address.Address = StopAddress;
2183 NextLine.EndSequence = 1;
2184 NextLine.PrologueEnd = 0;
2185 NextLine.BasicBlock = 0;
2186 NextLine.EpilogueBegin = 0;
2187 Seq.push_back(NextLine);
2196 if (Row.EndSequence && Seq.empty())
2200 Row.Address.Address += CurrRange->Value;
2201 Seq.emplace_back(Row);
2203 if (Row.EndSequence)
2207 LineTable.Rows = std::move(NewRows);
2210 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2213 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2216void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2221 for (
const auto &Namespace : Unit.getNamespaces())
2222 AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() +
2223 Unit.getStartOffset());
2225 for (
const auto &Pubname : Unit.getPubnames())
2226 AppleNames.addName(Pubname.Name,
2227 Pubname.Die->getOffset() + Unit.getStartOffset());
2229 for (
const auto &Pubtype : Unit.getPubtypes())
2231 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
2232 Pubtype.Die->getTag(),
2235 Pubtype.QualifiedNameHash);
2237 for (
const auto &ObjC : Unit.getObjC())
2238 AppleObjc.addName(
ObjC.Name,
2239 ObjC.Die->getOffset() + Unit.getStartOffset());
2246 for (
const auto &Namespace : Unit.getNamespaces())
2248 Namespace.Name, Namespace.Die->getOffset(),
2250 Namespace.Die->getTag(), Unit.getUniqueID(),
2251 Unit.getTag() == dwarf::DW_TAG_type_unit);
2252 for (
const auto &Pubname : Unit.getPubnames())
2254 Pubname.Name, Pubname.Die->getOffset(),
2256 Pubname.Die->getTag(), Unit.getUniqueID(),
2257 Unit.getTag() == dwarf::DW_TAG_type_unit);
2258 for (
const auto &Pubtype : Unit.getPubtypes())
2260 Pubtype.Name, Pubtype.Die->getOffset(),
2262 Pubtype.Die->getTag(), Unit.getUniqueID(),
2263 Unit.getTag() == dwarf::DW_TAG_type_unit);
2275void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) {
2276 DWARFContext &OrigDwarf = *Context.File.Dwarf;
2277 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2279 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2284 for (std::unique_ptr<CompileUnit> &Unit : Context.CompileUnits) {
2285 for (
auto CurRange : Unit->getFunctionRanges())
2286 AllUnitsRanges.
insert(CurRange.Range, CurRange.Value);
2289 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian(), 0);
2294 DenseMap<uint64_t, StringRef> LocalCIES;
2296 while (
Data.isValidOffset(InputOffset)) {
2297 uint64_t EntryOffset = InputOffset;
2299 if (InitialLength == 0xFFFFFFFF)
2300 return reportWarning(
"Dwarf64 bits no supported", Context.File);
2303 if (CIEId == 0xFFFFFFFF) {
2305 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2306 LocalCIES[EntryOffset] = CIEData;
2308 InputOffset += InitialLength - 4;
2312 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2318 std::optional<AddressRangeValuePair>
Range =
2319 AllUnitsRanges.getRangeThatContains(Loc);
2322 InputOffset = EntryOffset + InitialLength + 4;
2328 StringRef CIEData = LocalCIES[CIEId];
2329 if (CIEData.empty())
2330 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2335 auto IteratorInserted = EmittedCIEs.
insert(
2338 if (IteratorInserted.second) {
2340 IteratorInserted.first->getValue() = LastCIEOffset;
2341 TheDwarfEmitter->
emitCIE(CIEData);
2347 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2348 TheDwarfEmitter->
emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2350 FrameData.substr(InputOffset, FDERemainingBytes));
2351 InputOffset += FDERemainingBytes;
2355uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2357 const DWARFFile &File,
2358 int ChildRecurseDepth) {
2359 const char *
Name =
nullptr;
2360 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2361 CompileUnit *
CU = &
U;
2362 std::optional<DWARFFormValue>
Ref;
2368 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2369 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2377 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2379 OrigUnit = &RefCU->getOrigUnit();
2384 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2385 if (!
Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2386 Name =
"(anonymous namespace)";
2388 if (
CU->getInfo(
Idx).ParentIdx == 0 ||
2390 CU->getOrigUnit().getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx).getTag() ==
2391 dwarf::DW_TAG_module)
2394 DWARFDie Die = OrigUnit->getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx);
2403 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2412 if (ObjectPrefixMap.empty())
2416 for (
const auto &Entry : ObjectPrefixMap)
2419 return p.str().str();
2426 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2428 if (PCMFile.empty())
2431 if (ObjectPrefixMap)
2432 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2437std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2438 std::string &PCMFile,
2439 LinkContext &Context,
2442 if (PCMFile.empty())
2443 return std::make_pair(
false,
false);
2451 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2453 return std::make_pair(
true,
true);
2456 if (!
Quiet && Options.Verbose) {
2458 outs() <<
"Found clang module reference " << PCMFile;
2461 auto Cached = ClangModules.
find(PCMFile);
2462 if (Cached != ClangModules.
end()) {
2466 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2467 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2468 "different version of the module ") +
2471 if (!
Quiet && Options.Verbose)
2472 outs() <<
" [cached].\n";
2473 return std::make_pair(
true,
true);
2476 return std::make_pair(
true,
false);
2479bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2480 LinkContext &Context,
2481 ObjFileLoaderTy Loader,
2482 CompileUnitHandlerTy OnCUDieLoaded,
2484 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2485 std::pair<bool, bool> IsClangModuleRef =
2486 isClangModuleRef(CUDie, PCMFile, Context, Indent,
false);
2488 if (!IsClangModuleRef.first)
2491 if (IsClangModuleRef.second)
2494 if (Options.Verbose)
2501 if (Error
E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded,
2509Error DWARFLinker::loadClangModule(
2510 ObjFileLoaderTy Loader,
const DWARFDie &CUDie,
const std::string &PCMFile,
2511 LinkContext &Context, CompileUnitHandlerTy OnCUDieLoaded,
unsigned Indent) {
2517 SmallString<0>
Path(Options.PrependPath);
2524 if (Loader ==
nullptr) {
2525 reportError(
"Could not load clang module: loader is not specified.\n",
2530 auto ErrOrObj = Loader(Context.File.FileName, Path);
2534 std::unique_ptr<CompileUnit> Unit;
2535 for (
const auto &
CU : ErrOrObj->Dwarf->compile_units()) {
2538 auto ChildCUDie =
CU->getUnitDIE();
2541 if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded,
2546 ": Clang modules are expected to have exactly 1 compile unit.\n");
2547 reportError(Err, Context.File);
2554 if (PCMDwoId != DwoId) {
2555 if (Options.Verbose)
2557 Twine(
"hash mismatch: this object file was built against a "
2558 "different version of the module ") +
2562 ClangModules[PCMFile] = PCMDwoId;
2566 Unit = std::make_unique<CompileUnit>(*
CU, UniqueUnitID++, !Options.NoODR,
2572 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2577uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2578 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2581 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2583 for (
auto &CurrentUnit : CompileUnits) {
2584 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2585 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2586 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2587 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2589 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2592 if (CurrentUnit->getInfo(0).Keep) {
2595 CurrentUnit->createOutputDIE();
2596 rememberUnitForMacroOffset(*CurrentUnit);
2597 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2598 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2601 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2605 generateLineTableForUnit(*CurrentUnit);
2607 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2612 Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);
2614 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2615 SmallVectorImpl<uint8_t> &OutBytes,
2616 int64_t RelocAdjustment) {
2617 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2618 DataExtractor
Data(SrcBytes, IsLittleEndian,
2619 OrigUnit.getAddressByteSize());
2620 cloneExpression(
Data,
2621 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2622 OrigUnit.getFormParams().Format),
2623 File, *CurrentUnit, OutBytes, RelocAdjustment,
2626 generateUnitLocations(*CurrentUnit, File, ProcessExpr);
2627 emitDebugAddrSection(*CurrentUnit, DwarfVersion);
2635 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2638 for (
auto &CurrentUnit : CompileUnits) {
2639 CurrentUnit->fixupForwardReferences();
2641 if (!CurrentUnit->getOutputUnitDIE())
2644 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2647 CurrentUnit->getStartOffset());
2648 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2649 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2651 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2655 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2658void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2662 Dwarf.getDWARFObj().getRangesSection().Data,
2671 Dwarf.getDWARFObj().getRnglistsSection().Data,
2674 Dwarf.getDWARFObj().getLoclistsSection().Data,
2680 ObjectContexts.emplace_back(LinkContext(File));
2682 if (ObjectContexts.back().File.Dwarf) {
2683 for (
const std::unique_ptr<DWARFUnit> &
CU :
2684 ObjectContexts.back().File.Dwarf->compile_units()) {
2693 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
2700 assert((Options.TargetDWARFVersion != 0) &&
2701 "TargetDWARFVersion should be set");
2705 unsigned NumObjects = ObjectContexts.size();
2717 for (LinkContext &OptContext : ObjectContexts) {
2718 if (Options.Verbose)
2719 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
2721 if (!OptContext.File.Dwarf)
2724 if (Options.VerifyInputDWARF)
2725 verifyInput(OptContext.File);
2732 !OptContext.File.Addresses->hasValidRelocs()) {
2733 if (Options.Verbose)
2734 outs() <<
"No valid relocations found. Skipping.\n";
2738 OptContext.Skip =
true;
2743 if (!OptContext.File.Dwarf)
2747 if (!OptContext.File.Dwarf->types_section_units().empty()) {
2748 reportWarning(
"type units are not currently supported: file will "
2751 OptContext.Skip =
true;
2757 OptContext.CompileUnits.reserve(
2758 OptContext.File.Dwarf->getNumCompileUnits());
2759 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
2760 auto CUDie =
CU->getUnitDIE(
true);
2761 if (Options.Verbose) {
2762 outs() <<
"Input compilation unit:";
2765 DumpOpts.
Verbose = Options.Verbose;
2766 CUDie.dump(
outs(), 0, DumpOpts);
2770 for (
auto &
CU : OptContext.ModuleUnits) {
2771 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
2772 DebugLineStrPool, StringOffsetPool))
2773 reportWarning(
toString(std::move(Err)),
CU.File);
2783 (TheDwarfEmitter ==
nullptr) ? 0
2788 std::mutex ProcessedFilesMutex;
2789 std::condition_variable ProcessedFilesConditionVariable;
2790 BitVector ProcessedFiles(NumObjects,
false);
2794 auto AnalyzeLambda = [&](
size_t I) {
2795 auto &Context = ObjectContexts[
I];
2797 if (Context.Skip || !Context.File.Dwarf)
2800 for (
const auto &
CU : Context.File.Dwarf->compile_units()) {
2803 auto CUDie =
CU->getUnitDIE(
false);
2804 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2807 !isClangModuleRef(CUDie, PCMFile, Context, 0,
true).first) {
2808 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
2809 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
2814 for (
auto &CurrentUnit : Context.CompileUnits) {
2815 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
2819 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
2820 ModulesEndOffset, Options.ParseableSwiftInterfaces,
2822 reportWarning(Warning, Context.File, &DIE);
2834 auto CloneLambda = [&](
size_t I) {
2835 auto &OptContext = ObjectContexts[
I];
2836 if (OptContext.Skip || !OptContext.File.Dwarf)
2845 for (
auto &CurrentUnit : OptContext.CompileUnits)
2846 CurrentUnit->markEverythingAsKept();
2847 copyInvariantDebugSection(*OptContext.File.Dwarf);
2849 for (
auto &CurrentUnit : OptContext.CompileUnits) {
2850 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
2851 CurrentUnit->getOrigUnit().getUnitDIE(),
2852 OptContext.File, *CurrentUnit, 0);
2862 if (OptContext.File.Addresses->hasValidRelocs() ||
2864 SizeByObject[OptContext.File.FileName].Input =
2866 SizeByObject[OptContext.File.FileName].Output =
2867 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
2868 OptContext.CompileUnits, Options.Update, DebugStrPool,
2869 DebugLineStrPool, StringOffsetPool)
2870 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
2871 OptContext.File.Dwarf->isLittleEndian());
2873 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
2875 patchFrameInfoForObject(OptContext);
2878 cleanupAuxiliarryData(OptContext);
2881 auto EmitLambda = [&]() {
2883 if (TheDwarfEmitter !=
nullptr) {
2884 TheDwarfEmitter->
emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
2887 Options.TargetDWARFVersion);
2890 switch (TableKind) {
2909 auto AnalyzeAll = [&]() {
2910 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2913 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2914 ProcessedFiles.
set(
I);
2915 ProcessedFilesConditionVariable.notify_one();
2919 auto CloneAll = [&]() {
2920 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2922 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2923 if (!ProcessedFiles[
I]) {
2924 ProcessedFilesConditionVariable.wait(
2925 LockGuard, [&]() {
return ProcessedFiles[
I]; });
2937 if (Options.Threads == 1) {
2938 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2945 Pool.
async(AnalyzeAll);
2946 Pool.
async(CloneAll);
2950 if (Options.Statistics) {
2952 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
2953 for (
auto &
E : SizeByObject)
2954 Sorted.emplace_back(
E.first(),
E.second);
2956 return LHS.second.Output >
RHS.second.Output;
2959 auto ComputePercentange = [](int64_t Input, int64_t Output) ->
float {
2960 const float Difference = Output - Input;
2961 const float Sum = Input + Output;
2964 return (Difference / (Sum / 2));
2967 int64_t InputTotal = 0;
2968 int64_t OutputTotal = 0;
2969 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
2972 outs() <<
".debug_info section size (in bytes)\n";
2973 outs() <<
"----------------------------------------------------------------"
2974 "---------------\n";
2975 outs() <<
"Filename Object "
2977 outs() <<
"----------------------------------------------------------------"
2978 "---------------\n";
2981 for (
auto &
E : Sorted) {
2982 InputTotal +=
E.second.Input;
2983 OutputTotal +=
E.second.Output;
2986 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
2989 outs() <<
"----------------------------------------------------------------"
2990 "---------------\n";
2992 ComputePercentange(InputTotal, OutputTotal));
2993 outs() <<
"----------------------------------------------------------------"
2994 "---------------\n\n";
3000Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3006 assert(Unit.Unit.get() !=
nullptr);
3008 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3011 if (Options.Verbose) {
3013 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3018 &ODRContexts.
getRoot(), ODRContexts, 0,
3019 Options.ParseableSwiftInterfaces,
3021 reportWarning(Warning, Context.File, &DIE);
3024 Unit.Unit->markEverythingAsKept();
3028 CompileUnits.emplace_back(std::move(Unit.Unit));
3030 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3031 Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
3032 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3033 Unit.File.Dwarf->isLittleEndian());
3037void DWARFLinker::verifyInput(
const DWARFFile &File) {
3044 if (Options.InputVerificationHandler)
3045 Options.InputVerificationHandler(File,
OS.str());
static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE, int ChildRecurseDepth=0)
This file implements the BitVector class.
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))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void addName(DwarfStringPoolEntryRef Name, Types &&... Args)
void insert(AddressRange Range, int64_t Value)
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.
DIEAbbrev generateAbbrev() const
Generate the abbreviation for this DIE.
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
void setAbbrevNumber(unsigned I)
Set the abbreviation number for this DIE.
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
void setOffset(unsigned O)
dwarf::Tag getTag() const
static std::optional< uint64_t > getDefiningParentDieOffset(const DIE &Die)
If Die has a non-null parent and the parent is not a declaration, return its offset.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
uint64_t getOffset() const
Get the absolute offset into the debug info or types section.
iterator_range< iterator > children() const
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
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 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.
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.
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.
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
static const 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)
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
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.
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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 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)
static void insertLineSequence(std::vector< DWARFDebugLine::Row > &Seq, std::vector< DWARFDebugLine::Row > &Rows)
Insert the new line info sequence Seq into the current set of already linked line info Rows.
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
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
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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)
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.
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.
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)
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 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 bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
static bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Standard .debug_line state machine structure.
SmallVector< Encoding > Op
Encoding for Op operands.
Hold the input and output of the debug info size in bytes.
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?