51 for (
auto &Unit :
Dwarf.compile_units()) {
52 Size += Unit->getLength();
62 return LHS <
RHS->getOrigUnit().getNextUnitOffset();
64 return CU != Units.end() ?
CU->get() :
nullptr;
70DWARFDie DWARFLinker::resolveDIEReference(
const DWARFFile &File,
72 const DWARFFormValue &RefValue,
74 CompileUnit *&RefCU) {
76 uint64_t RefOffset = *RefValue.getAsReference();
78 if (
const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
85 reportWarning(
"could not find referenced DIE", File, &DIE);
95 case dwarf::DW_AT_type:
96 case dwarf::DW_AT_containing_type:
97 case dwarf::DW_AT_specification:
98 case dwarf::DW_AT_abstract_origin:
99 case dwarf::DW_AT_import:
107 case dwarf::DW_TAG_array_type:
108 case dwarf::DW_TAG_class_type:
109 case dwarf::DW_TAG_enumeration_type:
110 case dwarf::DW_TAG_pointer_type:
111 case dwarf::DW_TAG_reference_type:
112 case dwarf::DW_TAG_string_type:
113 case dwarf::DW_TAG_structure_type:
114 case dwarf::DW_TAG_subroutine_type:
115 case dwarf::DW_TAG_typedef:
116 case dwarf::DW_TAG_union_type:
117 case dwarf::DW_TAG_ptr_to_member_type:
118 case dwarf::DW_TAG_set_type:
119 case dwarf::DW_TAG_subrange_type:
120 case dwarf::DW_TAG_base_type:
121 case dwarf::DW_TAG_const_type:
122 case dwarf::DW_TAG_constant:
123 case dwarf::DW_TAG_file_type:
124 case dwarf::DW_TAG_namelist:
125 case dwarf::DW_TAG_packed_type:
126 case dwarf::DW_TAG_volatile_type:
127 case dwarf::DW_TAG_restrict_type:
128 case dwarf::DW_TAG_atomic_type:
129 case dwarf::DW_TAG_interface_type:
130 case dwarf::DW_TAG_unspecified_type:
131 case dwarf::DW_TAG_shared_type:
132 case dwarf::DW_TAG_immutable_type:
144bool DWARFLinker::DIECloner::getDIENames(
const DWARFDie &Die,
145 AttributesInfo &
Info,
147 bool StripTemplate) {
151 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
154 if (!
Info.MangledName)
155 if (
const char *MangledName = Die.getLinkageName())
156 Info.MangledName = StringPool.getEntry(MangledName);
159 if (
const char *
Name = Die.getShortName())
160 Info.Name = StringPool.getEntry(
Name);
162 if (!
Info.MangledName)
165 if (StripTemplate &&
Info.Name &&
Info.MangledName !=
Info.Name) {
166 StringRef
Name =
Info.Name.getString();
168 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
171 return Info.Name ||
Info.MangledName;
185 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
186 if (
CU.getLanguage() != dwarf::DW_LANG_Swift)
189 if (!ParseableSwiftInterfaces)
193 if (!Path.endswith(
".swiftinterface"))
198 SysRoot =
CU.getSysRoot();
199 if (!SysRoot.
empty() && Path.startswith(SysRoot))
201 std::optional<const char *>
Name =
205 auto &Entry = (*ParseableSwiftInterfaces)[*
Name];
207 DWARFDie CUDie =
CU.getOrigUnit().getUnitDIE();
212 if (!Entry.empty() && Entry != ResolvedPath)
213 ReportWarning(
Twine(
"Conflicting parseable interfaces for Swift Module ") +
214 *
Name +
": " + Entry +
" and " + Path,
216 Entry = std::string(ResolvedPath.
str());
259 Info.Prune &= (Die.
getTag() == dwarf::DW_TAG_module) ||
265 if (ModulesEndOffset == 0)
266 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset();
268 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset() > 0 &&
269 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
292 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
294 std::vector<ContextWorklistItem> Worklist;
295 Worklist.emplace_back(
DIE, CurrentDeclContext, ParentIdx,
false);
297 while (!Worklist.empty()) {
301 switch (Current.
Type) {
312 unsigned Idx =
CU.getOrigUnit().getDIEIndex(Current.
Die);
327 if (Current.
Die.
getTag() == dwarf::DW_TAG_module &&
330 CU.getClangModuleName()) {
338 if (
CU.hasODR() ||
Info.InModuleScope) {
342 Current.
Context = PtrInvalidPair.getPointer();
344 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
346 Info.Ctxt->setDefinedInClangModule(
Info.InModuleScope);
357 Worklist.emplace_back(
359 Worklist.emplace_back(Child, Current.
Context,
Idx,
369 case dwarf::DW_TAG_class_type:
370 case dwarf::DW_TAG_common_block:
371 case dwarf::DW_TAG_lexical_block:
372 case dwarf::DW_TAG_structure_type:
373 case dwarf::DW_TAG_subprogram:
374 case dwarf::DW_TAG_subroutine_type:
375 case dwarf::DW_TAG_union_type:
381void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
384 for (DIEBlock *
I : DIEBlocks)
386 for (DIELoc *
I : DIELocs)
395 return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
396 DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
399std::pair<bool, std::optional<int64_t>>
400DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
401 const DWARFDie &DIE) {
402 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
403 DIE.getTag() == dwarf::DW_TAG_constant) &&
404 "Wrong type of input die");
406 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
409 DWARFUnit *U = DIE.getDwarfUnit();
410 std::optional<uint32_t> LocationIdx =
411 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
413 return std::make_pair(
false, std::nullopt);
417 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
420 std::optional<DWARFFormValue> LocationValue =
421 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
423 return std::make_pair(
false, std::nullopt);
428 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
430 return std::make_pair(
false, std::nullopt);
433 DataExtractor
Data(
toStringRef(*Expr), U->getContext().isLittleEndian(),
434 U->getAddressByteSize());
435 DWARFExpression Expression(
Data, U->getAddressByteSize(),
436 U->getFormParams().Format);
438 bool HasLocationAddress =
false;
440 for (DWARFExpression::iterator It = Expression.begin();
441 It != Expression.end(); ++It) {
442 DWARFExpression::iterator NextIt = It;
445 const DWARFExpression::Operation &
Op = *It;
447 case dwarf::DW_OP_const2u:
448 case dwarf::DW_OP_const4u:
449 case dwarf::DW_OP_const8u:
450 case dwarf::DW_OP_const2s:
451 case dwarf::DW_OP_const4s:
452 case dwarf::DW_OP_const8s:
456 case dwarf::DW_OP_addr: {
457 HasLocationAddress =
true;
459 if (std::optional<int64_t> RelocAdjustment =
460 RelocMgr.getExprOpAddressRelocAdjustment(
461 *U,
Op, AttrOffset + CurExprOffset,
463 return std::make_pair(HasLocationAddress, *RelocAdjustment);
465 case dwarf::DW_OP_constx:
466 case dwarf::DW_OP_addrx: {
467 HasLocationAddress =
true;
468 if (std::optional<uint64_t> AddressOffset =
469 DIE.getDwarfUnit()->getIndexedAddressOffset(
472 if (std::optional<int64_t> RelocAdjustment =
473 RelocMgr.getExprOpAddressRelocAdjustment(
474 *U,
Op, *AddressOffset,
475 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize()))
476 return std::make_pair(HasLocationAddress, *RelocAdjustment);
486 return std::make_pair(HasLocationAddress, std::nullopt);
491unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
493 CompileUnit::DIEInfo &MyInfo,
495 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
498 if (!(Flags & TF_InFunctionScope) &&
499 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
500 MyInfo.InDebugMap =
true;
501 return Flags | TF_Keep;
509 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
510 getVariableRelocAdjustment(RelocMgr, DIE);
512 if (LocExprAddrAndRelocAdjustment.first)
513 MyInfo.HasLocationExpressionAddr =
true;
515 if (!LocExprAddrAndRelocAdjustment.second)
518 MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second;
519 MyInfo.InDebugMap =
true;
521 if (((Flags & TF_InFunctionScope) &&
525 if (Options.Verbose) {
526 outs() <<
"Keeping variable DIE:";
527 DIDumpOptions DumpOpts;
528 DumpOpts.ChildRecurseDepth = 0;
529 DumpOpts.Verbose = Options.Verbose;
530 DIE.dump(
outs(), 8 , DumpOpts);
533 return Flags | TF_Keep;
538unsigned DWARFLinker::shouldKeepSubprogramDIE(
539 AddressesMap &RelocMgr,
const DWARFDie &DIE,
const DWARFFile &File,
540 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
541 Flags |= TF_InFunctionScope;
547 assert(LowPc &&
"low_pc attribute is not an address.");
548 std::optional<int64_t> RelocAdjustment =
549 RelocMgr.getSubprogramRelocAdjustment(DIE);
550 if (!RelocAdjustment)
553 MyInfo.AddrAdjust = *RelocAdjustment;
554 MyInfo.InDebugMap =
true;
556 if (Options.Verbose) {
557 outs() <<
"Keeping subprogram DIE:";
558 DIDumpOptions DumpOpts;
559 DumpOpts.ChildRecurseDepth = 0;
560 DumpOpts.Verbose = Options.Verbose;
561 DIE.dump(
outs(), 8 , DumpOpts);
564 if (DIE.getTag() == dwarf::DW_TAG_label) {
565 if (Unit.hasLabelAt(*LowPc))
568 DWARFUnit &OrigUnit = Unit.getOrigUnit();
576 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
577 return Flags | TF_Keep;
582 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
584 reportWarning(
"Function without high_pc. Range will be discarded.\n", File,
588 if (*LowPc > *HighPc) {
589 reportWarning(
"low_pc greater than high_pc. Range will be discarded.\n",
595 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
601unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr,
const DWARFDie &DIE,
602 const DWARFFile &File, CompileUnit &Unit,
603 CompileUnit::DIEInfo &MyInfo,
605 switch (DIE.getTag()) {
606 case dwarf::DW_TAG_constant:
607 case dwarf::DW_TAG_variable:
608 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
609 case dwarf::DW_TAG_subprogram:
610 case dwarf::DW_TAG_label:
611 return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags);
612 case dwarf::DW_TAG_base_type:
615 case dwarf::DW_TAG_imported_module:
616 case dwarf::DW_TAG_imported_declaration:
617 case dwarf::DW_TAG_imported_unit:
619 return Flags | TF_Keep;
633 case dwarf::DW_TAG_structure_type:
634 case dwarf::DW_TAG_class_type:
635 case dwarf::DW_TAG_union_type:
653 case dwarf::DW_TAG_typedef:
654 case dwarf::DW_TAG_member:
655 case dwarf::DW_TAG_reference_type:
656 case dwarf::DW_TAG_ptr_to_member_type:
657 case dwarf::DW_TAG_pointer_type:
674void DWARFLinker::lookForChildDIEsToKeep(
675 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
676 SmallVectorImpl<WorklistItem> &Worklist) {
683 Flags &= ~DWARFLinker::TF_ParentWalk;
687 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
692 for (
auto Child :
reverse(Die.children())) {
695 CompileUnit::DIEInfo &ChildInfo =
CU.getInfo(Child);
696 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateChildIncompleteness,
698 Worklist.emplace_back(Child,
CU, Flags);
705 if (!
Info.Ctxt || (Die.
getTag() == dwarf::DW_TAG_namespace))
708 if (!
CU.hasODR() && !
Info.InModuleScope)
711 return !
Info.Incomplete &&
Info.Ctxt !=
CU.getInfo(
Info.ParentIdx).Ctxt;
714void DWARFLinker::markODRCanonicalDie(
const DWARFDie &Die, CompileUnit &
CU) {
715 CompileUnit::DIEInfo &
Info =
CU.getInfo(Die);
717 Info.ODRMarkingDone =
true;
719 !
Info.Ctxt->hasCanonicalDIE())
720 Info.Ctxt->setHasCanonicalDIE();
725void DWARFLinker::lookForRefDIEsToKeep(
726 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
727 const UnitListTy &Units,
const DWARFFile &File,
728 SmallVectorImpl<WorklistItem> &Worklist) {
729 bool UseOdr = (
Flags & DWARFLinker::TF_DependencyWalk)
730 ? (Flags & DWARFLinker::TF_ODR)
732 DWARFUnit &Unit =
CU.getOrigUnit();
733 DWARFDataExtractor
Data = Unit.getDebugInfoExtractor();
734 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
737 SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs;
738 for (
const auto &AttrSpec : Abbrev->attributes()) {
739 DWARFFormValue Val(AttrSpec.Form);
741 AttrSpec.Attr == dwarf::DW_AT_sibling) {
743 Unit.getFormParams());
747 Val.extractValue(
Data, &
Offset, Unit.getFormParams(), &Unit);
748 CompileUnit *ReferencedCU;
750 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
751 CompileUnit::DIEInfo &
Info = ReferencedCU->getInfo(RefDie);
762 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
764 Info.Ctxt->hasCanonicalDIE())
769 Info.Ctxt->hasCanonicalDIE()))
771 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
775 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
779 for (
auto &
P :
reverse(ReferencedDIEs)) {
782 CompileUnit::DIEInfo &
Info =
P.second.getInfo(
P.first);
783 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateRefIncompleteness,
785 Worklist.emplace_back(
P.first,
P.second,
786 DWARFLinker::TF_Keep |
787 DWARFLinker::TF_DependencyWalk | ODRFlag);
792void DWARFLinker::lookForParentDIEsToKeep(
793 unsigned AncestorIdx, CompileUnit &
CU,
unsigned Flags,
794 SmallVectorImpl<WorklistItem> &Worklist) {
796 if (
CU.getInfo(AncestorIdx).Keep)
799 DWARFUnit &Unit =
CU.getOrigUnit();
800 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);
801 Worklist.emplace_back(
CU.getInfo(AncestorIdx).ParentIdx,
CU, Flags);
802 Worklist.emplace_back(ParentDIE,
CU, Flags);
830void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
832 const DWARFDie &Die,
const DWARFFile &File,
833 CompileUnit &Cu,
unsigned Flags) {
835 SmallVector<WorklistItem, 4> Worklist;
836 Worklist.emplace_back(Die, Cu, Flags);
838 while (!Worklist.empty()) {
839 WorklistItem Current = Worklist.pop_back_val();
842 switch (Current.Type) {
843 case WorklistItemType::UpdateChildIncompleteness:
846 case WorklistItemType::UpdateRefIncompleteness:
849 case WorklistItemType::LookForChildDIEsToKeep:
850 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
852 case WorklistItemType::LookForRefDIEsToKeep:
853 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
856 case WorklistItemType::LookForParentDIEsToKeep:
857 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
860 case WorklistItemType::MarkODRCanonicalDie:
861 markODRCanonicalDie(Current.Die, Current.CU);
863 case WorklistItemType::LookForDIEsToKeep:
867 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
868 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(
Idx);
873 if (Current.Flags & TF_DependencyWalk)
874 MyInfo.Prune =
false;
881 bool AlreadyKept = MyInfo.Keep;
882 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
885 if (!(Current.Flags & TF_DependencyWalk))
886 Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU,
887 MyInfo, Current.Flags);
892 if (!(Current.Flags & TF_DependencyWalk) ||
893 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
894 if (Current.CU.hasODR() || MyInfo.InModuleScope)
895 Worklist.emplace_back(Current.Die, Current.CU,
896 WorklistItemType::MarkODRCanonicalDie);
902 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
903 WorklistItemType::LookForChildDIEsToKeep);
905 if (AlreadyKept || !(Current.Flags & TF_Keep))
914 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
915 Current.Die.getTag() != dwarf::DW_TAG_member &&
921 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
922 WorklistItemType::LookForRefDIEsToKeep);
924 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
925 : Current.CU.hasODR();
926 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
927 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
930 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
946 std::vector<DWARFDie> Worklist;
947 Worklist.push_back(
CU.getOrigUnit().getUnitDIE());
950 std::vector<BrokenLink> BrokenLinks;
952 while (!Worklist.empty()) {
953 const DWARFDie Current = Worklist.back();
956 const bool CurrentDieIsKept =
CU.getInfo(Current).Keep;
959 Worklist.push_back(Child);
961 const bool ChildDieIsKept =
CU.getInfo(Child).Keep;
962 if (!CurrentDieIsKept && ChildDieIsKept)
963 BrokenLinks.emplace_back(Current, Child);
967 if (!BrokenLinks.empty()) {
970 "Found invalid link in keep chain between {0:x} and {1:x}\n",
971 Link.Parent.getOffset(), Link.Child.getOffset());
974 Link.Parent.dump(
errs(), 0, {});
975 CU.getInfo(Link.Parent).dump();
978 Link.Child.dump(
errs(), 2, {});
979 CU.getInfo(Link.Child).dump();
992void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
997 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(
ID, InsertToken);
1002 Abbrev.setNumber(InSet->getNumber());
1005 Abbreviations.push_back(
1006 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
1007 for (
const auto &Attr : Abbrev.getData())
1008 Abbreviations.back()->AddAttribute(Attr);
1009 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
1011 Abbrev.setNumber(Abbreviations.size());
1012 Abbreviations.back()->setNumber(Abbreviations.size());
1016unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
1017 AttributeSpec AttrSpec,
1018 const DWARFFormValue &Val,
1020 AttributesInfo &
Info) {
1025 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
1030 if (AttrSpec.Attr == dwarf::DW_AT_name)
1032 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
1033 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
1035 if (
U.getVersion() >= 5) {
1037 auto StringOffsetIndex =
1038 StringOffsetPool.getValueIndex(
StringEntry.getOffset());
1041 dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
1042 ->sizeOf(
U.getFormParams());
1045 AttrSpec.Form = dwarf::DW_FORM_strp;
1052unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
1053 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1054 unsigned AttrSize,
const DWARFFormValue &Val,
const DWARFFile &File,
1055 CompileUnit &Unit) {
1056 const DWARFUnit &
U = Unit.getOrigUnit();
1059 DIE *NewRefDie =
nullptr;
1060 CompileUnit *RefUnit =
nullptr;
1063 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
1066 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
1069 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
1074 RefInfo.Ctxt->getCanonicalDIEOffset()) {
1075 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
1076 "Offset to canonical die is set, but context is not marked");
1077 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
1079 dwarf::DW_FORM_ref_addr, Attr);
1080 return U.getRefAddrByteSize();
1083 if (!RefInfo.Clone) {
1086 RefInfo.UnclonedReference =
true;
1089 NewRefDie = RefInfo.Clone;
1091 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1099 if (
Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1102 RefUnit->getStartOffset() + NewRefDie->getOffset();
1103 Attr = NewRefOffset;
1105 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));
1109 Unit.noteForwardReference(
1110 NewRefDie, RefUnit, RefInfo.Ctxt,
1112 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
1114 return U.getRefAddrByteSize();
1118 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1123void DWARFLinker::DIECloner::cloneExpression(
1124 DataExtractor &
Data, DWARFExpression Expression,
const DWARFFile &File,
1125 CompileUnit &Unit, SmallVectorImpl<uint8_t> &
OutputBuffer,
1126 int64_t AddrRelocAdjustment,
bool IsLittleEndian) {
1129 uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize();
1132 for (
auto &
Op : Expression) {
1138 Desc.
Op[0] != Encoding::Size1))
1139 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
1143 Desc.
Op[0] == Encoding::Size1)) {
1163 if (RefOffset > 0 ||
Op.
getCode() != dwarf::DW_OP_convert) {
1164 RefOffset += Unit.getOrigUnit().getOffset();
1165 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
1166 CompileUnit::DIEInfo &
Info = Unit.getInfo(RefDie);
1167 if (DIE *Clone =
Info.Clone)
1168 Offset = Clone->getOffset();
1170 Linker.reportWarning(
1171 "base type ref doesn't point to DW_TAG_base_type.", File);
1175 if (RealSize > ULEBsize) {
1178 Linker.reportWarning(
"base type ref doesn't fit.", File);
1180 assert(RealSize == ULEBsize &&
"padding failed");
1181 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1182 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1183 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_addrx) {
1184 if (std::optional<object::SectionedAddress> SA =
1185 Unit.getOrigUnit().getAddrOffsetSectionItem(
1192 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1195 ArrayRef<uint8_t> AddressBytes(
1196 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1197 OrigAddressByteSize);
1198 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1200 Linker.reportWarning(
"cannot read DW_OP_addrx operand.", File);
1201 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_constx) {
1202 if (std::optional<object::SectionedAddress> SA =
1203 Unit.getOrigUnit().getAddrOffsetSectionItem(
1209 std::optional<uint8_t> OutOperandKind;
1210 switch (OrigAddressByteSize) {
1212 OutOperandKind = dwarf::DW_OP_const4u;
1215 OutOperandKind = dwarf::DW_OP_const8u;
1218 Linker.reportWarning(
1219 formatv((
"unsupported address size: {0}."), OrigAddressByteSize),
1224 if (OutOperandKind) {
1226 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1229 ArrayRef<uint8_t> AddressBytes(
1230 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1231 OrigAddressByteSize);
1232 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1235 Linker.reportWarning(
"cannot read DW_OP_constx operand.", File);
1245unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1246 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1247 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1248 bool IsLittleEndian) {
1251 DIELoc *Loc =
nullptr;
1252 DIEBlock *
Block =
nullptr;
1253 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1254 Loc =
new (DIEAlloc) DIELoc;
1255 Linker.DIELocs.push_back(Loc);
1257 Block =
new (DIEAlloc) DIEBlock;
1258 Linker.DIEBlocks.push_back(
Block);
1260 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1261 :
static_cast<DIEValueList *
>(
Block);
1263 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1266 SmallVector<uint8_t, 32> Buffer;
1267 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1271 DataExtractor
Data(StringRef((
const char *)Bytes.data(), Bytes.size()),
1272 IsLittleEndian, OrigUnit.getAddressByteSize());
1273 DWARFExpression Expr(
Data, OrigUnit.getAddressByteSize(),
1274 OrigUnit.getFormParams().Format);
1275 cloneExpression(
Data, Expr, File, Unit, Buffer,
1276 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);
1279 for (
auto Byte : Bytes)
1281 dwarf::DW_FORM_data1, DIEInteger(Byte));
1287 Loc->setSize(Bytes.size());
1289 Block->setSize(Bytes.size());
1297 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&
1298 (Bytes.size() > UINT8_MAX)) ||
1299 (AttrSpec.Form == dwarf::DW_FORM_block2 &&
1300 (Bytes.size() > UINT16_MAX)) ||
1301 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))
1302 AttrSpec.Form = dwarf::DW_FORM_block;
1308 return Die.addValue(DIEAlloc, Value)->sizeOf(OrigUnit.getFormParams());
1311unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1312 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1313 unsigned AttrSize,
const DWARFFormValue &Val,
const CompileUnit &Unit,
1314 AttributesInfo &
Info) {
1315 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1316 Info.HasLowPc =
true;
1320 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1336 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1340 std::optional<uint64_t>
Addr = AddrAttribute->getAsAddress();
1342 Linker.reportWarning(
"Cann't read address attribute value.", ObjFile);
1346 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1347 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1348 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
1352 }
else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1353 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1354 if (
uint64_t HighPc = Unit.getHighPc())
1362 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
1364 AttrSpec.Form, DIEInteger(*
Addr));
1365 return Unit.getOrigUnit().getAddressByteSize();
1368 auto AddrIndex = AddrPool.getValueIndex(*
Addr);
1372 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))
1373 ->sizeOf(Unit.getOrigUnit().getFormParams());
1376unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1377 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1378 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1379 unsigned AttrSize, AttributesInfo &
Info) {
1384 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1385 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1386 const DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacinfo();
1392 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1393 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1394 const DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacro();
1400 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1404 Info.AttrStrOffsetBaseSeen =
true;
1406 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1407 dwarf::DW_FORM_sec_offset, DIEInteger(8))
1408 ->sizeOf(Unit.getOrigUnit().getFormParams());
1412 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1413 Value = *OptionalValue;
1414 else if (
auto OptionalValue = Val.getAsSignedConstant())
1415 Value = *OptionalValue;
1416 else if (
auto OptionalValue = Val.getAsSectionOffset())
1417 Value = *OptionalValue;
1419 Linker.reportWarning(
1420 "Unsupported scalar attribute form. Dropping attribute.", File,
1424 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1425 Info.IsDeclaration =
true;
1427 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1436 [[maybe_unused]]
dwarf::Form OriginalForm = AttrSpec.Form;
1437 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1441 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1443 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1447 std::optional<uint64_t>
Offset =
1448 Unit.getOrigUnit().getRnglistOffset(*
Index);
1450 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1456 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1457 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1458 }
else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1462 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1464 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1468 std::optional<uint64_t>
Offset =
1469 Unit.getOrigUnit().getLoclistOffset(*
Index);
1471 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1477 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1478 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1479 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1480 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1481 std::optional<uint64_t> LowPC = Unit.getLowPc();
1485 Value = Unit.getHighPc() - *LowPC;
1486 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1487 Value = *Val.getAsSectionOffset();
1488 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1489 Value = *Val.getAsSignedConstant();
1490 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1491 Value = *OptionalValue;
1493 Linker.reportWarning(
1494 "Unsupported scalar attribute form. Dropping attribute.", File,
1499 DIE::value_iterator Patch =
1502 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1503 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1504 Unit.noteRangeAttribute(Die, Patch);
1505 Info.HasRanges =
true;
1509 Unit.getOrigUnit().getVersion())) {
1511 CompileUnit::DIEInfo &LocationDieInfo = Unit.getInfo(InputDIE);
1512 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
1513 ? LocationDieInfo.AddrAdjust
1515 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1516 Info.IsDeclaration =
true;
1519 assert((
Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1520 "Unhandled DW_FORM_rnglistx attribute");
1528unsigned DWARFLinker::DIECloner::cloneAttribute(
1529 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1530 CompileUnit &Unit,
const DWARFFormValue &Val,
const AttributeSpec AttrSpec,
1531 unsigned AttrSize, AttributesInfo &
Info,
bool IsLittleEndian) {
1532 const DWARFUnit &
U = Unit.getOrigUnit();
1534 switch (AttrSpec.Form) {
1535 case dwarf::DW_FORM_strp:
1536 case dwarf::DW_FORM_line_strp:
1537 case dwarf::DW_FORM_string:
1538 case dwarf::DW_FORM_strx:
1539 case dwarf::DW_FORM_strx1:
1540 case dwarf::DW_FORM_strx2:
1541 case dwarf::DW_FORM_strx3:
1542 case dwarf::DW_FORM_strx4:
1543 return cloneStringAttribute(Die, AttrSpec, Val, U,
Info);
1544 case dwarf::DW_FORM_ref_addr:
1545 case dwarf::DW_FORM_ref1:
1546 case dwarf::DW_FORM_ref2:
1547 case dwarf::DW_FORM_ref4:
1548 case dwarf::DW_FORM_ref8:
1549 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1551 case dwarf::DW_FORM_block:
1552 case dwarf::DW_FORM_block1:
1553 case dwarf::DW_FORM_block2:
1554 case dwarf::DW_FORM_block4:
1555 case dwarf::DW_FORM_exprloc:
1556 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1558 case dwarf::DW_FORM_addr:
1559 case dwarf::DW_FORM_addrx:
1560 case dwarf::DW_FORM_addrx1:
1561 case dwarf::DW_FORM_addrx2:
1562 case dwarf::DW_FORM_addrx3:
1563 case dwarf::DW_FORM_addrx4:
1564 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1566 case dwarf::DW_FORM_data1:
1567 case dwarf::DW_FORM_data2:
1568 case dwarf::DW_FORM_data4:
1569 case dwarf::DW_FORM_data8:
1570 case dwarf::DW_FORM_udata:
1571 case dwarf::DW_FORM_sdata:
1572 case dwarf::DW_FORM_sec_offset:
1573 case dwarf::DW_FORM_flag:
1574 case dwarf::DW_FORM_flag_present:
1575 case dwarf::DW_FORM_rnglistx:
1576 case dwarf::DW_FORM_loclistx:
1577 case dwarf::DW_FORM_implicit_const:
1578 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1581 Linker.reportWarning(
"Unsupported attribute form " +
1583 " in cloneAttribute. Dropping.",
1590void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1592 DwarfStringPoolEntryRef
Name,
1594 bool SkipPubSection) {
1595 std::optional<ObjCSelectorNames> Names =
1599 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),
1601 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),
1603 if (Names->ClassNameNoCategory)
1604 Unit.addObjCAccelerator(
1605 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);
1606 if (Names->MethodNameNoCategory)
1607 Unit.addNameAccelerator(
1608 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);
1615 switch (AttrSpec.
Attr) {
1618 case dwarf::DW_AT_low_pc:
1619 case dwarf::DW_AT_high_pc:
1620 case dwarf::DW_AT_ranges:
1621 return !Update && SkipPC;
1622 case dwarf::DW_AT_rnglists_base:
1628 case dwarf::DW_AT_loclists_base:
1634 case dwarf::DW_AT_location:
1635 case dwarf::DW_AT_frame_base:
1636 return !Update && SkipPC;
1640DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1641 const DWARFFile &File, CompileUnit &Unit,
1642 int64_t PCOffset,
uint32_t OutOffset,
1643 unsigned Flags,
bool IsLittleEndian,
1645 DWARFUnit &U = Unit.getOrigUnit();
1646 unsigned Idx = U.getDIEIndex(InputDIE);
1647 CompileUnit::DIEInfo &
Info = Unit.getInfo(
Idx);
1650 if (!Unit.getInfo(
Idx).Keep)
1654 assert(!(Die &&
Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1663 assert(Die->getTag() == InputDIE.getTag());
1664 Die->setOffset(OutOffset);
1666 (
Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1667 if (!
Info.Ctxt->hasCanonicalDIE())
1668 Info.Ctxt->setHasCanonicalDIE();
1672 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1676 DWARFDataExtractor
Data =
U.getDebugInfoExtractor();
1681 ?
U.getDIEAtIndex(
Idx + 1).getOffset()
1682 :
U.getNextUnitOffset();
1683 AttributesInfo AttrInfo;
1688 SmallString<40> DIECopy(
Data.getData().substr(
Offset, NextOffset -
Offset));
1690 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1693 ObjFile.Addresses->applyValidRelocs(DIECopy,
Offset,
Data.isLittleEndian());
1699 const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr();
1703 if (Die->getTag() == dwarf::DW_TAG_subprogram)
1704 PCOffset =
Info.AddrAdjust;
1705 AttrInfo.PCOffset = PCOffset;
1707 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1708 Flags |= TF_InFunctionScope;
1711 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1714 if ((Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1715 Flags &= ~TF_SkipPC;
1718 else if (!
Info.InDebugMap &&
Info.HasLocationExpressionAddr &&
1723 for (
const auto &AttrSpec : Abbrev->attributes()) {
1730 DWARFFormValue Val = AttrSpec.getFormValue();
1732 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1733 AttrSize =
Offset - AttrSize;
1735 OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec,
1736 AttrSize, AttrInfo, IsLittleEndian);
1744 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1745 Tag != dwarf::DW_TAG_compile_unit &&
1746 getDIENames(InputDIE, AttrInfo, DebugStrPool,
1747 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1748 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1749 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1750 Tag == dwarf::DW_TAG_inlined_subroutine);
1751 if (AttrInfo.Name) {
1752 if (AttrInfo.NameWithoutTemplate)
1753 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1755 Unit.addNameAccelerator(Die, AttrInfo.Name,
1756 Tag == dwarf::DW_TAG_inlined_subroutine);
1759 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,
1762 }
else if (
Tag == dwarf::DW_TAG_namespace) {
1764 AttrInfo.Name = DebugStrPool.getEntry(
"(anonymous namespace)");
1765 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1766 }
else if (
Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1767 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1768 }
else if (
isTypeTag(
Tag) && !AttrInfo.IsDeclaration &&
1769 getDIENames(InputDIE, AttrInfo, DebugStrPool) && AttrInfo.Name &&
1770 AttrInfo.Name.getString()[0]) {
1771 uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit, File);
1775 bool ObjCClassIsImplementation =
1776 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1777 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1780 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1785 bool HasChildren =
false;
1786 for (
auto Child : InputDIE.children()) {
1787 unsigned Idx =
U.getDIEIndex(Child);
1788 if (Unit.getInfo(
Idx).Keep) {
1794 if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
1795 Die->getTag() == dwarf::DW_TAG_compile_unit) {
1797 Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1798 dwarf::DW_FORM_sec_offset, DIEInteger(8));
1802 DIEAbbrev NewAbbrev = Die->generateAbbrev();
1806 Linker.assignAbbrev(NewAbbrev);
1807 Die->setAbbrevNumber(NewAbbrev.getNumber());
1814 Die->setSize(OutOffset - Die->getOffset());
1819 for (
auto Child : InputDIE.children()) {
1820 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
1822 Die->addChild(Clone);
1823 OutOffset = Clone->getOffset() + Clone->getSize();
1828 OutOffset +=
sizeof(int8_t);
1830 Die->setSize(OutOffset - Die->getOffset());
1837void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File,
1838 DebugDieValuePool &AddrPool)
const {
1842 const auto &FunctionRanges = Unit.getFunctionRanges();
1845 AddressRanges LinkedFunctionRanges;
1846 for (
const AddressRangeValuePair &Range : FunctionRanges)
1847 LinkedFunctionRanges.insert(
1851 if (!LinkedFunctionRanges.empty())
1852 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
1855 std::optional<PatchLocation> UnitRngListAttribute =
1856 Unit.getUnitRangesAttribute();
1858 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
1859 std::optional<AddressRangeValuePair> CachedRange;
1860 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
1864 for (PatchLocation &AttributePatch : AllRngListAttributes) {
1867 AddressRanges LinkedRanges;
1868 if (Expected<DWARFAddressRangesVector> OriginalRanges =
1869 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
1871 for (
const auto &Range : *OriginalRanges) {
1872 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
1873 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
1877 reportWarning(
"inconsistent range data.", File);
1882 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
1883 Range.HighPC + CachedRange->Value});
1887 reportWarning(
"invalid range list ignored.", File);
1891 TheDwarfEmitter->emitDwarfDebugRangeListFragment(
1892 Unit, LinkedRanges, AttributePatch, AddrPool);
1896 if (UnitRngListAttribute.has_value())
1897 TheDwarfEmitter->emitDwarfDebugRangeListFragment(
1898 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);
1901 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
1905void DWARFLinker::DIECloner::generateUnitLocations(
1906 CompileUnit &Unit,
const DWARFFile &File,
1907 ExpressionHandlerRef ExprHandler) {
1912 Unit.getLocationAttributes();
1914 if (AllLocListAttributes.empty())
1920 for (
auto &CurLocAttr : AllLocListAttributes) {
1923 Expected<DWARFLocationExpressionsVector> OriginalLocations =
1924 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
1926 if (!OriginalLocations) {
1928 Linker.reportWarning(
"Invalid location attribute ignored.", File);
1933 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
1934 DWARFLocationExpression LinkedExpression;
1936 if (CurExpression.Range) {
1938 LinkedExpression.Range = {
1939 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
1940 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
1944 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
1945 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
1946 CurLocAttr.RelocAdjustment);
1948 LinkedLocationExpressions.push_back(LinkedExpression);
1952 Emitter->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions,
1953 CurLocAttr, AddrPool);
1957 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
1961 for (
auto &V : Die.
values())
1962 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
1970void DWARFLinker::DIECloner::emitDebugAddrSection(
1972 const uint16_t DwarfVersion)
const {
1977 if (DwarfVersion < 5)
1980 if (AddrPool.DieValues.empty())
1983 MCSymbol *EndLabel =
Emitter->emitDwarfDebugAddrsHeader(Unit);
1985 DIEInteger(
Emitter->getDebugAddrSectionSize()));
1986 Emitter->emitDwarfDebugAddrs(AddrPool.DieValues,
1987 Unit.getOrigUnit().getAddressByteSize());
1988 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
1994 std::vector<DWARFDebugLine::Row> &Rows) {
1998 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
2012 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
2013 InsertPoint->EndSequence) {
2014 *InsertPoint = Seq.front();
2015 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
2017 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
2024 for (
auto &V : Die.
values())
2025 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2033void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2034 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2035 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2037 if (std::optional<uint64_t> MacroAttr =
2039 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2043 if (std::optional<uint64_t> MacroAttr =
2045 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2050void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2055 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
2061 if (
auto *OutputDIE = Unit.getOutputUnitDIE())
2064 if (
const DWARFDebugLine::LineTable *LT =
2065 ObjFile.Dwarf->getLineTableForUnit(&Unit.getOrigUnit())) {
2067 DWARFDebugLine::LineTable LineTable;
2070 LineTable.Prologue =
LT->Prologue;
2073 if (Linker.Options.Update) {
2074 LineTable.Rows =
LT->Rows;
2077 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2078 LineTable.Rows.clear();
2080 LineTable.Sequences =
LT->Sequences;
2083 std::vector<DWARFDebugLine::Row> NewRows;
2084 NewRows.reserve(
LT->Rows.size());
2088 std::vector<DWARFDebugLine::Row> Seq;
2090 const auto &FunctionRanges = Unit.getFunctionRanges();
2091 std::optional<AddressRangeValuePair> CurrRange;
2104 for (DWARFDebugLine::Row Row :
LT->Rows) {
2110 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {
2114 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2115 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
2116 if (StopAddress != -1ULL && !Seq.empty()) {
2119 auto NextLine = Seq.back();
2120 NextLine.Address.Address = StopAddress;
2121 NextLine.EndSequence = 1;
2122 NextLine.PrologueEnd = 0;
2123 NextLine.BasicBlock = 0;
2124 NextLine.EpilogueBegin = 0;
2125 Seq.push_back(NextLine);
2134 if (Row.EndSequence && Seq.empty())
2138 Row.Address.Address += CurrRange->Value;
2139 Seq.emplace_back(Row);
2141 if (Row.EndSequence)
2145 LineTable.Rows = std::move(NewRows);
2148 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2151 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2154void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2159 for (
const auto &Namespace : Unit.getNamespaces())
2160 AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() +
2161 Unit.getStartOffset());
2163 for (
const auto &Pubname : Unit.getPubnames())
2164 AppleNames.addName(Pubname.Name,
2165 Pubname.Die->getOffset() + Unit.getStartOffset());
2167 for (
const auto &Pubtype : Unit.getPubtypes())
2169 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
2170 Pubtype.Die->getTag(),
2173 Pubtype.QualifiedNameHash);
2175 for (
const auto &ObjC : Unit.getObjC())
2176 AppleObjc.addName(
ObjC.Name,
2177 ObjC.Die->getOffset() + Unit.getStartOffset());
2180 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2181 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2184 for (
const auto &Namespace : Unit.getNamespaces())
2185 DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
2186 Namespace.Die->getTag(), Unit.getUniqueID());
2187 for (
const auto &Pubname : Unit.getPubnames())
2188 DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(),
2189 Pubname.Die->getTag(), Unit.getUniqueID());
2190 for (
const auto &Pubtype : Unit.getPubtypes())
2191 DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(),
2192 Pubtype.Die->getTag(), Unit.getUniqueID());
2204void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) {
2205 DWARFContext &OrigDwarf = *
Context.File.Dwarf;
2206 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2208 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2213 for (std::unique_ptr<CompileUnit> &Unit :
Context.CompileUnits) {
2214 for (
auto CurRange : Unit->getFunctionRanges())
2215 AllUnitsRanges.
insert(CurRange.Range, CurRange.Value);
2218 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian(), 0);
2223 DenseMap<uint64_t, StringRef> LocalCIES;
2225 while (
Data.isValidOffset(InputOffset)) {
2226 uint64_t EntryOffset = InputOffset;
2228 if (InitialLength == 0xFFFFFFFF)
2229 return reportWarning(
"Dwarf64 bits no supported",
Context.File);
2232 if (CIEId == 0xFFFFFFFF) {
2234 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2235 LocalCIES[EntryOffset] = CIEData;
2237 InputOffset += InitialLength - 4;
2241 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2247 std::optional<AddressRangeValuePair>
Range =
2248 AllUnitsRanges.getRangeThatContains(Loc);
2251 InputOffset = EntryOffset + InitialLength + 4;
2257 StringRef CIEData = LocalCIES[CIEId];
2258 if (CIEData.empty())
2259 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2264 auto IteratorInserted = EmittedCIEs.
insert(
2265 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2267 if (IteratorInserted.second) {
2268 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2269 IteratorInserted.first->getValue() = LastCIEOffset;
2270 TheDwarfEmitter->emitCIE(CIEData);
2276 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2277 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2279 FrameData.substr(InputOffset, FDERemainingBytes));
2280 InputOffset += FDERemainingBytes;
2284uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2286 const DWARFFile &File,
2287 int ChildRecurseDepth) {
2288 const char *
Name =
nullptr;
2289 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2290 CompileUnit *
CU = &
U;
2291 std::optional<DWARFFormValue>
Ref;
2297 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2298 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2306 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2308 OrigUnit = &RefCU->getOrigUnit();
2313 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2314 if (!
Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2315 Name =
"(anonymous namespace)";
2317 if (
CU->getInfo(
Idx).ParentIdx == 0 ||
2319 CU->getOrigUnit().getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx).getTag() ==
2320 dwarf::DW_TAG_module)
2323 DWARFDie Die = OrigUnit->getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx);
2327 hashFullyQualifiedName(Die, *
CU, File, ++ChildRecurseDepth)));
2332 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2340 if (ObjectPrefixMap.empty())
2344 for (
const auto &Entry : ObjectPrefixMap)
2347 return p.str().str();
2353 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2355 if (PCMFile.empty())
2358 if (ObjectPrefixMap)
2359 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2364std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2365 std::string &PCMFile,
2366 LinkContext &Context,
2369 if (PCMFile.empty())
2370 return std::make_pair(
false,
false);
2378 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2380 return std::make_pair(
true,
true);
2383 if (!
Quiet && Options.Verbose) {
2385 outs() <<
"Found clang module reference " << PCMFile;
2388 auto Cached = ClangModules.
find(PCMFile);
2389 if (Cached != ClangModules.
end()) {
2393 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2394 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2395 "different version of the module ") +
2398 if (!
Quiet && Options.Verbose)
2399 outs() <<
" [cached].\n";
2400 return std::make_pair(
true,
true);
2403 return std::make_pair(
true,
false);
2406bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2407 LinkContext &Context,
2408 objFileLoader Loader,
2411 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2412 std::pair<bool, bool> IsClangModuleRef =
2413 isClangModuleRef(CUDie, PCMFile, Context, Indent,
false);
2415 if (!IsClangModuleRef.first)
2418 if (IsClangModuleRef.second)
2421 if (Options.Verbose)
2428 if (Error
E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded,
2436Error DWARFLinker::loadClangModule(objFileLoader Loader,
const DWARFDie &CUDie,
2437 const std::string &PCMFile,
2438 LinkContext &Context,
2446 SmallString<0>
Path(Options.PrependPath);
2453 if (Loader ==
nullptr) {
2454 reportError(
"Could not load clang module: loader is not specified.\n",
2459 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2463 std::unique_ptr<CompileUnit> Unit;
2464 for (
const auto &
CU : ErrOrObj->Dwarf->compile_units()) {
2467 auto ChildCUDie =
CU->getUnitDIE();
2470 if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded,
2475 ": Clang modules are expected to have exactly 1 compile unit.\n");
2476 reportError(Err,
Context.File);
2483 if (PCMDwoId != DwoId) {
2484 if (Options.Verbose)
2486 Twine(
"hash mismatch: this object file was built against a "
2487 "different version of the module ") +
2491 ClangModules[PCMFile] = PCMDwoId;
2495 Unit = std::make_unique<CompileUnit>(*
CU, UniqueUnitID++, !Options.NoODR,
2501 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2506uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2507 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2510 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2512 for (
auto &CurrentUnit : CompileUnits) {
2513 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2514 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2515 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2516 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2518 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2521 if (CurrentUnit->getInfo(0).Keep) {
2524 CurrentUnit->createOutputDIE();
2525 rememberUnitForMacroOffset(*CurrentUnit);
2526 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2527 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2530 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2534 generateLineTableForUnit(*CurrentUnit);
2536 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2541 Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);
2543 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2544 SmallVectorImpl<uint8_t> &OutBytes,
2545 int64_t RelocAdjustment) {
2546 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2547 DataExtractor
Data(SrcBytes, IsLittleEndian,
2548 OrigUnit.getAddressByteSize());
2549 cloneExpression(
Data,
2550 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2551 OrigUnit.getFormParams().Format),
2552 File, *CurrentUnit, OutBytes, RelocAdjustment,
2555 generateUnitLocations(*CurrentUnit, File, ProcessExpr);
2556 emitDebugAddrSection(*CurrentUnit, DwarfVersion);
2564 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2567 for (
auto &CurrentUnit : CompileUnits) {
2568 CurrentUnit->fixupForwardReferences();
2570 if (!CurrentUnit->getOutputUnitDIE())
2573 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2576 CurrentUnit->getStartOffset());
2577 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2578 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2580 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2584 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2587bool DWARFLinker::emitPaperTrailWarnings(
const DWARFFile &File,
2590 if (
File.Warnings.empty())
2593 DIE *CUDie =
DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit);
2594 CUDie->setOffset(11);
2596 StringRef WarningHeader;
2598 switch (DwarfLinkerClientID) {
2600 Producer = StringPool.internString(
"dsymutil");
2601 WarningHeader =
"dsymutil_warning";
2605 Producer = StringPool.internString(
"dwarfopt");
2606 WarningHeader =
"dwarfopt_warning";
2610 StringRef FileName = StringPool.internString(
File.FileName);
2611 CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp,
2612 DIEInteger(StringPool.getStringOffset(Producer)));
2613 DIEBlock *
String =
new (DIEAlloc) DIEBlock();
2614 DIEBlocks.push_back(
String);
2615 for (
auto &
C : FileName)
2621 CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string,
String);
2623 DIE &ConstDie = CUDie->addChild(
DIE::get(DIEAlloc, dwarf::DW_TAG_constant));
2624 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp,
2625 DIEInteger(StringPool.getStringOffset(WarningHeader)));
2626 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag,
2628 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp,
2629 DIEInteger(StringPool.getStringOffset(
Warning)));
2631 unsigned Size = 4 + FileName.size() + 1 +
2632 File.Warnings.size() * (4 + 1 + 4) + 1 ;
2633 DIEAbbrev Abbrev = CUDie->generateAbbrev();
2634 assignAbbrev(Abbrev);
2635 CUDie->setAbbrevNumber(Abbrev.getNumber());
2638 for (
auto &Child : CUDie->children()) {
2639 Abbrev = Child.generateAbbrev();
2640 assignAbbrev(Abbrev);
2641 Child.setAbbrevNumber(Abbrev.getNumber());
2644 CUDie->setSize(
Size);
2645 TheDwarfEmitter->emitPaperTrailWarningsDie(*CUDie);
2650void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2651 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getLocSection().Data,
2653 TheDwarfEmitter->emitSectionContents(
2654 Dwarf.getDWARFObj().getRangesSection().Data,
"debug_ranges");
2655 TheDwarfEmitter->emitSectionContents(
2656 Dwarf.getDWARFObj().getFrameSection().Data,
"debug_frame");
2657 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getArangesSection(),
2659 TheDwarfEmitter->emitSectionContents(
2660 Dwarf.getDWARFObj().getAddrSection().Data,
"debug_addr");
2661 TheDwarfEmitter->emitSectionContents(
2662 Dwarf.getDWARFObj().getRnglistsSection().Data,
"debug_rnglists");
2663 TheDwarfEmitter->emitSectionContents(
2664 Dwarf.getDWARFObj().getLoclistsSection().Data,
"debug_loclists");
2669 ObjectContexts.emplace_back(LinkContext(File));
2671 if (ObjectContexts.back().File.Dwarf) {
2672 for (
const std::unique_ptr<DWARFUnit> &
CU :
2673 ObjectContexts.back().File.Dwarf->compile_units()) {
2682 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
2689 assert((Options.TargetDWARFVersion != 0) &&
2690 "TargetDWARFVersion should be set");
2694 unsigned NumObjects = ObjectContexts.size();
2706 for (LinkContext &OptContext : ObjectContexts) {
2707 if (Options.Verbose) {
2709 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
2711 outs() <<
"OBJECT FILE: " << OptContext.File.FileName <<
"\n";
2714 if (emitPaperTrailWarnings(OptContext.File, DebugStrPool))
2717 if (!OptContext.File.Dwarf)
2720 if (Options.VerifyInputDWARF)
2721 verifyInput(OptContext.File);
2728 !OptContext.File.Addresses->hasValidRelocs()) {
2729 if (Options.Verbose)
2730 outs() <<
"No valid relocations found. Skipping.\n";
2734 OptContext.Skip =
true;
2739 if (!OptContext.File.Dwarf)
2743 if (!OptContext.File.Dwarf->types_section_units().empty()) {
2744 reportWarning(
"type units are not currently supported: file will "
2747 OptContext.Skip =
true;
2752 OptContext.CompileUnits.reserve(
2753 OptContext.File.Dwarf->getNumCompileUnits());
2755 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
2756 auto CUDie =
CU->getUnitDIE(
false);
2757 if (Options.Verbose) {
2758 outs() <<
"Input compilation unit:";
2761 DumpOpts.
Verbose = Options.Verbose;
2762 CUDie.dump(
outs(), 0, DumpOpts);
2766 for (
auto &
CU : OptContext.ModuleUnits) {
2767 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
2768 DebugLineStrPool, StringOffsetPool))
2769 reportWarning(
toString(std::move(Err)),
CU.File);
2779 (TheDwarfEmitter ==
nullptr) ? 0
2780 : TheDwarfEmitter->getDebugInfoSectionSize();
2784 std::mutex ProcessedFilesMutex;
2785 std::condition_variable ProcessedFilesConditionVariable;
2786 BitVector ProcessedFiles(NumObjects,
false);
2790 auto AnalyzeLambda = [&](
size_t I) {
2796 for (
const auto &
CU :
Context.File.Dwarf->compile_units()) {
2799 auto CUDie =
CU->getUnitDIE();
2800 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2803 !isClangModuleRef(CUDie, PCMFile,
Context, 0,
true).first) {
2804 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
2805 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
2810 for (
auto &CurrentUnit :
Context.CompileUnits) {
2811 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
2815 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
2816 ModulesEndOffset, Options.ParseableSwiftInterfaces,
2818 reportWarning(Warning, Context.File, &DIE);
2830 auto CloneLambda = [&](
size_t I) {
2831 auto &OptContext = ObjectContexts[
I];
2832 if (OptContext.Skip || !OptContext.File.Dwarf)
2841 for (
auto &CurrentUnit : OptContext.CompileUnits)
2842 CurrentUnit->markEverythingAsKept();
2843 copyInvariantDebugSection(*OptContext.File.Dwarf);
2845 for (
auto &CurrentUnit : OptContext.CompileUnits) {
2846 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
2847 CurrentUnit->getOrigUnit().getUnitDIE(),
2848 OptContext.File, *CurrentUnit, 0);
2858 if (OptContext.File.Addresses->hasValidRelocs() ||
2860 SizeByObject[OptContext.File.FileName].Input =
2862 SizeByObject[OptContext.File.FileName].Output =
2863 DIECloner(*
this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc,
2864 OptContext.CompileUnits, Options.Update, DebugStrPool,
2865 DebugLineStrPool, StringOffsetPool)
2866 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
2867 OptContext.File.Dwarf->isLittleEndian());
2869 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
2871 patchFrameInfoForObject(OptContext);
2874 cleanupAuxiliarryData(OptContext);
2877 auto EmitLambda = [&]() {
2879 if (TheDwarfEmitter !=
nullptr) {
2880 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
2881 TheDwarfEmitter->emitStrings(DebugStrPool);
2882 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.
DieValues,
2883 Options.TargetDWARFVersion);
2884 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
2886 switch (TableKind) {
2888 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
2889 TheDwarfEmitter->emitAppleNames(AppleNames);
2890 TheDwarfEmitter->emitAppleTypes(AppleTypes);
2891 TheDwarfEmitter->emitAppleObjc(AppleObjc);
2898 TheDwarfEmitter->emitDebugNames(DebugNames);
2905 auto AnalyzeAll = [&]() {
2906 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2909 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2910 ProcessedFiles.
set(
I);
2911 ProcessedFilesConditionVariable.notify_one();
2915 auto CloneAll = [&]() {
2916 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2918 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2919 if (!ProcessedFiles[
I]) {
2920 ProcessedFilesConditionVariable.wait(
2921 LockGuard, [&]() {
return ProcessedFiles[
I]; });
2933 if (Options.Threads == 1) {
2934 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2941 Pool.
async(AnalyzeAll);
2942 Pool.
async(CloneAll);
2946 if (Options.Statistics) {
2948 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
2949 for (
auto &
E : SizeByObject)
2950 Sorted.emplace_back(
E.first(),
E.second);
2952 return LHS.second.Output >
RHS.second.Output;
2955 auto ComputePercentange = [](int64_t Input, int64_t Output) ->
float {
2956 const float Difference = Output - Input;
2957 const float Sum = Input + Output;
2960 return (Difference / (Sum / 2));
2963 int64_t InputTotal = 0;
2964 int64_t OutputTotal = 0;
2965 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
2968 outs() <<
".debug_info section size (in bytes)\n";
2969 outs() <<
"----------------------------------------------------------------"
2970 "---------------\n";
2971 outs() <<
"Filename Object "
2973 outs() <<
"----------------------------------------------------------------"
2974 "---------------\n";
2977 for (
auto &
E : Sorted) {
2978 InputTotal +=
E.second.Input;
2979 OutputTotal +=
E.second.Output;
2982 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
2985 outs() <<
"----------------------------------------------------------------"
2986 "---------------\n";
2988 ComputePercentange(InputTotal, OutputTotal));
2989 outs() <<
"----------------------------------------------------------------"
2990 "---------------\n\n";
2996Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3002 assert(Unit.Unit.get() !=
nullptr);
3004 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3007 if (Options.Verbose) {
3009 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3014 &ODRContexts.
getRoot(), ODRContexts, 0,
3015 Options.ParseableSwiftInterfaces,
3016 [&](
const Twine &
Warning,
const DWARFDie &DIE) {
3017 reportWarning(Warning, Context.File, &DIE);
3020 Unit.Unit->markEverythingAsKept();
3024 CompileUnits.emplace_back(std::move(Unit.Unit));
3026 DIECloner(*
this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits,
3027 Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
3028 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3029 Unit.File.Dwarf->isLittleEndian());
3033void DWARFLinker::verifyInput(
const DWARFFile &File) {
3038 raw_string_ostream
OS(Buffer);
3039 DIDumpOptions DumpOpts;
3040 if (!
File.Dwarf->verify(
OS, DumpOpts.noImplicitRecursion())) {
3041 if (Options.InputVerificationHandler)
3042 Options.InputVerificationHandler(File,
OS.str());
3050 TheDwarfEmitter = std::make_unique<DwarfStreamer>(
3051 FileType, OutFile, StringsTranslator, WarningHandler);
3053 return TheDwarfEmitter->init(TheTriple,
"__DWARF");
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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,...
Stores all information relating to a compile unit, be it in its original instance in the object file ...
A structured debug information entry.
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
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.
iterator_range< iterator > children() const
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from 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
This class represents DWARF information for source file and its address map.
OutputFileType
Type of output file.
std::function< ErrorOr< DWARFFile & >(StringRef ContainerName, StringRef Path)> objFileLoader
Error link()
Link debug info for added objFiles. Object files are linked all together.
DwarfEmitter * getEmitter()
AccelTableKind
The kind of accelerator tables we should emit.
@ DebugNames
.debug_names.
@ Apple
.apple_names, .apple_namespaces, .apple_types, .apple_objc.
@ Pub
.debug_pubnames, .debug_pubtypes
void addObjectFile(DWARFFile &File, objFileLoader Loader=nullptr, CompileUnitHandler OnCUDieLoaded=[](const DWARFUnit &) {})
Add object file to be linked.
Error createEmitter(const Triple &TheTriple, OutputFileType FileType, raw_pwrite_stream &OutFile)
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.
DwarfEmitter presents interface to generate all debug info tables.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
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.
A ThreadPool for asynchronous parallel execution on a defined number of threads.
void wait()
Blocking wait for all the threads to complete and the queue to be empty.
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Triple - Helper class for working with autoconf configuration names.
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.
An efficient, type-erasing, non-owning reference to a callable.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
An abstract base class for streams implementations that also support a pwrite operation.
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.
@ C
The default llvm calling convention, compatible with C.
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.
StringMapEntry< std::nullopt_t > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
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 std::string getPCMFile(const DWARFDie &CUDie, objectPrefixMap *ObjectPrefixMap)
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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.
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
std::vector< std::unique_ptr< CompileUnit > > UnitListTy
SmallVector< PatchLocation > RngListAttributesTy
function_ref< void(const DWARFUnit &Unit)> CompileUnitHandler
static void patchAddrBase(DIE &Die, DIEInteger Offset)
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.
SmallVector< PatchLocation > LocListAttributesTy
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 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.
static void analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, DeclContext *CurrentDeclContext, DeclContextTree &Contexts, uint64_t ModulesEndOffset, swiftInterfacesMap *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Recursive helper to build the global DeclContext information and gather the child->parent relationshi...
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)
std::map< std::string, std::string > swiftInterfacesMap
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.
static std::string remapPath(StringRef Path, const objectPrefixMap &ObjectPrefixMap)
@ 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)
std::map< std::string, std::string > objectPrefixMap
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
static void analyzeImportedModule(const DWARFDie &DIE, CompileUnit &CU, swiftInterfacesMap *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
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 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.
ContextWorklistItemType
The distinct types of work performed by the work loop in analyzeContextInfo.
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
void consumeError(Error Err)
Consume a Error without doing anything.
static bool isODRAttribute(uint16_t Attr)
static void patchStmtList(DIE &Die, DIEInteger Offset)
A broken link in the keep chain.
BrokenLink(DWARFDie Parent, DWARFDie Child)
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?
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.
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.
SmallVector< uint64_t > DieValues
Hold the input and output of the debug info size in bytes.