55 for (
auto &Unit :
Dwarf.compile_units()) {
56 Size += Unit->getLength();
66 return LHS <
RHS->getOrigUnit().getNextUnitOffset();
68 return CU != Units.end() ?
CU->get() :
nullptr;
74DWARFDie DWARFLinker::resolveDIEReference(
const DWARFFile &File,
76 const DWARFFormValue &RefValue,
78 CompileUnit *&RefCU) {
81 if (std::optional<uint64_t> Off = RefValue.getAsRelativeReference()) {
82 RefOffset = RefValue.getUnit()->getOffset() + *Off;
83 }
else if (Off = RefValue.getAsDebugInfoReference(); Off) {
86 reportWarning(
"Unsupported reference type", File, &DIE);
90 if (
const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
97 reportWarning(
"could not find referenced DIE", File, &DIE);
107 case dwarf::DW_AT_type:
108 case dwarf::DW_AT_containing_type:
109 case dwarf::DW_AT_specification:
110 case dwarf::DW_AT_abstract_origin:
111 case dwarf::DW_AT_import:
112 case dwarf::DW_AT_LLVM_alloc_type:
120 case dwarf::DW_TAG_array_type:
121 case dwarf::DW_TAG_class_type:
122 case dwarf::DW_TAG_enumeration_type:
123 case dwarf::DW_TAG_pointer_type:
124 case dwarf::DW_TAG_reference_type:
125 case dwarf::DW_TAG_string_type:
126 case dwarf::DW_TAG_structure_type:
127 case dwarf::DW_TAG_subroutine_type:
128 case dwarf::DW_TAG_template_alias:
129 case dwarf::DW_TAG_typedef:
130 case dwarf::DW_TAG_union_type:
131 case dwarf::DW_TAG_ptr_to_member_type:
132 case dwarf::DW_TAG_set_type:
133 case dwarf::DW_TAG_subrange_type:
134 case dwarf::DW_TAG_base_type:
135 case dwarf::DW_TAG_const_type:
136 case dwarf::DW_TAG_constant:
137 case dwarf::DW_TAG_file_type:
138 case dwarf::DW_TAG_namelist:
139 case dwarf::DW_TAG_packed_type:
140 case dwarf::DW_TAG_volatile_type:
141 case dwarf::DW_TAG_restrict_type:
142 case dwarf::DW_TAG_atomic_type:
143 case dwarf::DW_TAG_interface_type:
144 case dwarf::DW_TAG_unspecified_type:
145 case dwarf::DW_TAG_shared_type:
146 case dwarf::DW_TAG_immutable_type:
157DWARFLinker::DIECloner::getCanonicalDIEName(DWARFDie Die,
const DWARFFile &File,
162 std::optional<DWARFFormValue>
Ref;
164 auto GetDieName = [](
const DWARFDie &
D) -> llvm::StringRef {
165 auto NameForm =
D.find(llvm::dwarf::DW_AT_name);
169 auto NameOrErr = NameForm->getAsCString();
178 llvm::StringRef
Name = GetDieName(Die);
183 if (!(
Ref = Die.find(llvm::dwarf::DW_AT_specification)) &&
184 !(
Ref = Die.find(llvm::dwarf::DW_AT_abstract_origin)))
187 Die = Linker.resolveDIEReference(File, CompileUnits, *
Ref, Die, Unit);
193 unsigned SpecIdx =
Unit->getOrigUnit().getDIEIndex(Die);
194 CompileUnit::DIEInfo &SpecInfo =
Unit->getInfo(SpecIdx);
195 if (SpecInfo.Ctxt && SpecInfo.Ctxt->hasCanonicalDIE()) {
196 if (!SpecInfo.Ctxt->getCanonicalName().empty()) {
197 Name = SpecInfo.Ctxt->getCanonicalName();
202 Name = GetDieName(Die);
210bool DWARFLinker::DIECloner::getDIENames(
212 const DWARFFile &File, CompileUnit &Unit,
bool StripTemplate) {
216 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
222 if (!
Info.MangledName)
223 if (
const char *MangledName = Die.getLinkageName())
224 Info.MangledName = StringPool.getEntry(MangledName);
230 if (llvm::StringRef Name = getCanonicalDIEName(Die, File, &Unit);
232 Info.Name = StringPool.getEntry(Name);
234 if (!
Info.MangledName)
237 if (StripTemplate &&
Info.Name &&
Info.MangledName !=
Info.Name) {
238 StringRef
Name =
Info.Name.getString();
240 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
243 return Info.Name ||
Info.MangledName;
257 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
258 if (
CU.getLanguage() != dwarf::DW_LANG_Swift)
261 if (!ParseableSwiftInterfaces)
265 if (!Path.ends_with(
".swiftinterface"))
270 SysRoot =
CU.getSysRoot();
271 if (!SysRoot.
empty() && Path.starts_with(SysRoot))
276 if (!DeveloperDir.
empty() && Path.starts_with(DeveloperDir))
280 std::optional<const char *> Name =
284 auto &Entry = (*ParseableSwiftInterfaces)[*Name];
286 DWARFDie CUDie =
CU.getOrigUnit().getUnitDIE();
291 if (!Entry.empty() && Entry != ResolvedPath)
292 ReportWarning(
Twine(
"Conflicting parseable interfaces for Swift Module ") +
293 *Name +
": " + Entry +
" and " + Path,
295 Entry = std::string(ResolvedPath);
338 Info.Prune &= (Die.
getTag() == dwarf::DW_TAG_module) ||
344 if (ModulesEndOffset == 0)
345 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();
347 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 &&
348 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
356 Info.Prune &= ChildInfo.
Prune;
372 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
374 std::vector<ContextWorklistItem> Worklist;
375 Worklist.emplace_back(
DIE, CurrentDeclContext, ParentIdx,
false);
377 while (!Worklist.empty()) {
381 switch (Current.
Type) {
392 unsigned Idx =
CU.getOrigUnit().getDIEIndex(Current.
Die);
407 if (Current.
Die.
getTag() == dwarf::DW_TAG_module &&
410 CU.getClangModuleName()) {
418 if (
CU.hasODR() || Info.InModuleScope) {
422 Current.
Context = PtrInvalidPair.getPointer();
424 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
428 Info.Ctxt = Current.
Context =
nullptr;
437 Worklist.emplace_back(
439 Worklist.emplace_back(Child, Current.
Context, Idx,
449 case dwarf::DW_TAG_class_type:
450 case dwarf::DW_TAG_common_block:
451 case dwarf::DW_TAG_enumeration_type:
452 case dwarf::DW_TAG_lexical_block:
453 case dwarf::DW_TAG_structure_type:
454 case dwarf::DW_TAG_subprogram:
455 case dwarf::DW_TAG_subroutine_type:
456 case dwarf::DW_TAG_union_type:
462void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
465 for (DIEBlock *
I : DIEBlocks)
467 for (DIELoc *
I : DIELocs)
481 auto StmtAttrs = Unit.getStmtSeqListAttributes();
483 SortedOffsets.
reserve(StmtAttrs.size());
493std::pair<bool, std::optional<int64_t>>
494DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
495 const DWARFDie &DIE) {
496 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
497 DIE.getTag() == dwarf::DW_TAG_constant) &&
498 "Wrong type of input die");
500 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
503 DWARFUnit *U = DIE.getDwarfUnit();
504 std::optional<uint32_t> LocationIdx =
505 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
507 return std::make_pair(
false, std::nullopt);
511 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
514 std::optional<DWARFFormValue> LocationValue =
515 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
517 return std::make_pair(
false, std::nullopt);
522 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
524 return std::make_pair(
false, std::nullopt);
527 DataExtractor
Data(*Expr, U->getContext().isLittleEndian());
528 DWARFExpression Expression(
Data, U->getAddressByteSize(),
529 U->getFormParams().Format);
531 bool HasLocationAddress =
false;
533 for (DWARFExpression::iterator It = Expression.begin();
534 It != Expression.end(); ++It) {
535 DWARFExpression::iterator NextIt = It;
538 const DWARFExpression::Operation &
Op = *It;
540 case dwarf::DW_OP_const2u:
541 case dwarf::DW_OP_const4u:
542 case dwarf::DW_OP_const8u:
543 case dwarf::DW_OP_const2s:
544 case dwarf::DW_OP_const4s:
545 case dwarf::DW_OP_const8s:
546 if (NextIt == Expression.end() ||
550 case dwarf::DW_OP_addr: {
551 HasLocationAddress =
true;
553 if (std::optional<int64_t> RelocAdjustment =
554 RelocMgr.getExprOpAddressRelocAdjustment(
555 *U,
Op, AttrOffset + CurExprOffset,
557 return std::make_pair(HasLocationAddress, *RelocAdjustment);
559 case dwarf::DW_OP_constx:
560 case dwarf::DW_OP_addrx: {
561 HasLocationAddress =
true;
562 if (std::optional<uint64_t> AddressOffset =
563 DIE.getDwarfUnit()->getIndexedAddressOffset(
566 if (std::optional<int64_t> RelocAdjustment =
567 RelocMgr.getExprOpAddressRelocAdjustment(
568 *U,
Op, *AddressOffset,
569 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
571 return std::make_pair(HasLocationAddress, *RelocAdjustment);
581 return std::make_pair(HasLocationAddress, std::nullopt);
586unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
588 CompileUnit::DIEInfo &MyInfo,
590 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
593 if (!(Flags & TF_InFunctionScope) &&
594 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
595 MyInfo.InDebugMap =
true;
596 return Flags | TF_Keep;
604 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
605 getVariableRelocAdjustment(RelocMgr, DIE);
607 if (LocExprAddrAndRelocAdjustment.first)
608 MyInfo.HasLocationExpressionAddr =
true;
610 if (!LocExprAddrAndRelocAdjustment.second)
613 MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second;
614 MyInfo.InDebugMap =
true;
616 if (((Flags & TF_InFunctionScope) &&
620 if (Options.Verbose) {
621 outs() <<
"Keeping variable DIE:";
622 DIDumpOptions DumpOpts;
623 DumpOpts.ChildRecurseDepth = 0;
624 DumpOpts.Verbose = Options.Verbose;
625 DIE.dump(
outs(), 8 , DumpOpts);
628 return Flags | TF_Keep;
633unsigned DWARFLinker::shouldKeepSubprogramDIE(
634 AddressesMap &RelocMgr,
const DWARFDie &DIE,
const DWARFFile &File,
635 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
636 Flags |= TF_InFunctionScope;
642 assert(LowPc &&
"low_pc attribute is not an address.");
643 std::optional<int64_t> RelocAdjustment =
644 RelocMgr.getSubprogramRelocAdjustment(DIE, Options.Verbose);
645 if (!RelocAdjustment)
648 MyInfo.AddrAdjust = *RelocAdjustment;
649 MyInfo.InDebugMap =
true;
651 if (Options.Verbose) {
652 outs() <<
"Keeping subprogram DIE:";
653 DIDumpOptions DumpOpts;
654 DumpOpts.ChildRecurseDepth = 0;
655 DumpOpts.Verbose = Options.Verbose;
656 DIE.dump(
outs(), 8 , DumpOpts);
659 if (DIE.getTag() == dwarf::DW_TAG_label) {
660 if (
Unit.hasLabelAt(*LowPc))
663 DWARFUnit &OrigUnit =
Unit.getOrigUnit();
673 if (
Unit.getLanguage() == dwarf::DW_LANG_Mips_Assembler ||
674 Unit.getLanguage() == dwarf::DW_LANG_Assembly) {
675 if (
auto Range = RelocMgr.getSymbolRangeForAddress(*LowPc)) {
676 Unit.addFunctionRange(
Range->LowPC,
Range->HighPC, MyInfo.AddrAdjust);
678 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
681 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
683 return Flags | TF_Keep;
688 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
690 reportWarning(
"Function without high_pc. Range will be discarded.\n", File,
694 if (*LowPc > *HighPc) {
695 reportWarning(
"low_pc greater than high_pc. Range will be discarded.\n",
701 Unit.addFunctionRange(
703 RelocMgr.constrainCodeRangeHighPC(*LowPc, *HighPc, MyInfo.AddrAdjust),
710unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr,
const DWARFDie &DIE,
711 const DWARFFile &File, CompileUnit &Unit,
712 CompileUnit::DIEInfo &MyInfo,
714 switch (DIE.getTag()) {
715 case dwarf::DW_TAG_constant:
716 case dwarf::DW_TAG_variable:
717 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
718 case dwarf::DW_TAG_subprogram:
719 case dwarf::DW_TAG_label:
720 return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags);
721 case dwarf::DW_TAG_base_type:
724 case dwarf::DW_TAG_imported_module:
725 case dwarf::DW_TAG_imported_declaration:
726 case dwarf::DW_TAG_imported_unit:
728 return Flags | TF_Keep;
742 case dwarf::DW_TAG_structure_type:
743 case dwarf::DW_TAG_class_type:
744 case dwarf::DW_TAG_union_type:
762 case dwarf::DW_TAG_typedef:
763 case dwarf::DW_TAG_member:
764 case dwarf::DW_TAG_reference_type:
765 case dwarf::DW_TAG_ptr_to_member_type:
766 case dwarf::DW_TAG_pointer_type:
783void DWARFLinker::lookForChildDIEsToKeep(
784 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
785 SmallVectorImpl<WorklistItem> &Worklist) {
792 Flags &= ~DWARFLinker::TF_ParentWalk;
796 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
801 for (
auto Child :
reverse(Die.children())) {
804 CompileUnit::DIEInfo &ChildInfo =
CU.getInfo(Child);
805 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateChildIncompleteness,
807 Worklist.emplace_back(Child,
CU, Flags);
814 if (!Info.Ctxt || (Die.
getTag() == dwarf::DW_TAG_namespace))
817 if (!
CU.hasODR() && !Info.InModuleScope)
820 return !Info.Incomplete && Info.Ctxt !=
CU.getInfo(Info.ParentIdx).Ctxt;
823void DWARFLinker::markODRCanonicalDie(
const DWARFDie &Die, CompileUnit &
CU) {
824 CompileUnit::DIEInfo &Info =
CU.getInfo(Die);
826 Info.ODRMarkingDone =
true;
828 !Info.Ctxt->hasCanonicalDIE())
829 Info.Ctxt->setHasCanonicalDIE();
834void DWARFLinker::lookForRefDIEsToKeep(
835 const DWARFDie &Die, CompileUnit &CU,
unsigned Flags,
836 const UnitListTy &Units,
const DWARFFile &File,
837 SmallVectorImpl<WorklistItem> &Worklist) {
838 bool UseOdr = (
Flags & DWARFLinker::TF_DependencyWalk)
839 ? (Flags & DWARFLinker::TF_ODR)
841 DWARFUnit &
Unit = CU.getOrigUnit();
842 DWARFDataExtractor
Data =
Unit.getDebugInfoExtractor();
843 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
847 for (
const auto &AttrSpec : Abbrev->attributes()) {
848 DWARFFormValue Val(AttrSpec.Form);
850 AttrSpec.Attr == dwarf::DW_AT_sibling) {
852 Unit.getFormParams());
857 CompileUnit *ReferencedCU;
859 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
860 CompileUnit::DIEInfo &
Info = ReferencedCU->getInfo(RefDie);
871 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
873 Info.Ctxt->hasCanonicalDIE())
878 Info.Ctxt->hasCanonicalDIE()))
880 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
884 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
888 for (
auto &
P :
reverse(ReferencedDIEs)) {
891 CompileUnit::DIEInfo &
Info =
P.second.getInfo(
P.first);
892 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness,
894 Worklist.emplace_back(
P.first,
P.second,
895 DWARFLinker::TF_Keep |
896 DWARFLinker::TF_DependencyWalk | ODRFlag);
901void DWARFLinker::lookForParentDIEsToKeep(
902 unsigned AncestorIdx, CompileUnit &CU,
unsigned Flags,
903 SmallVectorImpl<WorklistItem> &Worklist) {
905 if (CU.getInfo(AncestorIdx).Keep)
908 DWARFUnit &
Unit = CU.getOrigUnit();
909 DWARFDie ParentDIE =
Unit.getDIEAtIndex(AncestorIdx);
910 Worklist.emplace_back(CU.getInfo(AncestorIdx).ParentIdx, CU, Flags);
911 Worklist.emplace_back(ParentDIE, CU, Flags);
939void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
941 const DWARFDie &Die,
const DWARFFile &File,
942 CompileUnit &Cu,
unsigned Flags) {
945 Worklist.emplace_back(Die, Cu, Flags);
947 while (!Worklist.empty()) {
948 WorklistItem Current = Worklist.pop_back_val();
951 switch (Current.Type) {
952 case WorklistItemType::UpdateChildIncompleteness:
955 case WorklistItemType::UpdateRefIncompleteness:
958 case WorklistItemType::LookForChildDIEsToKeep:
959 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
961 case WorklistItemType::LookForRefDIEsToKeep:
962 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
965 case WorklistItemType::LookForParentDIEsToKeep:
966 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
969 case WorklistItemType::MarkODRCanonicalDie:
970 markODRCanonicalDie(Current.Die, Current.CU);
972 case WorklistItemType::LookForDIEsToKeep:
976 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
977 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx);
982 if (Current.Flags & TF_DependencyWalk)
983 MyInfo.Prune =
false;
990 bool AlreadyKept = MyInfo.Keep;
991 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
994 if (!(Current.Flags & TF_DependencyWalk))
995 Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU,
996 MyInfo, Current.Flags);
1001 if (!(Current.Flags & TF_DependencyWalk) ||
1002 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
1003 if (Current.CU.hasODR() || MyInfo.InModuleScope)
1004 Worklist.emplace_back(Current.Die, Current.CU,
1005 WorklistItemType::MarkODRCanonicalDie);
1011 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1012 WorklistItemType::LookForChildDIEsToKeep);
1014 if (AlreadyKept || !(Current.Flags & TF_Keep))
1023 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
1024 Current.Die.getTag() != dwarf::DW_TAG_member &&
1030 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1031 WorklistItemType::LookForRefDIEsToKeep);
1033 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
1034 : Current.CU.hasODR();
1035 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
1036 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
1039 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
1055 std::vector<DWARFDie> Worklist;
1056 Worklist.push_back(
CU.getOrigUnit().getUnitDIE());
1059 std::vector<BrokenLink> BrokenLinks;
1061 while (!Worklist.empty()) {
1062 const DWARFDie Current = Worklist.back();
1063 Worklist.pop_back();
1065 const bool CurrentDieIsKept =
CU.getInfo(Current).Keep;
1068 Worklist.push_back(Child);
1070 const bool ChildDieIsKept =
CU.getInfo(Child).Keep;
1071 if (!CurrentDieIsKept && ChildDieIsKept)
1072 BrokenLinks.emplace_back(Current, Child);
1076 if (!BrokenLinks.empty()) {
1079 "Found invalid link in keep chain between {0:x} and {1:x}\n",
1080 Link.Parent.getOffset(), Link.Child.getOffset());
1082 errs() <<
"Parent:";
1083 Link.Parent.dump(
errs(), 0, {});
1084 CU.getInfo(Link.Parent).dump();
1087 Link.Child.dump(
errs(), 2, {});
1088 CU.getInfo(Link.Child).dump();
1101void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
1103 FoldingSetNodeID ID;
1106 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
1111 Abbrev.setNumber(InSet->getNumber());
1114 Abbreviations.push_back(
1115 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
1116 for (
const auto &Attr : Abbrev.getData())
1117 Abbreviations.back()->AddAttribute(Attr);
1118 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
1120 Abbrev.setNumber(Abbreviations.size());
1121 Abbreviations.back()->setNumber(Abbreviations.size());
1125unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
1126 AttributeSpec AttrSpec,
1127 const DWARFFormValue &Val,
1129 AttributesInfo &Info) {
1134 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
1139 if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
1140 Info.HasAppleOrigin =
true;
1141 if (std::optional<StringRef> FileName =
1142 ObjFile.Addresses->getLibraryInstallName()) {
1148 if (AttrSpec.Attr == dwarf::DW_AT_name)
1150 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
1151 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
1153 if (
U.getVersion() >= 5) {
1155 auto StringOffsetIndex =
1156 StringOffsetPool.getValueIndex(
StringEntry.getOffset());
1159 dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
1160 ->sizeOf(
U.getFormParams());
1163 AttrSpec.Form = dwarf::DW_FORM_strp;
1170unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
1171 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1172 unsigned AttrSize,
const DWARFFormValue &Val,
const DWARFFile &File,
1173 CompileUnit &Unit) {
1174 const DWARFUnit &
U =
Unit.getOrigUnit();
1176 if (std::optional<uint64_t> Off = Val.getAsRelativeReference())
1177 Ref = Val.getUnit()->getOffset() + *
Off;
1178 else if (Off = Val.getAsDebugInfoReference(); Off)
1183 DIE *NewRefDie =
nullptr;
1184 CompileUnit *RefUnit =
nullptr;
1187 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
1190 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
1193 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
1198 RefInfo.Ctxt->getCanonicalDIEOffset()) {
1199 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
1200 "Offset to canonical die is set, but context is not marked");
1201 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
1203 dwarf::DW_FORM_ref_addr, Attr);
1204 return U.getRefAddrByteSize();
1207 if (!RefInfo.Clone) {
1210 RefInfo.UnclonedReference =
true;
1213 NewRefDie = RefInfo.Clone;
1215 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1217 if (
Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1222 dwarf::DW_FORM_ref_addr, DIEEntry(*NewRefDie));
1228 Unit.noteForwardReference(
1229 NewRefDie, RefUnit, RefInfo.Ctxt,
1231 dwarf::DW_FORM_ref_addr, DIEInteger(
UINT64_MAX)));
1233 return U.getRefAddrByteSize();
1237 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1242void DWARFLinker::DIECloner::cloneExpression(
1243 DataExtractor &
Data, DWARFExpression Expression,
const DWARFFile &File,
1244 CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer,
1245 int64_t AddrRelocAdjustment,
bool IsLittleEndian) {
1248 uint8_t OrigAddressByteSize =
Unit.getOrigUnit().getAddressByteSize();
1251 for (
auto &
Op : Expression) {
1257 Linker.reportWarning(
1258 "cannot decode a DW_OP, copying the rest of the expression "
1261 StringRef Bytes =
Data.getData().substr(OpOffset);
1262 OutputBuffer.append(Bytes.begin(), Bytes.end());
1270 Desc.
Op[0] != Encoding::Size1))
1271 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
1275 Desc.
Op[0] == Encoding::Size1)) {
1295 if (RefOffset > 0 ||
Op.
getCode() != dwarf::DW_OP_convert) {
1296 RefOffset +=
Unit.getOrigUnit().getOffset();
1297 auto RefDie =
Unit.getOrigUnit().getDIEForOffset(RefOffset);
1298 CompileUnit::DIEInfo &
Info =
Unit.getInfo(RefDie);
1299 if (DIE *Clone =
Info.Clone)
1300 Offset = Clone->getOffset();
1302 Linker.reportWarning(
1303 "base type ref doesn't point to DW_TAG_base_type.", File);
1307 if (RealSize > ULEBsize) {
1310 Linker.reportWarning(
"base type ref doesn't fit.", File);
1312 assert(RealSize == ULEBsize &&
"padding failed");
1313 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1314 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1315 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_addrx) {
1316 if (std::optional<object::SectionedAddress> SA =
1317 Unit.getOrigUnit().getAddrOffsetSectionItem(
1323 OutputBuffer.push_back(dwarf::DW_OP_addr);
1324 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1327 ArrayRef<uint8_t> AddressBytes(
1328 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1329 OrigAddressByteSize);
1330 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1332 Linker.reportWarning(
"cannot read DW_OP_addrx operand.", File);
1333 }
else if (!Linker.Options.Update &&
Op.
getCode() == dwarf::DW_OP_constx) {
1334 if (std::optional<object::SectionedAddress> SA =
1335 Unit.getOrigUnit().getAddrOffsetSectionItem(
1341 std::optional<uint8_t> OutOperandKind;
1342 switch (OrigAddressByteSize) {
1344 OutOperandKind = dwarf::DW_OP_const4u;
1347 OutOperandKind = dwarf::DW_OP_const8u;
1350 Linker.reportWarning(
1351 formatv((
"unsupported address size: {0}."), OrigAddressByteSize),
1356 if (OutOperandKind) {
1357 OutputBuffer.push_back(*OutOperandKind);
1358 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1361 ArrayRef<uint8_t> AddressBytes(
1362 reinterpret_cast<const uint8_t *
>(&LinkedAddress),
1363 OrigAddressByteSize);
1364 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1367 Linker.reportWarning(
"cannot read DW_OP_constx operand.", File);
1371 OutputBuffer.append(Bytes.begin(), Bytes.end());
1377unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1378 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1379 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1380 bool IsLittleEndian) {
1383 DIELoc *Loc =
nullptr;
1384 DIEBlock *
Block =
nullptr;
1385 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1386 Loc =
new (DIEAlloc) DIELoc;
1387 Linker.DIELocs.push_back(Loc);
1389 Block =
new (DIEAlloc) DIEBlock;
1390 Linker.DIEBlocks.push_back(
Block);
1392 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1393 : static_cast<DIEValueList *>(
Block);
1395 DWARFUnit &OrigUnit =
Unit.getOrigUnit();
1398 SmallVector<uint8_t, 32> Buffer;
1399 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1403 DataExtractor Data(Bytes, IsLittleEndian);
1404 DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
1405 OrigUnit.getFormParams().Format);
1406 cloneExpression(Data, Expr, File, Unit, Buffer,
1407 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);
1410 for (
auto Byte : Bytes)
1412 dwarf::DW_FORM_data1, DIEInteger(Byte));
1418 Loc->setSize(Bytes.size());
1420 Block->setSize(Bytes.size());
1428 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&
1429 (Bytes.size() > UINT8_MAX)) ||
1430 (AttrSpec.Form == dwarf::DW_FORM_block2 &&
1431 (Bytes.size() > UINT16_MAX)) ||
1432 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))
1433 AttrSpec.Form = dwarf::DW_FORM_block;
1435 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
1436 dwarf::Form(AttrSpec.Form), Block);
1439 return Die.addValue(DIEAlloc,
Value)->sizeOf(OrigUnit.getFormParams());
1450 bool IsLength, int64_t PCOffset,
1452 std::optional<uint64_t> LowPC =
1457 *LowPC, IsLength ? *LowPC + HighPC : HighPC, PCOffset);
1458 return IsLength ? Constrained - *LowPC : Constrained;
1461unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1462 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1463 unsigned AttrSize,
const DWARFFormValue &Val,
const CompileUnit &Unit,
1464 AttributesInfo &Info) {
1465 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1466 Info.HasLowPc =
true;
1470 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1486 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1490 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
1492 Linker.reportWarning(
"Cann't read address attribute value.", ObjFile);
1496 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1497 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1498 if (std::optional<uint64_t> LowPC =
Unit.getLowPc())
1502 }
else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1503 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1509 if (AttrSpec.Attr == dwarf::DW_AT_high_pc)
1511 *ObjFile.Addresses);
1512 *Addr +=
Info.PCOffset;
1515 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
1517 AttrSpec.Form, DIEInteger(*Addr));
1518 return Unit.getOrigUnit().getAddressByteSize();
1521 auto AddrIndex = AddrPool.getValueIndex(*Addr);
1525 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))
1526 ->sizeOf(
Unit.getOrigUnit().getFormParams());
1529unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1530 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1531 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1532 unsigned AttrSize, AttributesInfo &Info) {
1537 if (AttrSpec.Attr == dwarf::DW_AT_GNU_dwo_id ||
1538 AttrSpec.Attr == dwarf::DW_AT_dwo_id)
1543 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1544 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1545 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacinfo();
1551 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1552 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1553 const llvm::DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacro();
1559 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1563 Info.AttrStrOffsetBaseSeen =
true;
1565 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1566 dwarf::DW_FORM_sec_offset, DIEInteger(8))
1567 ->sizeOf(
Unit.getOrigUnit().getFormParams());
1570 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
1573 dwarf::DW_FORM_sec_offset,
1574 DIEInteger(*Val.getAsSectionOffset()));
1577 Unit.noteStmtSeqListAttribute(Patch);
1579 return Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1583 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1584 Value = *OptionalValue;
1585 else if (
auto OptionalValue = Val.getAsSignedConstant())
1586 Value = *OptionalValue;
1587 else if (
auto OptionalValue = Val.getAsSectionOffset())
1588 Value = *OptionalValue;
1590 Linker.reportWarning(
1591 "Unsupported scalar attribute form. Dropping attribute.", File,
1595 if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1596 Info.IsDeclaration =
true;
1598 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1607 [[maybe_unused]]
dwarf::Form OriginalForm = AttrSpec.Form;
1608 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1612 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1614 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1618 std::optional<uint64_t>
Offset =
1619 Unit.getOrigUnit().getRnglistOffset(*Index);
1621 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1627 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1628 AttrSize =
Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1629 }
else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1633 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1635 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1639 std::optional<uint64_t>
Offset =
1640 Unit.getOrigUnit().getLoclistOffset(*Index);
1642 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1648 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1649 AttrSize =
Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1650 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1651 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1652 std::optional<uint64_t> LowPC =
Unit.getLowPc();
1657 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1658 Value = *Val.getAsSectionOffset();
1659 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1660 Value = *Val.getAsSignedConstant();
1661 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1662 Value = *OptionalValue;
1664 Linker.reportWarning(
1665 "Unsupported scalar attribute form. Dropping attribute.", File,
1672 if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1673 Die.getTag() != dwarf::DW_TAG_compile_unit)
1677 DIE::value_iterator Patch =
1680 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1681 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1682 Unit.noteRangeAttribute(Die, Patch);
1683 Info.HasRanges =
true;
1687 Unit.getOrigUnit().getVersion())) {
1689 CompileUnit::DIEInfo &LocationDieInfo =
Unit.getInfo(InputDIE);
1690 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
1691 ? LocationDieInfo.AddrAdjust
1693 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1694 Info.IsDeclaration =
true;
1697 assert((
Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1698 "Unhandled DW_FORM_rnglistx attribute");
1706unsigned DWARFLinker::DIECloner::cloneAttribute(
1707 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1708 CompileUnit &Unit,
const DWARFFormValue &Val,
const AttributeSpec AttrSpec,
1709 unsigned AttrSize, AttributesInfo &Info,
bool IsLittleEndian) {
1710 const DWARFUnit &
U =
Unit.getOrigUnit();
1712 switch (AttrSpec.Form) {
1713 case dwarf::DW_FORM_strp:
1714 case dwarf::DW_FORM_line_strp:
1715 case dwarf::DW_FORM_string:
1716 case dwarf::DW_FORM_strx:
1717 case dwarf::DW_FORM_strx1:
1718 case dwarf::DW_FORM_strx2:
1719 case dwarf::DW_FORM_strx3:
1720 case dwarf::DW_FORM_strx4:
1721 return cloneStringAttribute(Die, AttrSpec, Val, U, Info);
1722 case dwarf::DW_FORM_ref_addr:
1723 case dwarf::DW_FORM_ref1:
1724 case dwarf::DW_FORM_ref2:
1725 case dwarf::DW_FORM_ref4:
1726 case dwarf::DW_FORM_ref8:
1727 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1729 case dwarf::DW_FORM_block:
1730 case dwarf::DW_FORM_block1:
1731 case dwarf::DW_FORM_block2:
1732 case dwarf::DW_FORM_block4:
1733 case dwarf::DW_FORM_exprloc:
1734 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1736 case dwarf::DW_FORM_addr:
1737 case dwarf::DW_FORM_addrx:
1738 case dwarf::DW_FORM_addrx1:
1739 case dwarf::DW_FORM_addrx2:
1740 case dwarf::DW_FORM_addrx3:
1741 case dwarf::DW_FORM_addrx4:
1742 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1744 case dwarf::DW_FORM_data1:
1745 case dwarf::DW_FORM_data2:
1746 case dwarf::DW_FORM_data4:
1747 case dwarf::DW_FORM_data8:
1748 case dwarf::DW_FORM_udata:
1749 case dwarf::DW_FORM_sdata:
1750 case dwarf::DW_FORM_sec_offset:
1751 case dwarf::DW_FORM_flag:
1752 case dwarf::DW_FORM_flag_present:
1753 case dwarf::DW_FORM_rnglistx:
1754 case dwarf::DW_FORM_loclistx:
1755 case dwarf::DW_FORM_implicit_const:
1756 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1759 Linker.reportWarning(
"Unsupported attribute form " +
1761 " in cloneAttribute. Dropping.",
1768void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1770 DwarfStringPoolEntryRef Name,
1772 bool SkipPubSection) {
1773 std::optional<ObjCSelectorNames> Names =
1777 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),
1779 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),
1781 if (Names->ClassNameNoCategory)
1782 Unit.addObjCAccelerator(
1783 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);
1784 if (Names->MethodNameNoCategory)
1785 Unit.addNameAccelerator(
1786 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);
1793 switch (AttrSpec.
Attr) {
1796 case dwarf::DW_AT_low_pc:
1797 case dwarf::DW_AT_high_pc:
1798 case dwarf::DW_AT_ranges:
1799 return !Update && SkipPC;
1800 case dwarf::DW_AT_rnglists_base:
1806 case dwarf::DW_AT_loclists_base:
1812 case dwarf::DW_AT_location:
1813 case dwarf::DW_AT_frame_base:
1814 return !Update && SkipPC;
1824DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1826 int64_t PCOffset,
uint32_t OutOffset,
1827 unsigned Flags,
bool IsLittleEndian,
1830 unsigned Idx = U.getDIEIndex(InputDIE);
1834 if (!Unit.getInfo(Idx).Keep)
1838 assert(!(Die && Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1850 (Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1851 if (!Info.Ctxt->hasCanonicalDIE())
1852 Info.Ctxt->setHasCanonicalDIE();
1856 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1860 DWARFDataExtractor
Data =
U.getDebugInfoExtractor();
1864 uint64_t NextOffset = (Idx + 1 <
U.getNumDIEs())
1865 ?
U.getDIEAtIndex(Idx + 1).getOffset()
1866 :
U.getNextUnitOffset();
1867 AttributesInfo AttrInfo;
1872 SmallString<40> DIECopy(
Data.getData().substr(
Offset, NextOffset -
Offset));
1874 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1877 ObjFile.Addresses->applyValidRelocs(DIECopy,
Offset,
Data.isLittleEndian());
1887 if (Die->
getTag() == dwarf::DW_TAG_subprogram)
1888 PCOffset =
Info.AddrAdjust;
1889 AttrInfo.PCOffset = PCOffset;
1891 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1892 Flags |= TF_InFunctionScope;
1895 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1898 if ((Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1899 Flags &= ~TF_SkipPC;
1902 else if (!
Info.InDebugMap &&
Info.HasLocationExpressionAddr &&
1907 std::optional<StringRef> LibraryInstallName =
1908 ObjFile.Addresses->getLibraryInstallName();
1910 for (
const auto &AttrSpec : Abbrev->attributes()) {
1917 AttributeLinkedOffsetFixup CurAttrFixup;
1919 CurAttrFixup.LinkedOffsetFixupVal =
1920 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1922 DWARFFormValue Val = AttrSpec.getFormValue();
1924 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1926 AttrSize =
Offset - AttrSize;
1929 cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
1930 AttrInfo, IsLittleEndian);
1931 if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
1932 AttributesFixups.push_back(CurAttrFixup);
1934 OutOffset += FinalAttrSize;
1940 const bool NeedsAppleOrigin = (
Tag == dwarf::DW_TAG_compile_unit) &&
1941 LibraryInstallName.has_value() &&
1942 !AttrInfo.HasAppleOrigin;
1943 if (NeedsAppleOrigin) {
1944 auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
1946 dwarf::DW_FORM_strp, DIEInteger(
StringEntry.getOffset()));
1955 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1956 Tag != dwarf::DW_TAG_compile_unit &&
1957 getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit,
1958 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1959 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1960 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1961 Tag == dwarf::DW_TAG_inlined_subroutine);
1962 if (AttrInfo.Name) {
1963 if (AttrInfo.NameWithoutTemplate)
1964 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1966 Unit.addNameAccelerator(Die, AttrInfo.Name,
1967 Tag == dwarf::DW_TAG_inlined_subroutine);
1970 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,
1973 }
else if (
Tag == dwarf::DW_TAG_namespace) {
1975 AttrInfo.Name = DebugStrPool.getEntry(
"(anonymous namespace)");
1976 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1977 }
else if (
Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1978 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1979 }
else if (
isTypeTag(
Tag) && !AttrInfo.IsDeclaration) {
1980 bool Success = getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit);
1984 bool ObjCClassIsImplementation =
1985 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1986 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1989 if (
Success && AttrInfo.Name && !AttrInfo.Name.getString().empty()) {
1991 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1996 if (
Success && AttrInfo.MangledName &&
1997 RuntimeLang == dwarf::DW_LANG_Swift &&
1998 !AttrInfo.MangledName.getString().empty() &&
1999 AttrInfo.MangledName != AttrInfo.Name) {
2000 auto Hash =
djbHash(AttrInfo.MangledName.getString().data());
2001 Unit.addTypeAccelerator(Die, AttrInfo.MangledName,
2002 ObjCClassIsImplementation, Hash);
2007 bool HasChildren =
false;
2008 for (
auto Child : InputDIE.
children()) {
2009 unsigned Idx =
U.getDIEIndex(Child);
2010 if (
Unit.getInfo(Idx).Keep) {
2016 if (
Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
2017 Die->
getTag() == dwarf::DW_TAG_compile_unit) {
2019 Die->
addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
2020 dwarf::DW_FORM_sec_offset, DIEInteger(8));
2028 Linker.assignAbbrev(NewAbbrev);
2034 OutOffset += AbbrevNumberSize;
2037 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2038 F.LinkedOffsetFixupVal += AbbrevNumberSize;
2040 for (AttributeLinkedOffsetFixup &
F : AttributesFixups)
2041 ObjFile.Addresses->updateAndSaveValidRelocs(
2042 Unit.getOrigUnit().getVersion() >= 5,
Unit.getOrigUnit().getOffset(),
2043 F.LinkedOffsetFixupVal,
F.InputAttrStartOffset,
F.InputAttrEndOffset);
2052 for (
auto Child : InputDIE.
children()) {
2053 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
2056 OutOffset = Clone->getOffset() + Clone->getSize();
2061 OutOffset +=
sizeof(int8_t);
2070Error DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File,
2075 const auto &FunctionRanges =
Unit.getFunctionRanges();
2078 AddressRanges LinkedFunctionRanges;
2079 for (
const AddressRangeValuePair &
Range : FunctionRanges)
2080 LinkedFunctionRanges.insert(
2084 if (!LinkedFunctionRanges.empty())
2085 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
2088 std::optional<PatchLocation> UnitRngListAttribute =
2089 Unit.getUnitRangesAttribute();
2091 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
2092 std::optional<AddressRangeValuePair> CachedRange;
2093 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
2097 for (PatchLocation &AttributePatch : AllRngListAttributes) {
2100 AddressRanges LinkedRanges;
2101 if (Expected<DWARFAddressRangesVector> OriginalRanges =
2102 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
2104 for (
const auto &
Range : *OriginalRanges) {
2105 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
2106 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
2110 reportWarning(
"inconsistent range data.", File);
2115 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
2116 Range.HighPC + CachedRange->Value});
2120 reportWarning(
"invalid range list ignored.", File);
2124 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2125 Unit, LinkedRanges, AttributePatch, AddrPool))
2130 if (UnitRngListAttribute.has_value())
2131 if (
Error E = TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2132 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool))
2136 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
2142Error DWARFLinker::DIECloner::generateUnitLocations(
2143 CompileUnit &Unit,
const DWARFFile &File,
2144 ExpressionHandlerRef ExprHandler) {
2149 Unit.getLocationAttributes();
2151 if (AllLocListAttributes.empty())
2157 for (
auto &CurLocAttr : AllLocListAttributes) {
2160 Expected<DWARFLocationExpressionsVector> OriginalLocations =
2161 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
2163 if (!OriginalLocations) {
2165 Linker.reportWarning(
"Invalid location attribute ignored.", File);
2170 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
2171 DWARFLocationExpression LinkedExpression;
2173 if (CurExpression.Range) {
2175 LinkedExpression.Range = {
2176 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
2177 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
2181 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
2182 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
2183 CurLocAttr.RelocAdjustment);
2185 LinkedLocationExpressions.push_back(LinkedExpression);
2190 Unit, LinkedLocationExpressions, CurLocAttr, AddrPool))
2195 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
2201 for (
auto &V : Die.
values())
2202 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
2210Error DWARFLinker::DIECloner::emitDebugAddrSection(
2211 CompileUnit &Unit,
const uint16_t DwarfVersion)
const {
2216 if (DwarfVersion < 5)
2219 if (AddrPool.getValues().empty())
2222 MCSymbol *EndLabel =
Emitter->emitDwarfDebugAddrsHeader(Unit);
2224 dwarf::FormParams
FP = Unit.getOrigUnit().getFormParams();
2225 if (AddrOffset >
FP.getDwarfMaxOffset())
2229 patchAddrBase(*Unit.getOutputUnitDIE(), DIEInteger(AddrOffset));
2230 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),
2231 Unit.getOrigUnit().getAddressByteSize());
2232 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
2250 std::vector<TrackedRow> &Rows) {
2256 Seq.front().isStartSeqInOutput =
true;
2258 if (!Rows.empty() && Rows.back().Row.Address < Seq.front().Row.Address) {
2266 Rows, [=](
const TrackedRow &O) {
return O.Row.Address < Front; });
2275 Rows.insert(
InsertPoint + 1, Seq.begin() + 1, Seq.end());
2284 for (
auto &V : Die.
values())
2285 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2293void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2294 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2295 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2297 if (std::optional<uint64_t> MacroAttr =
2299 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2303 if (std::optional<uint64_t> MacroAttr =
2305 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2310Error DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2315 DWARFDie CUDie =
Unit.getOrigUnit().getUnitDIE();
2321 if (
auto *OutputDIE =
Unit.getOutputUnitDIE()) {
2323 dwarf::FormParams
FP =
Unit.getOrigUnit().getFormParams();
2324 if (StmtOffset >
FP.getDwarfMaxOffset())
2331 if (
const DWARFDebugLine::LineTable *LT =
2332 ObjFile.Dwarf->getLineTableForUnit(&
Unit.getOrigUnit())) {
2334 DWARFDebugLine::LineTable LineTable;
2337 LineTable.Prologue =
LT->Prologue;
2340 if (Linker.Options.Update) {
2341 LineTable.Rows =
LT->Rows;
2344 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2345 LineTable.Rows.clear();
2347 LineTable.Sequences =
LT->Sequences;
2349 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2353 std::vector<TrackedRow> InputRows;
2354 InputRows.reserve(
LT->Rows.size());
2355 for (
size_t i = 0; i <
LT->Rows.size(); i++)
2356 InputRows.emplace_back(TrackedRow{LT->Rows[i], i, false});
2359 std::vector<TrackedRow> OutputRows;
2360 OutputRows.reserve(InputRows.size());
2364 std::vector<TrackedRow> Seq;
2365 Seq.reserve(InputRows.size());
2367 const auto &FunctionRanges =
Unit.getFunctionRanges();
2368 std::optional<AddressRangeValuePair> CurrRange;
2381 for (
size_t i = 0; i < InputRows.size(); i++) {
2382 TrackedRow
TR = InputRows[i];
2389 if (!CurrRange || !CurrRange->Range.contains(
TR.Row.Address.Address)) {
2393 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2395 FunctionRanges.getRangeThatContains(
TR.Row.Address.Address);
2396 if (StopAddress != -1ULL && !Seq.empty()) {
2399 auto NextLine = Seq.back();
2400 NextLine.Row.Address.Address = StopAddress;
2401 NextLine.Row.EndSequence = 1;
2402 NextLine.Row.PrologueEnd = 0;
2403 NextLine.Row.BasicBlock = 0;
2404 NextLine.Row.EpilogueBegin = 0;
2405 Seq.push_back(NextLine);
2414 if (
TR.Row.EndSequence && Seq.empty())
2418 TR.Row.Address.Address += CurrRange->Value;
2421 if (
TR.Row.EndSequence)
2432 if (!OutputRows.empty()) {
2433 OutputRows[0].isStartSeqInOutput =
true;
2434 for (
size_t i = 1; i < OutputRows.size(); ++i)
2435 OutputRows[i].isStartSeqInOutput = OutputRows[i - 1].Row.EndSequence;
2439 LineTable.Rows.clear();
2440 LineTable.Rows.reserve(OutputRows.size());
2441 for (
auto &TR : OutputRows)
2442 LineTable.Rows.push_back(
TR.Row);
2446 std::vector<uint64_t> OutputRowOffsets;
2450 bool hasStmtSeq =
Unit.getStmtSeqListAttributes().size() > 0;
2451 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2453 hasStmtSeq ? &OutputRowOffsets :
nullptr);
2456 assert(OutputRowOffsets.size() == OutputRows.size() &&
2457 "must have an offset for each row");
2460 DenseMap<uint64_t, uint64_t> SeqOffToOrigRow;
2465 if (!
LT->Rows.empty())
2473 DenseMap<size_t, size_t> OrigRowToOutputRow;
2474 std::vector<size_t> OutputRowToSeqStart(OutputRows.size());
2476 size_t CurrentSeqStart = 0;
2477 for (
size_t i = 0; i < OutputRows.size(); ++i) {
2479 if (OutputRows[i].isStartSeqInOutput)
2480 CurrentSeqStart = i;
2481 OutputRowToSeqStart[i] = CurrentSeqStart;
2484 OrigRowToOutputRow[OutputRows[i].OriginalRowIndex] = i;
2489 for (
const auto &StmtSeq :
Unit.getStmtSeqListAttributes()) {
2490 uint64_t OrigStmtSeq = StmtSeq.get();
2492 auto OrigRowIter = SeqOffToOrigRow.find(OrigStmtSeq);
2494 Unit.getOrigUnit().getFormParams().getDwarfMaxOffset();
2498 if (OrigRowIter == SeqOffToOrigRow.end()) {
2499 StmtSeq.set(InvalidOffset);
2502 size_t OrigRowIndex = OrigRowIter->second;
2505 auto OutputRowIter = OrigRowToOutputRow.find(OrigRowIndex);
2506 if (OutputRowIter == OrigRowToOutputRow.end()) {
2508 StmtSeq.set(InvalidOffset);
2511 size_t OutputRowIdx = OutputRowIter->second;
2516 size_t SeqStartIdx = OutputRowToSeqStart[OutputRowIdx];
2520 assert(SeqStartIdx < OutputRowOffsets.size() &&
2521 "Sequence start index out of bounds");
2522 uint64_t NewStmtSeqOffset = OutputRowOffsets[SeqStartIdx];
2525 StmtSeq.set(NewStmtSeqOffset);
2531 Linker.reportWarning(
"Cann't load line table.", ObjFile);
2536void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2541 for (
const auto &Namespace :
Unit.getNamespaces())
2543 Unit.getStartOffset());
2545 for (
const auto &Pubname :
Unit.getPubnames())
2546 AppleNames.addName(Pubname.Name,
2547 Pubname.Die->getOffset() +
Unit.getStartOffset());
2549 for (
const auto &Pubtype :
Unit.getPubtypes())
2551 Pubtype.Name, Pubtype.Die->getOffset() +
Unit.getStartOffset(),
2552 Pubtype.Die->getTag(),
2555 Pubtype.QualifiedNameHash);
2557 for (
const auto &ObjC :
Unit.getObjC())
2558 AppleObjc.addName(ObjC.Name,
2559 ObjC.Die->getOffset() +
Unit.getStartOffset());
2562 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2563 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2566 for (
const auto &Namespace :
Unit.getNamespaces())
2571 Unit.getTag() == dwarf::DW_TAG_type_unit);
2572 for (
const auto &Pubname :
Unit.getPubnames())
2574 Pubname.Name, Pubname.Die->getOffset(),
2576 Pubname.Die->getTag(),
Unit.getUniqueID(),
2577 Unit.getTag() == dwarf::DW_TAG_type_unit);
2578 for (
const auto &Pubtype :
Unit.getPubtypes())
2580 Pubtype.Name, Pubtype.Die->getOffset(),
2582 Pubtype.Die->getTag(),
Unit.getUniqueID(),
2583 Unit.getTag() == dwarf::DW_TAG_type_unit);
2595void DWARFLinker::patchFrameInfoForObject(LinkContext &
Context) {
2596 DWARFContext &OrigDwarf = *
Context.File.Dwarf;
2597 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2599 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2604 for (std::unique_ptr<CompileUnit> &Unit :
Context.CompileUnits) {
2605 for (
auto CurRange :
Unit->getFunctionRanges())
2606 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
2609 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian());
2614 DenseMap<uint64_t, StringRef> LocalCIES;
2616 while (
Data.isValidOffset(InputOffset)) {
2617 uint64_t EntryOffset = InputOffset;
2618 uint32_t InitialLength =
Data.getU32(&InputOffset);
2619 if (InitialLength == 0xFFFFFFFF)
2620 return reportWarning(
"Dwarf64 bits no supported",
Context.File);
2622 uint32_t CIEId =
Data.getU32(&InputOffset);
2623 if (CIEId == 0xFFFFFFFF) {
2625 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2626 LocalCIES[EntryOffset] = CIEData;
2628 InputOffset += InitialLength - 4;
2632 uint64_t Loc =
Data.getUnsigned(&InputOffset, SrcAddrSize);
2638 std::optional<AddressRangeValuePair>
Range =
2639 AllUnitsRanges.getRangeThatContains(Loc);
2642 InputOffset = EntryOffset + InitialLength + 4;
2648 StringRef CIEData = LocalCIES[CIEId];
2649 if (CIEData.empty())
2650 return reportWarning(
"Inconsistent debug_frame content. Dropping.",
2655 auto IteratorInserted = EmittedCIEs.insert(
2656 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2658 if (IteratorInserted.second) {
2659 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2660 IteratorInserted.first->getValue() = LastCIEOffset;
2661 TheDwarfEmitter->emitCIE(CIEData);
2667 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2668 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2670 FrameData.substr(InputOffset, FDERemainingBytes));
2671 InputOffset += FDERemainingBytes;
2675uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2677 const DWARFFile &File,
2678 int ChildRecurseDepth) {
2679 const char *
Name =
nullptr;
2680 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2681 CompileUnit *CU = &
U;
2682 std::optional<DWARFFormValue>
Ref;
2688 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2689 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2697 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2699 OrigUnit = &RefCU->getOrigUnit();
2704 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2705 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2706 Name =
"(anonymous namespace)";
2708 if (CU->getInfo(Idx).ParentIdx == 0 ||
2710 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
2711 dwarf::DW_TAG_module)
2712 return djbHash(Name ? Name :
"",
djbHash(ChildRecurseDepth ?
"" :
"::"));
2714 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
2723 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2732 if (ObjectPrefixMap.empty())
2736 for (
const auto &Entry : ObjectPrefixMap)
2739 return p.str().str();
2746 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2748 if (PCMFile.empty())
2751 if (ObjectPrefixMap)
2752 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2757std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2758 std::string &PCMFile,
2759 LinkContext &Context,
2762 if (PCMFile.empty())
2763 return std::make_pair(
false,
false);
2768 std::string Name =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2771 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2773 return std::make_pair(
true,
true);
2776 if (!
Quiet && Options.Verbose) {
2778 outs() <<
"Found clang module reference " << PCMFile;
2781 auto Cached = ClangModules.find(PCMFile);
2782 if (Cached != ClangModules.end()) {
2786 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2787 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2788 "different version of the module ") +
2791 if (!
Quiet && Options.Verbose)
2792 outs() <<
" [cached].\n";
2793 return std::make_pair(
true,
true);
2796 return std::make_pair(
true,
false);
2799bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2804 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2805 std::pair<bool, bool> IsClangModuleRef =
2806 isClangModuleRef(CUDie, PCMFile,
Context, Indent,
false);
2808 if (!IsClangModuleRef.first)
2811 if (IsClangModuleRef.second)
2814 if (Options.Verbose)
2819 ClangModules.insert({PCMFile,
getDwoId(CUDie)});
2821 if (
Error E = loadClangModule(Loader, CUDie, PCMFile,
Context, OnCUDieLoaded,
2829Error DWARFLinker::loadClangModule(
2830 ObjFileLoaderTy Loader,
const DWARFDie &CUDie,
const std::string &PCMFile,
2834 std::string ModuleName =
dwarf::toString(CUDie.find(dwarf::DW_AT_name),
"");
2837 SmallString<0>
Path(Options.PrependPath);
2844 if (Loader ==
nullptr) {
2845 reportError(
"Could not load clang module: loader is not specified.\n",
2850 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2854 std::unique_ptr<CompileUnit>
Unit;
2855 for (
const auto &CU : ErrOrObj->Dwarf->compile_units()) {
2858 auto ChildCUDie = CU->getUnitDIE();
2861 if (!registerModuleReference(ChildCUDie,
Context, Loader, OnCUDieLoaded,
2866 ": Clang modules are expected to have exactly 1 compile unit.\n");
2867 reportError(Err,
Context.File);
2874 if (PCMDwoId != DwoId) {
2875 if (Options.Verbose)
2877 Twine(
"hash mismatch: this object file was built against a "
2878 "different version of the module ") +
2882 ClangModules[PCMFile] = PCMDwoId;
2886 Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR,
2892 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2897Expected<uint64_t> DWARFLinker::DIECloner::cloneAllCompileUnits(
2898 DWARFContext &DwarfContext,
const DWARFFile &File,
bool IsLittleEndian) {
2901 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2903 for (
auto &CurrentUnit : CompileUnits) {
2904 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2905 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2906 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2907 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2909 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2912 if (CurrentUnit->getInfo(0).Keep) {
2915 CurrentUnit->createOutputDIE();
2916 rememberUnitForMacroOffset(*CurrentUnit);
2917 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2918 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2921 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2925 if (
Error E = generateLineTableForUnit(*CurrentUnit))
2928 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2933 if (
Error E = Linker.generateUnitRanges(*CurrentUnit, File, AddrPool))
2936 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2937 SmallVectorImpl<uint8_t> &OutBytes,
2938 int64_t RelocAdjustment) {
2939 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2940 DataExtractor
Data(SrcBytes, IsLittleEndian);
2941 cloneExpression(
Data,
2942 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2943 OrigUnit.getFormParams().Format),
2944 File, *CurrentUnit, OutBytes, RelocAdjustment,
2947 if (
Error E = generateUnitLocations(*CurrentUnit, File, ProcessExpr))
2949 if (
Error E = emitDebugAddrSection(*CurrentUnit, DwarfVersion))
2958 Emitter->emitMacroTables(
File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2961 for (
auto &CurrentUnit : CompileUnits) {
2962 CurrentUnit->fixupForwardReferences();
2964 if (!CurrentUnit->getOutputUnitDIE())
2967 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2970 CurrentUnit->getStartOffset());
2971 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2972 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2974 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2978 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2981void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2982 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getLocSection().Data,
2984 TheDwarfEmitter->emitSectionContents(
2985 Dwarf.getDWARFObj().getRangesSection().Data,
2987 TheDwarfEmitter->emitSectionContents(
2989 TheDwarfEmitter->emitSectionContents(
Dwarf.getDWARFObj().getArangesSection(),
2991 TheDwarfEmitter->emitSectionContents(
2993 TheDwarfEmitter->emitSectionContents(
2994 Dwarf.getDWARFObj().getRnglistsSection().Data,
2996 TheDwarfEmitter->emitSectionContents(
2997 Dwarf.getDWARFObj().getLoclistsSection().Data,
3003 ObjectContexts.emplace_back(LinkContext(File));
3005 if (ObjectContexts.back().File.Dwarf) {
3006 for (
const std::unique_ptr<DWARFUnit> &
CU :
3007 ObjectContexts.back().File.Dwarf->compile_units()) {
3016 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
3023 assert((Options.TargetDWARFVersion != 0) &&
3024 "TargetDWARFVersion should be set");
3028 unsigned NumObjects = ObjectContexts.size();
3040 for (LinkContext &OptContext : ObjectContexts) {
3041 if (Options.Verbose)
3042 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
3044 if (!OptContext.File.Dwarf)
3047 if (Options.VerifyInputDWARF)
3048 verifyInput(OptContext.File);
3055 !OptContext.File.Addresses->hasValidRelocs()) {
3056 if (Options.Verbose)
3057 outs() <<
"No valid relocations found. Skipping.\n";
3061 OptContext.Skip =
true;
3066 if (!OptContext.File.Dwarf)
3070 if (!OptContext.File.Dwarf->types_section_units().empty()) {
3071 reportWarning(
"type units are not currently supported: file will "
3074 OptContext.Skip =
true;
3080 OptContext.CompileUnits.reserve(
3081 OptContext.File.Dwarf->getNumCompileUnits());
3082 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
3083 auto CUDie =
CU->getUnitDIE(
true);
3084 if (Options.Verbose) {
3085 outs() <<
"Input compilation unit:";
3088 DumpOpts.
Verbose = Options.Verbose;
3089 CUDie.dump(
outs(), 0, DumpOpts);
3093 for (
auto &
CU : OptContext.ModuleUnits) {
3094 if (
Error Err = cloneModuleUnit(OptContext,
CU, ODRContexts, DebugStrPool,
3095 DebugLineStrPool, StringOffsetPool))
3096 reportWarning(
toString(std::move(Err)),
CU.File);
3106 (TheDwarfEmitter ==
nullptr) ? 0
3107 : TheDwarfEmitter->getDebugInfoSectionSize();
3111 std::mutex ProcessedFilesMutex;
3112 std::condition_variable ProcessedFilesConditionVariable;
3113 BitVector ProcessedFiles(NumObjects,
false);
3117 auto AnalyzeLambda = [&](
size_t I) {
3118 auto &Context = ObjectContexts[
I];
3120 if (Context.Skip || !Context.File.Dwarf)
3123 for (
const auto &
CU : Context.File.Dwarf->compile_units()) {
3126 auto CUDie =
CU->getUnitDIE(
false);
3127 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
3130 !isClangModuleRef(CUDie, PCMFile, Context, 0,
true).first) {
3131 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
3132 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
3137 for (
auto &CurrentUnit : Context.CompileUnits) {
3138 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
3142 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
3143 ModulesEndOffset, Options.ParseableSwiftInterfaces,
3145 reportWarning(Warning, Context.File, &DIE);
3158 auto &OptContext = ObjectContexts[
I];
3159 if (OptContext.Skip || !OptContext.File.Dwarf)
3168 for (
auto &CurrentUnit : OptContext.CompileUnits)
3169 CurrentUnit->markEverythingAsKept();
3170 copyInvariantDebugSection(*OptContext.File.Dwarf);
3172 for (
auto &CurrentUnit : OptContext.CompileUnits) {
3173 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
3174 CurrentUnit->getOrigUnit().getUnitDIE(),
3175 OptContext.File, *CurrentUnit, 0);
3185 if (OptContext.File.Addresses->hasValidRelocs() ||
3187 SizeByObject[OptContext.File.FileName].Input =
3190 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
3191 OptContext.CompileUnits, Options.Update, DebugStrPool,
3192 DebugLineStrPool, StringOffsetPool)
3193 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
3194 OptContext.File.Dwarf->isLittleEndian());
3199 SizeByObject[OptContext.File.FileName].Output = *SizeOrErr;
3201 if ((TheDwarfEmitter !=
nullptr) && !OptContext.CompileUnits.empty() &&
3203 patchFrameInfoForObject(OptContext);
3206 cleanupAuxiliarryData(OptContext);
3209 auto EmitLambda = [&]() {
3211 if (TheDwarfEmitter !=
nullptr) {
3212 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
3213 TheDwarfEmitter->emitStrings(DebugStrPool);
3214 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.
getValues(),
3215 Options.TargetDWARFVersion);
3216 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
3218 switch (TableKind) {
3220 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
3221 TheDwarfEmitter->emitAppleNames(AppleNames);
3222 TheDwarfEmitter->emitAppleTypes(AppleTypes);
3223 TheDwarfEmitter->emitAppleObjc(AppleObjc);
3230 TheDwarfEmitter->emitDebugNames(DebugNames);
3237 auto AnalyzeAll = [&]() {
3238 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3241 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3242 ProcessedFiles.
set(
I);
3243 ProcessedFilesConditionVariable.notify_one();
3248 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3250 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
3251 if (!ProcessedFiles[
I]) {
3252 ProcessedFilesConditionVariable.wait(
3253 LockGuard, [&]() {
return ProcessedFiles[
I]; });
3269 if (Options.Threads == 1) {
3270 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
3280 Pool.
async(AnalyzeAll);
3281 Pool.
async(CloneAll, std::reference_wrapper<Error>(CE));
3288 if (Options.Statistics) {
3290 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
3291 for (
auto &
E : SizeByObject)
3292 Sorted.emplace_back(
E.first(),
E.second);
3294 return LHS.second.Output >
RHS.second.Output;
3297 auto ComputePercentange = [](int64_t
Input, int64_t Output) ->
float {
3298 const float Difference = Output -
Input;
3299 const float Sum =
Input + Output;
3302 return (Difference / (Sum / 2));
3305 int64_t InputTotal = 0;
3306 int64_t OutputTotal = 0;
3307 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
3310 outs() <<
".debug_info section size (in bytes)\n";
3311 outs() <<
"----------------------------------------------------------------"
3312 "---------------\n";
3313 outs() <<
"Filename Object "
3315 outs() <<
"----------------------------------------------------------------"
3316 "---------------\n";
3319 for (
auto &
E : Sorted) {
3320 InputTotal +=
E.second.Input;
3321 OutputTotal +=
E.second.Output;
3324 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
3327 outs() <<
"----------------------------------------------------------------"
3328 "---------------\n";
3330 ComputePercentange(InputTotal, OutputTotal));
3331 outs() <<
"----------------------------------------------------------------"
3332 "---------------\n\n";
3338Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3344 assert(Unit.Unit.get() !=
nullptr);
3346 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3351 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
3356 &ODRContexts.
getRoot(), ODRContexts, 0,
3357 Options.ParseableSwiftInterfaces,
3359 reportWarning(Warning, Context.File, &DIE);
3362 Unit.Unit->markEverythingAsKept();
3366 CompileUnits.emplace_back(std::move(Unit.Unit));
3369 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3370 Options.Update, DebugStrPool, DebugLineStrPool,
3372 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3373 Unit.File.Dwarf->isLittleEndian());
3379void DWARFLinker::verifyInput(
const DWARFFile &File) {
3386 if (
Options.InputVerificationHandler)
3387 Options.InputVerificationHandler(File, OS.str());
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE, int ChildRecurseDepth=0)
This file implements the BitVector class.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
dxil DXContainer Global Emitter
Provides ErrorOr<T> smart pointer.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
BitVector & set()
Set all bits in the bitvector.
void setChildrenFlag(bool hasChild)
value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V)
A structured debug information entry.
unsigned getAbbrevNumber() const
DIE & addChild(DIE *Child)
Add a child to the DIE.
LLVM_ABI DIEAbbrev generateAbbrev() const
Generate the abbreviation for this DIE.
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
void setAbbrevNumber(unsigned I)
Set the abbreviation number for this DIE.
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
void setOffset(unsigned O)
dwarf::Tag getTag() const
static LLVM_ABI std::optional< uint64_t > getDefiningParentDieOffset(const DIE &Die)
If Die has a non-null parent and the parent is not a declaration, return its offset.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
uint64_t getOffset() const
Get the absolute offset into the debug info or types section.
iterator_range< iterator > children() const
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Get the abbreviation declaration for this DIE.
dwarf::Tag getTag() const
LLVM_ABI std::optional< unsigned > getSubCode() const
uint64_t getEndOffset() const
Encoding
Size and signedness of expression operations' operands.
const Description & getDescription() const
uint64_t getRawOperand(unsigned Idx) const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
void wait() override
Blocking wait for all the tasks to execute first.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(uint64_t Val)
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
AddressesMap represents information about valid addresses used by debug information.
uint64_t constrainCodeRangeHighPC(uint64_t LowPC, uint64_t HighPC, int64_t Adjustment)
Constrains the end of the code range starting at LowPC, whose addresses shift by Adjustment in the ou...
This class represents DWARF information for source file and it's address map.
std::map< std::string, std::string > ObjectPrefixMapTy
function_ref< void(const DWARFUnit &Unit)> CompileUnitHandlerTy
AccelTableKind
The kind of accelerator tables to be emitted.
@ DebugNames
.debug_names.
@ Apple
.apple_names, .apple_namespaces, .apple_types, .apple_objc.
@ Pub
.debug_pubnames, .debug_pubtypes
std::map< std::string, std::string > SwiftInterfacesMapTy
std::function< ErrorOr< DWARFFile & >( StringRef ContainerName, StringRef Path)> ObjFileLoaderTy
const SmallVector< T > & getValues() const
Stores all information relating to a compile unit, be it in its original instance in the object file ...
void addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader=nullptr, CompileUnitHandlerTy OnCUDieLoaded=[](const DWARFUnit &) {}) override
Add object file to be linked.
Error link() override
Link debug info for added objFiles. Object files are linked all together.
This class gives a tree-like API to the DenseMap that stores the DeclContext objects.
LLVM_ABI PointerIntPair< DeclContext *, 1 > getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, CompileUnit &Unit, bool InClangModule)
Get the child of Context described by DIE in Unit.
A DeclContext is a named program scope that is used for ODR uniquing of types.
void setDefinedInClangModule(bool Val)
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
LLVM_ABI StringRef FormEncodingString(unsigned Encoding)
LLVM_ABI StringRef FormatString(DwarfFormat Format)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallVector< PatchLocation > RngListAttributesTy
std::vector< std::unique_ptr< CompileUnit > > UnitListTy
IndexedValuesMap< uint64_t > DebugDieValuePool
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
SmallVector< PatchLocation > LocListAttributesTy
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
LLVM_ABI void buildStmtSeqOffsetToFirstRowIndex(const DWARFDebugLine::LineTable <, ArrayRef< uint64_t > SortedStmtSeqOffsets, DenseMap< uint64_t, uint64_t > &SeqOffToFirstRow)
Build a map from an input DW_AT_LLVM_stmt_sequence byte offset to the first-row index (in LT....
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
bool isInToolchainDir(StringRef Path)
Make a best effort to determine whether Path is inside a toolchain.
bool isTlsAddressOp(uint8_t O)
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
LLVM_ABI bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, uint16_t DwarfVersion)
Check whether specified Form belongs to the FC class.
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
@ DW_FLAG_type_implementation
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
LLVM_ABI bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
LLVM_ABI bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
constexpr bool IsLittleEndianHost
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
static void verifyKeepChain(CompileUnit &CU)
Verify the keep chain by looking for DIEs that are kept but who's parent isn't.
static void updateRefIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &RefInfo)
Helper that updates the completeness of the current DIE based on the completeness of the DIEs it refe...
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
static void patchAddrBase(DIE &Die, DIEInteger Offset)
auto unique(Range &&R, Predicate P)
static std::string remapPath(StringRef Path, const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap)
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
static CompileUnit * getUnitForOffset(const UnitListTy &Units, uint64_t Offset)
Similar to DWARFUnitSection::getUnitForOffset(), but returning our CompileUnit object instead.
static void insertLineSequence(std::vector< TrackedRow > &Seq, std::vector< TrackedRow > &Rows)
Insert the new line info sequence Seq into the current set of already linked line info Rows.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
static void resolveRelativeObjectPath(SmallVectorImpl< char > &Buf, DWARFDie CU)
Resolve the relative path to a build artifact referenced by DWARF by applying DW_AT_comp_dir.
static std::string getPCMFile(const DWARFDie &CUDie, const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
static bool shouldSkipAttribute(bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, bool SkipPC)
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
static uint64_t getDebugInfoSize(DWARFContext &Dwarf)
Compute the total size of the debug info.
static bool isTypeTag(uint16_t Tag)
@ Dwarf
DWARF v5 .debug_names.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI std::optional< StringRef > StripTemplateParameters(StringRef Name)
If Name is the name of a templated function that includes template parameters, returns a substring of...
static uint64_t getDwoId(const DWARFDie &CUDie)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, uint64_t ModulesEndOffset)
@ Success
The lock was released successfully.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
static void updateChildIncompleteness(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)
Helper that updates the completeness of the current DIE based on the completeness of one of its child...
SingleThreadExecutor DefaultThreadPool
DWARFExpression::Operation Op
static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
LLVM_ABI std::optional< ObjCSelectorNames > getObjCNamesIfSelector(StringRef Name)
If Name is the AT_name of a DIE which refers to an Objective-C selector, returns an instance of ObjCS...
static void analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, DeclContext *CurrentDeclContext, DeclContextTree &Contexts, uint64_t ModulesEndOffset, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Recursive helper to build the global DeclContext information and gather the child->parent relationshi...
static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag)
StrongType< NonRelocatableStringpool, OffsetsTag > OffsetsStringPool
static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU)
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
static void analyzeImportedModule(const DWARFDie &DIE, CompileUnit &CU, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
ContextWorklistItemType
The distinct types of work performed by the work loop in analyzeContextInfo.
static uint64_t constrainHighPC(const DWARFDie &InputDIE, uint64_t HighPC, bool IsLength, int64_t PCOffset, AddressesMap &Addresses)
Returns InputDIE's DW_AT_high_pc value HighPC, constrained so the code range it ends stays clear of t...
void consumeError(Error Err)
Consume a Error without doing anything.
static bool isODRAttribute(uint16_t Attr)
static void patchStmtList(DIE &Die, DIEInteger Offset)
static void constructSeqOffsettoOrigRowMapping(CompileUnit &Unit, const DWARFDebugLine::LineTable <, DenseMap< uint64_t, uint64_t > &SeqOffToOrigRow)
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
int64_t LinkedOffsetFixupVal
uint64_t InputAttrStartOffset
uint64_t InputAttrEndOffset
A broken link in the keep chain.
BrokenLink(DWARFDie Parent, DWARFDie Child)
This class represents an item in the work list.
CompileUnit::DIEInfo * OtherInfo
ContextWorklistItem(DWARFDie Die, DeclContext *Context, unsigned ParentIdx, bool InImportedModule)
ContextWorklistItemType Type
ContextWorklistItem(DWARFDie Die, ContextWorklistItemType T, CompileUnit::DIEInfo *OtherInfo=nullptr)
Container for dump options that control which debug information will be dumped.
DIDumpOptions noImplicitRecursion() const
Return the options with RecurseDepth set to 0 unless explicitly required.
unsigned ChildRecurseDepth
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Standard .debug_line state machine structure.
SmallVector< Encoding > Op
Encoding for Op operands.
Hold the input and output of the debug info size in bytes.
A helper struct to help keep track of the association between the input and output rows during line t...
Information gathered about a DIE in the object file.
bool Prune
Is this a pure forward declaration we can strip?
bool Incomplete
Does DIE transitively refer an incomplete decl?