48 for (
auto &Unit :
Dwarf.compile_units()) {
49 Size += Unit->getLength();
59 return LHS <
RHS->getOrigUnit().getNextUnitOffset();
61 return CU != Units.end() ?
CU->get() :
nullptr;
67DWARFDie DWARFLinker::resolveDIEReference(
const DWARFFile &File,
69 const DWARFFormValue &RefValue,
71 CompileUnit *&RefCU) {
73 uint64_t RefOffset = *RefValue.getAsReference();
75 if (
const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
82 reportWarning(
"could not find referenced DIE", File, &DIE);
92 case dwarf::DW_AT_type:
93 case dwarf::DW_AT_containing_type:
94 case dwarf::DW_AT_specification:
95 case dwarf::DW_AT_abstract_origin:
96 case dwarf::DW_AT_import:
104 case dwarf::DW_TAG_array_type:
105 case dwarf::DW_TAG_class_type:
106 case dwarf::DW_TAG_enumeration_type:
107 case dwarf::DW_TAG_pointer_type:
108 case dwarf::DW_TAG_reference_type:
109 case dwarf::DW_TAG_string_type:
110 case dwarf::DW_TAG_structure_type:
111 case dwarf::DW_TAG_subroutine_type:
112 case dwarf::DW_TAG_typedef:
113 case dwarf::DW_TAG_union_type:
114 case dwarf::DW_TAG_ptr_to_member_type:
115 case dwarf::DW_TAG_set_type:
116 case dwarf::DW_TAG_subrange_type:
117 case dwarf::DW_TAG_base_type:
118 case dwarf::DW_TAG_const_type:
119 case dwarf::DW_TAG_constant:
120 case dwarf::DW_TAG_file_type:
121 case dwarf::DW_TAG_namelist:
122 case dwarf::DW_TAG_packed_type:
123 case dwarf::DW_TAG_volatile_type:
124 case dwarf::DW_TAG_restrict_type:
125 case dwarf::DW_TAG_atomic_type:
126 case dwarf::DW_TAG_interface_type:
127 case dwarf::DW_TAG_unspecified_type:
128 case dwarf::DW_TAG_shared_type:
129 case dwarf::DW_TAG_immutable_type:
148 if (!
Name.endswith(
">") ||
Name.count(
"<") == 0 ||
Name.endswith(
"<=>"))
152 size_t NumLeftAnglesToSkip = 1;
155 NumLeftAnglesToSkip +=
Name.count(
"<=>");
157 size_t RightAngleCount =
Name.count(
'>');
158 size_t LeftAngleCount =
Name.count(
'<');
162 if (LeftAngleCount > RightAngleCount)
163 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
165 size_t StartOfTemplate = 0;
166 while (NumLeftAnglesToSkip--)
167 StartOfTemplate =
Name.find(
'<', StartOfTemplate) + 1;
169 return Name.substr(0, StartOfTemplate - 1);
172bool DWARFLinker::DIECloner::getDIENames(
const DWARFDie &Die,
173 AttributesInfo &
Info,
175 bool StripTemplate) {
179 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
182 if (!
Info.MangledName)
183 if (
const char *MangledName = Die.getLinkageName())
184 Info.MangledName = StringPool.getEntry(MangledName);
187 if (
const char *
Name = Die.getShortName())
188 Info.Name = StringPool.getEntry(
Name);
190 if (!
Info.MangledName)
193 if (StripTemplate &&
Info.Name &&
Info.MangledName !=
Info.Name) {
194 StringRef
Name =
Info.Name.getString();
196 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
199 return Info.Name ||
Info.MangledName;
213 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
214 if (
CU.getLanguage() != dwarf::DW_LANG_Swift)
217 if (!ParseableSwiftInterfaces)
221 if (!Path.endswith(
".swiftinterface"))
226 SysRoot =
CU.getSysRoot();
227 if (!SysRoot.
empty() && Path.startswith(SysRoot))
229 std::optional<const char *>
Name =
233 auto &Entry = (*ParseableSwiftInterfaces)[*
Name];
235 DWARFDie CUDie =
CU.getOrigUnit().getUnitDIE();
240 if (!Entry.empty() && Entry != ResolvedPath)
241 ReportWarning(
Twine(
"Conflicting parseable interfaces for Swift Module ") +
242 *
Name +
": " + Entry +
" and " + Path,
244 Entry = std::string(ResolvedPath.
str());
287 Info.Prune &= (Die.
getTag() == dwarf::DW_TAG_module) ||
293 if (ModulesEndOffset == 0)
294 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset();
296 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset() > 0 &&
297 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
320 std::function<
void(
const Twine &,
const DWARFDie &)> ReportWarning) {
322 std::vector<ContextWorklistItem> Worklist;
323 Worklist.emplace_back(
DIE, CurrentDeclContext, ParentIdx,
false);
325 while (!Worklist.empty()) {
329 switch (Current.
Type) {
340 unsigned Idx =
CU.getOrigUnit().getDIEIndex(Current.
Die);
355 if (Current.
Die.
getTag() == dwarf::DW_TAG_module &&
358 CU.getClangModuleName()) {
366 if (
CU.hasODR() ||
Info.InModuleScope) {
370 Current.
Context = PtrInvalidPair.getPointer();
372 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
374 Info.Ctxt->setDefinedInClangModule(
Info.InModuleScope);
385 Worklist.emplace_back(
387 Worklist.emplace_back(Child, Current.
Context,
Idx,
397 case dwarf::DW_TAG_class_type:
398 case dwarf::DW_TAG_common_block:
399 case dwarf::DW_TAG_lexical_block:
400 case dwarf::DW_TAG_structure_type:
401 case dwarf::DW_TAG_subprogram:
402 case dwarf::DW_TAG_subroutine_type:
403 case dwarf::DW_TAG_union_type:
409void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
412 for (DIEBlock *
I : DIEBlocks)
414 for (DIELoc *
I : DIELocs)
424unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
426 CompileUnit::DIEInfo &MyInfo,
428 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
431 if (!(
Flags & TF_InFunctionScope) &&
432 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
433 MyInfo.InDebugMap =
true;
434 return Flags | TF_Keep;
442 const bool HasLiveMemoryLocation = RelocMgr.isLiveVariable(DIE, MyInfo);
443 if (!HasLiveMemoryLocation || ((
Flags & TF_InFunctionScope) &&
447 if (Options.Verbose) {
448 outs() <<
"Keeping variable DIE:";
449 DIDumpOptions DumpOpts;
450 DumpOpts.ChildRecurseDepth = 0;
451 DumpOpts.Verbose = Options.Verbose;
452 DIE.dump(
outs(), 8 , DumpOpts);
455 return Flags | TF_Keep;
460unsigned DWARFLinker::shouldKeepSubprogramDIE(
461 AddressesMap &RelocMgr,
RangesTy &Ranges,
const DWARFDie &DIE,
462 const DWARFFile &File, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
464 Flags |= TF_InFunctionScope;
470 assert(LowPc &&
"low_pc attribute is not an address.");
471 if (!RelocMgr.isLiveSubprogram(DIE, MyInfo))
474 if (Options.Verbose) {
475 outs() <<
"Keeping subprogram DIE:";
476 DIDumpOptions DumpOpts;
477 DumpOpts.ChildRecurseDepth = 0;
478 DumpOpts.Verbose = Options.Verbose;
479 DIE.dump(
outs(), 8 , DumpOpts);
482 if (DIE.getTag() == dwarf::DW_TAG_label) {
483 if (Unit.hasLabelAt(*LowPc))
486 DWARFUnit &OrigUnit = Unit.getOrigUnit();
494 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
495 return Flags | TF_Keep;
500 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
502 reportWarning(
"Function without high_pc. Range will be discarded.\n", File,
506 if (*LowPc > *HighPc) {
507 reportWarning(
"low_pc greater than high_pc. Range will be discarded.\n",
513 Ranges.insert({*LowPc, *HighPc}, MyInfo.AddrAdjust);
514 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
520unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr,
RangesTy &Ranges,
521 const DWARFDie &DIE,
const DWARFFile &File,
523 CompileUnit::DIEInfo &MyInfo,
525 switch (DIE.getTag()) {
526 case dwarf::DW_TAG_constant:
527 case dwarf::DW_TAG_variable:
528 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo,
Flags);
529 case dwarf::DW_TAG_subprogram:
530 case dwarf::DW_TAG_label:
531 return shouldKeepSubprogramDIE(RelocMgr, Ranges, DIE, File, Unit, MyInfo,
533 case dwarf::DW_TAG_base_type:
536 case dwarf::DW_TAG_imported_module:
537 case dwarf::DW_TAG_imported_declaration:
538 case dwarf::DW_TAG_imported_unit:
540 return Flags | TF_Keep;
554 case dwarf::DW_TAG_structure_type:
555 case dwarf::DW_TAG_class_type:
556 case dwarf::DW_TAG_union_type:
574 case dwarf::DW_TAG_typedef:
575 case dwarf::DW_TAG_member:
576 case dwarf::DW_TAG_reference_type:
577 case dwarf::DW_TAG_ptr_to_member_type:
578 case dwarf::DW_TAG_pointer_type:
595void DWARFLinker::lookForChildDIEsToKeep(
596 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
597 SmallVectorImpl<WorklistItem> &Worklist) {
604 Flags &= ~DWARFLinker::TF_ParentWalk;
608 if (!Die.hasChildren() || (
Flags & DWARFLinker::TF_ParentWalk))
613 for (
auto Child :
reverse(Die.children())) {
616 CompileUnit::DIEInfo &ChildInfo =
CU.getInfo(Child);
617 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateChildIncompleteness,
619 Worklist.emplace_back(Child,
CU,
Flags);
626 if (!
Info.Ctxt || (Die.
getTag() == dwarf::DW_TAG_namespace))
629 if (!
CU.hasODR() && !
Info.InModuleScope)
632 return !
Info.Incomplete &&
Info.Ctxt !=
CU.getInfo(
Info.ParentIdx).Ctxt;
635void DWARFLinker::markODRCanonicalDie(
const DWARFDie &Die, CompileUnit &
CU) {
636 CompileUnit::DIEInfo &
Info =
CU.getInfo(Die);
638 Info.ODRMarkingDone =
true;
640 !
Info.Ctxt->hasCanonicalDIE())
641 Info.Ctxt->setHasCanonicalDIE();
646void DWARFLinker::lookForRefDIEsToKeep(
647 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
648 const UnitListTy &Units,
const DWARFFile &File,
649 SmallVectorImpl<WorklistItem> &Worklist) {
650 bool UseOdr = (
Flags & DWARFLinker::TF_DependencyWalk)
651 ? (
Flags & DWARFLinker::TF_ODR)
653 DWARFUnit &Unit =
CU.getOrigUnit();
654 DWARFDataExtractor
Data = Unit.getDebugInfoExtractor();
655 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
658 SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs;
659 for (
const auto &AttrSpec : Abbrev->attributes()) {
660 DWARFFormValue Val(AttrSpec.Form);
662 AttrSpec.Attr == dwarf::DW_AT_sibling) {
664 Unit.getFormParams());
668 Val.extractValue(
Data, &
Offset, Unit.getFormParams(), &Unit);
669 CompileUnit *ReferencedCU;
671 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
672 CompileUnit::DIEInfo &
Info = ReferencedCU->getInfo(RefDie);
683 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
685 Info.Ctxt->hasCanonicalDIE())
690 Info.Ctxt->hasCanonicalDIE()))
692 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
696 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
700 for (
auto &
P :
reverse(ReferencedDIEs)) {
703 CompileUnit::DIEInfo &
Info =
P.second.getInfo(
P.first);
704 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateRefIncompleteness,
706 Worklist.emplace_back(
P.first,
P.second,
707 DWARFLinker::TF_Keep |
708 DWARFLinker::TF_DependencyWalk | ODRFlag);
713void DWARFLinker::lookForParentDIEsToKeep(
714 unsigned AncestorIdx, CompileUnit &
CU,
unsigned Flags,
715 SmallVectorImpl<WorklistItem> &Worklist) {
717 if (
CU.getInfo(AncestorIdx).Keep)
720 DWARFUnit &Unit =
CU.getOrigUnit();
721 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);
722 Worklist.emplace_back(
CU.getInfo(AncestorIdx).ParentIdx,
CU,
Flags);
723 Worklist.emplace_back(ParentDIE,
CU,
Flags);
751void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
753 const DWARFDie &Die,
const DWARFFile &File,
754 CompileUnit &Cu,
unsigned Flags) {
756 SmallVector<WorklistItem, 4> Worklist;
757 Worklist.emplace_back(Die, Cu,
Flags);
759 while (!Worklist.empty()) {
760 WorklistItem Current = Worklist.pop_back_val();
763 switch (Current.Type) {
764 case WorklistItemType::UpdateChildIncompleteness:
767 case WorklistItemType::UpdateRefIncompleteness:
770 case WorklistItemType::LookForChildDIEsToKeep:
771 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
773 case WorklistItemType::LookForRefDIEsToKeep:
774 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
777 case WorklistItemType::LookForParentDIEsToKeep:
778 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
781 case WorklistItemType::MarkODRCanonicalDie:
782 markODRCanonicalDie(Current.Die, Current.CU);
784 case WorklistItemType::LookForDIEsToKeep:
788 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
789 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(
Idx);
794 if (Current.Flags & TF_DependencyWalk)
795 MyInfo.Prune =
false;
802 bool AlreadyKept = MyInfo.Keep;
803 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
808 if (!(Current.Flags & TF_DependencyWalk))
809 Current.Flags = shouldKeepDIE(AddressesMap, Ranges, Current.Die, File,
810 Current.CU, MyInfo, Current.Flags);
815 if (!(Current.Flags & TF_DependencyWalk) ||
816 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
817 if (Current.CU.hasODR() || MyInfo.InModuleScope)
818 Worklist.emplace_back(Current.Die, Current.CU,
819 WorklistItemType::MarkODRCanonicalDie);
825 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
826 WorklistItemType::LookForChildDIEsToKeep);
828 if (AlreadyKept || !(Current.Flags & TF_Keep))
837 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
838 Current.Die.getTag() != dwarf::DW_TAG_member &&
844 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
845 WorklistItemType::LookForRefDIEsToKeep);
847 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
848 : Current.CU.hasODR();
849 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
850 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
853 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
869 std::vector<DWARFDie> Worklist;
870 Worklist.push_back(
CU.getOrigUnit().getUnitDIE());
873 std::vector<BrokenLink> BrokenLinks;
875 while (!Worklist.empty()) {
876 const DWARFDie Current = Worklist.back();
879 const bool CurrentDieIsKept =
CU.getInfo(Current).Keep;
882 Worklist.push_back(Child);
884 const bool ChildDieIsKept =
CU.getInfo(Child).Keep;
885 if (!CurrentDieIsKept && ChildDieIsKept)
886 BrokenLinks.emplace_back(Current, Child);
890 if (!BrokenLinks.empty()) {
893 "Found invalid link in keep chain between {0:x} and {1:x}\n",
894 Link.Parent.getOffset(), Link.Child.getOffset());
897 Link.Parent.dump(
errs(), 0, {});
898 CU.getInfo(Link.Parent).dump();
901 Link.Child.dump(
errs(), 2, {});
902 CU.getInfo(Link.Child).dump();
915void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
920 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(
ID, InsertToken);
925 Abbrev.setNumber(InSet->getNumber());
928 Abbreviations.push_back(
929 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
930 for (
const auto &Attr : Abbrev.getData())
931 Abbreviations.back()->AddAttribute(Attr);
932 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
934 Abbrev.setNumber(Abbreviations.size());
935 Abbreviations.back()->setNumber(Abbreviations.size());
939unsigned DWARFLinker::DIECloner::cloneStringAttribute(
940 DIE &Die, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
947 auto StringEntry = StringPool.getEntry(*
String);
950 if (AttrSpec.Attr == dwarf::DW_AT_name)
951 Info.Name = StringEntry;
952 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
953 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
954 Info.MangledName = StringEntry;
956 Die.addValue(DIEAlloc,
dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp,
957 DIEInteger(StringEntry.getOffset()));
962unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
963 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
964 unsigned AttrSize,
const DWARFFormValue &Val,
const DWARFFile &File,
966 const DWARFUnit &
U = Unit.getOrigUnit();
969 DIE *NewRefDie =
nullptr;
970 CompileUnit *RefUnit =
nullptr;
973 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
976 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
979 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
984 RefInfo.Ctxt->getCanonicalDIEOffset()) {
985 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
986 "Offset to canonical die is set, but context is not marked");
987 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
989 dwarf::DW_FORM_ref_addr, Attr);
990 return U.getRefAddrByteSize();
993 if (!RefInfo.Clone) {
996 RefInfo.UnclonedReference =
true;
999 NewRefDie = RefInfo.Clone;
1001 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1009 if (
Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1012 RefUnit->getStartOffset() + NewRefDie->getOffset();
1013 Attr = NewRefOffset;
1015 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));
1019 Unit.noteForwardReference(
1020 NewRefDie, RefUnit, RefInfo.Ctxt,
1022 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
1024 return U.getRefAddrByteSize();
1028 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1033void DWARFLinker::DIECloner::cloneExpression(
1034 DataExtractor &
Data, DWARFExpression Expression,
const DWARFFile &File,
1035 CompileUnit &Unit, SmallVectorImpl<uint8_t> &
OutputBuffer) {
1039 for (
auto &Op : Expression) {
1040 auto Description =
Op.getDescription();
1043 auto Op0 = Description.Op[0];
1044 auto Op1 = Description.Op[1];
1045 if ((Op0 == Encoding::BaseTypeRef && Op1 != Encoding::SizeNA) ||
1046 (Op1 == Encoding::BaseTypeRef && Op0 != Encoding::Size1))
1047 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
1049 if ((Op0 == Encoding::BaseTypeRef && Op1 == Encoding::SizeNA) ||
1050 (Op1 == Encoding::BaseTypeRef && Op0 == Encoding::Size1)) {
1052 assert(OpOffset <
Op.getEndOffset());
1053 uint32_t ULEBsize =
Op.getEndOffset() - OpOffset - 1;
1059 if (Op1 == Encoding::SizeNA) {
1060 RefOffset =
Op.getRawOperand(0);
1063 RefOffset =
Op.getRawOperand(1);
1069 if (RefOffset > 0 ||
Op.getCode() != dwarf::DW_OP_convert) {
1070 RefOffset += Unit.getOrigUnit().getOffset();
1071 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
1072 CompileUnit::DIEInfo &
Info = Unit.getInfo(RefDie);
1073 if (DIE *Clone =
Info.Clone)
1074 Offset = Clone->getOffset();
1076 Linker.reportWarning(
1077 "base type ref doesn't point to DW_TAG_base_type.", File);
1081 if (RealSize > ULEBsize) {
1084 Linker.reportWarning(
"base type ref doesn't fit.", File);
1086 assert(RealSize == ULEBsize &&
"padding failed");
1087 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1088 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1091 StringRef Bytes =
Data.getData().slice(OpOffset,
Op.getEndOffset());
1094 OpOffset =
Op.getEndOffset();
1098unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1099 DIE &Die,
const DWARFFile &File, CompileUnit &Unit, AttributeSpec AttrSpec,
1100 const DWARFFormValue &Val,
unsigned AttrSize,
bool IsLittleEndian) {
1103 DIELoc *Loc =
nullptr;
1104 DIEBlock *
Block =
nullptr;
1105 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1106 Loc =
new (DIEAlloc) DIELoc;
1107 Linker.DIELocs.push_back(Loc);
1109 Block =
new (DIEAlloc) DIEBlock;
1110 Linker.DIEBlocks.push_back(
Block);
1112 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1113 :
static_cast<DIEValueList *
>(
Block);
1124 SmallVector<uint8_t, 32> Buffer;
1125 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1129 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1130 DataExtractor
Data(StringRef((
const char *)Bytes.data(), Bytes.size()),
1131 IsLittleEndian, OrigUnit.getAddressByteSize());
1132 DWARFExpression Expr(
Data, OrigUnit.getAddressByteSize(),
1133 OrigUnit.getFormParams().Format);
1134 cloneExpression(
Data, Expr, File, Unit, Buffer);
1137 for (
auto Byte : Bytes)
1139 dwarf::DW_FORM_data1, DIEInteger(Byte));
1145 Loc->setSize(Bytes.size());
1147 Block->setSize(Bytes.size());
1149 Die.addValue(DIEAlloc, Value);
1153unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1154 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1155 unsigned AttrSize,
const DWARFFormValue &Val,
const CompileUnit &Unit,
1156 AttributesInfo &
Info) {
1157 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1158 Info.HasLowPc =
true;
1162 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1178 std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
1182 std::optional<uint64_t>
Addr = AddrAttribute->getAsAddress();
1184 Linker.reportWarning(
"Cann't read address attribute value.", ObjFile);
1188 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1189 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1190 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
1194 }
else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1195 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1196 if (
uint64_t HighPc = Unit.getHighPc())
1204 switch (AttrSpec.Form) {
1205 case dwarf::DW_FORM_addrx:
1206 case dwarf::DW_FORM_addrx1:
1207 case dwarf::DW_FORM_addrx2:
1208 case dwarf::DW_FORM_addrx3:
1209 case dwarf::DW_FORM_addrx4: {
1212 AttrSpec.Form = dwarf::DW_FORM_addr;
1221 AttrSpec.Form, DIEInteger(*
Addr));
1222 return Unit.getOrigUnit().getAddressByteSize();
1225unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1226 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1227 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1228 unsigned AttrSize, AttributesInfo &
Info) {
1233 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1234 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1235 const DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacinfo();
1241 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1242 if (std::optional<uint64_t>
Offset = Val.getAsSectionOffset()) {
1243 const DWARFDebugMacro *
Macro =
File.Dwarf->getDebugMacro();
1250 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1251 Value = *OptionalValue;
1252 else if (
auto OptionalValue = Val.getAsSignedConstant())
1253 Value = *OptionalValue;
1254 else if (
auto OptionalValue = Val.getAsSectionOffset())
1255 Value = *OptionalValue;
1257 Linker.reportWarning(
1258 "Unsupported scalar attribute form. Dropping attribute.", File,
1262 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1263 Info.IsDeclaration =
true;
1265 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1274 [[maybe_unused]]
dwarf::Form OriginalForm = AttrSpec.Form;
1275 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1279 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1281 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1285 std::optional<uint64_t>
Offset =
1286 Unit.getOrigUnit().getRnglistOffset(*
Index);
1288 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1294 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1295 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1296 }
else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1300 std::optional<uint64_t>
Index = Val.getAsSectionOffset();
1302 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1306 std::optional<uint64_t>
Offset =
1307 Unit.getOrigUnit().getLoclistOffset(*
Index);
1309 Linker.reportWarning(
"Cannot read the attribute. Dropping.", File,
1315 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1316 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1317 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1318 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1319 std::optional<uint64_t> LowPC = Unit.getLowPc();
1323 Value = Unit.getHighPc() - *LowPC;
1324 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1325 Value = *Val.getAsSectionOffset();
1326 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1327 Value = *Val.getAsSignedConstant();
1328 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1329 Value = *OptionalValue;
1331 Linker.reportWarning(
1332 "Unsupported scalar attribute form. Dropping attribute.", File,
1337 PatchLocation Patch =
1340 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1341 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1342 Unit.noteRangeAttribute(Die, Patch);
1343 Info.HasRanges =
true;
1347 Unit.getOrigUnit().getVersion())) {
1348 Unit.noteLocationAttribute(Patch,
Info.PCOffset);
1349 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1350 Info.IsDeclaration =
true;
1353 assert((
Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1354 "Unhandled DW_FORM_rnglistx attribute");
1362unsigned DWARFLinker::DIECloner::cloneAttribute(
1363 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1365 const AttributeSpec AttrSpec,
unsigned AttrSize, AttributesInfo &
Info,
1366 bool IsLittleEndian) {
1367 const DWARFUnit &
U = Unit.getOrigUnit();
1369 switch (AttrSpec.Form) {
1370 case dwarf::DW_FORM_strp:
1371 case dwarf::DW_FORM_string:
1372 case dwarf::DW_FORM_strx:
1373 case dwarf::DW_FORM_strx1:
1374 case dwarf::DW_FORM_strx2:
1375 case dwarf::DW_FORM_strx3:
1376 case dwarf::DW_FORM_strx4:
1377 return cloneStringAttribute(Die, AttrSpec, Val, U, StringPool,
Info);
1378 case dwarf::DW_FORM_ref_addr:
1379 case dwarf::DW_FORM_ref1:
1380 case dwarf::DW_FORM_ref2:
1381 case dwarf::DW_FORM_ref4:
1382 case dwarf::DW_FORM_ref8:
1383 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1385 case dwarf::DW_FORM_block:
1386 case dwarf::DW_FORM_block1:
1387 case dwarf::DW_FORM_block2:
1388 case dwarf::DW_FORM_block4:
1389 case dwarf::DW_FORM_exprloc:
1390 return cloneBlockAttribute(Die, File, Unit, AttrSpec, Val, AttrSize,
1392 case dwarf::DW_FORM_addr:
1393 case dwarf::DW_FORM_addrx:
1394 case dwarf::DW_FORM_addrx1:
1395 case dwarf::DW_FORM_addrx2:
1396 case dwarf::DW_FORM_addrx3:
1397 case dwarf::DW_FORM_addrx4:
1398 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1400 case dwarf::DW_FORM_data1:
1401 case dwarf::DW_FORM_data2:
1402 case dwarf::DW_FORM_data4:
1403 case dwarf::DW_FORM_data8:
1404 case dwarf::DW_FORM_udata:
1405 case dwarf::DW_FORM_sdata:
1406 case dwarf::DW_FORM_sec_offset:
1407 case dwarf::DW_FORM_flag:
1408 case dwarf::DW_FORM_flag_present:
1409 case dwarf::DW_FORM_rnglistx:
1410 case dwarf::DW_FORM_loclistx:
1411 case dwarf::DW_FORM_implicit_const:
1412 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1415 Linker.reportWarning(
"Unsupported attribute form " +
1417 " in cloneAttribute. Dropping.",
1425 return Name.size() > 2 && (
Name[0] ==
'-' ||
Name[0] ==
'+') &&
1429void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1431 DwarfStringPoolEntryRef
Name,
1433 bool SkipPubSection) {
1437 StringRef ClassNameStart(
Name.getString().drop_front(2));
1438 size_t FirstSpace = ClassNameStart.find(
' ');
1442 StringRef SelectorStart(ClassNameStart.data() + FirstSpace + 1);
1443 if (!SelectorStart.size())
1446 StringRef Selector(SelectorStart.data(), SelectorStart.size() - 1);
1447 Unit.addNameAccelerator(Die, StringPool.getEntry(Selector), SkipPubSection);
1451 StringRef ClassName(ClassNameStart.data(), FirstSpace);
1452 Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassName), SkipPubSection);
1454 if (ClassName[ClassName.size() - 1] ==
')') {
1455 size_t OpenParens = ClassName.find(
'(');
1457 StringRef ClassNameNoCategory(ClassName.data(), OpenParens);
1458 Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassNameNoCategory),
1461 std::string MethodNameNoCategory(
Name.getString().data(), OpenParens + 2);
1464 MethodNameNoCategory.append(std::string(SelectorStart));
1465 Unit.addNameAccelerator(Die, StringPool.getEntry(MethodNameNoCategory),
1473 uint16_t Tag,
bool InDebugMap,
bool SkipPC,
bool InFunctionScope) {
1474 switch (AttrSpec.
Attr) {
1477 case dwarf::DW_AT_low_pc:
1478 case dwarf::DW_AT_high_pc:
1479 case dwarf::DW_AT_ranges:
1480 return !Update && SkipPC;
1481 case dwarf::DW_AT_addr_base:
1484 case dwarf::DW_AT_rnglists_base:
1490 case dwarf::DW_AT_str_offsets_base:
1493 case dwarf::DW_AT_loclists_base:
1499 case dwarf::DW_AT_location:
1500 case dwarf::DW_AT_frame_base:
1507 (SkipPC || (!InFunctionScope &&
Tag == dwarf::DW_TAG_variable &&
1513DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1514 const DWARFFile &File, CompileUnit &Unit,
1516 int64_t PCOffset,
uint32_t OutOffset,
1517 unsigned Flags,
bool IsLittleEndian,
1519 DWARFUnit &U = Unit.getOrigUnit();
1520 unsigned Idx = U.getDIEIndex(InputDIE);
1521 CompileUnit::DIEInfo &
Info = Unit.getInfo(
Idx);
1524 if (!Unit.getInfo(
Idx).Keep)
1528 assert(!(Die &&
Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1537 assert(Die->getTag() == InputDIE.getTag());
1538 Die->setOffset(OutOffset);
1540 (
Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1541 if (!
Info.Ctxt->hasCanonicalDIE())
1542 Info.Ctxt->setHasCanonicalDIE();
1546 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1550 DWARFDataExtractor
Data =
U.getDebugInfoExtractor();
1555 ?
U.getDIEAtIndex(
Idx + 1).getOffset()
1556 :
U.getNextUnitOffset();
1557 AttributesInfo AttrInfo;
1562 SmallString<40> DIECopy(
Data.getData().substr(
Offset, NextOffset -
Offset));
1564 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1567 ObjFile.Addresses->applyValidRelocs(DIECopy,
Offset,
Data.isLittleEndian());
1573 const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr();
1577 if (Die->getTag() == dwarf::DW_TAG_subprogram)
1578 PCOffset =
Info.AddrAdjust;
1579 AttrInfo.PCOffset = PCOffset;
1581 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1582 Flags |= TF_InFunctionScope;
1585 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1588 if ((
Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1589 Flags &= ~TF_SkipPC;
1592 for (
const auto &AttrSpec : Abbrev->attributes()) {
1594 Flags & TF_SkipPC,
Flags & TF_InFunctionScope)) {
1600 DWARFFormValue Val = AttrSpec.getFormValue();
1602 Val.extractValue(
Data, &
Offset,
U.getFormParams(), &U);
1603 AttrSize =
Offset - AttrSize;
1605 OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, StringPool, Val,
1606 AttrSpec, AttrSize, AttrInfo, IsLittleEndian);
1614 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1615 Tag != dwarf::DW_TAG_compile_unit &&
1616 getDIENames(InputDIE, AttrInfo, StringPool,
1617 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1618 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1619 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1620 Tag == dwarf::DW_TAG_inlined_subroutine);
1621 if (AttrInfo.Name) {
1622 if (AttrInfo.NameWithoutTemplate)
1623 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1625 Unit.addNameAccelerator(Die, AttrInfo.Name,
1626 Tag == dwarf::DW_TAG_inlined_subroutine);
1629 addObjCAccelerator(Unit, Die, AttrInfo.Name, StringPool,
1632 }
else if (
Tag == dwarf::DW_TAG_namespace) {
1634 AttrInfo.Name = StringPool.getEntry(
"(anonymous namespace)");
1635 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1636 }
else if (
Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
1637 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1638 }
else if (
isTypeTag(
Tag) && !AttrInfo.IsDeclaration &&
1639 getDIENames(InputDIE, AttrInfo, StringPool) && AttrInfo.Name &&
1640 AttrInfo.Name.getString()[0]) {
1641 uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit, File);
1645 bool ObjCClassIsImplementation =
1646 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1647 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1650 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1655 bool HasChildren =
false;
1656 for (
auto Child : InputDIE.children()) {
1657 unsigned Idx =
U.getDIEIndex(Child);
1658 if (Unit.getInfo(
Idx).Keep) {
1664 DIEAbbrev NewAbbrev = Die->generateAbbrev();
1668 Linker.assignAbbrev(NewAbbrev);
1669 Die->setAbbrevNumber(NewAbbrev.getNumber());
1676 Die->setSize(OutOffset - Die->getOffset());
1681 for (
auto Child : InputDIE.children()) {
1682 if (DIE *Clone = cloneDIE(Child, File, Unit, StringPool, PCOffset,
1683 OutOffset,
Flags, IsLittleEndian)) {
1684 Die->addChild(Clone);
1685 OutOffset = Clone->getOffset() + Clone->getSize();
1690 OutOffset +=
sizeof(int8_t);
1692 Die->setSize(OutOffset - Die->getOffset());
1699void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
1700 const DWARFFile &File)
const {
1704 const auto &FunctionRanges = Unit.getFunctionRanges();
1707 AddressRanges LinkedFunctionRanges;
1708 for (
const AddressRangeValuePair &Range : FunctionRanges)
1709 LinkedFunctionRanges.insert(
1713 if (!LinkedFunctionRanges.empty())
1717 std::optional<PatchLocation> UnitRngListAttribute =
1718 Unit.getUnitRangesAttribute();
1720 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
1721 std::optional<AddressRangeValuePair> CachedRange;
1726 for (PatchLocation &AttributePatch : AllRngListAttributes) {
1729 AddressRanges LinkedRanges;
1730 if (Expected<DWARFAddressRangesVector> OriginalRanges =
1731 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
1733 for (
const auto &Range : *OriginalRanges) {
1734 if (!CachedRange || !CachedRange->Range.contains(
Range.LowPC))
1735 CachedRange = FunctionRanges.getRangeThatContains(
Range.LowPC);
1739 reportWarning(
"inconsistent range data.", File);
1744 LinkedRanges.insert({
Range.LowPC + CachedRange->Value,
1745 Range.HighPC + CachedRange->Value});
1749 reportWarning(
"invalid range list ignored.", File);
1758 if (UnitRngListAttribute.has_value())
1760 Unit, LinkedFunctionRanges, *UnitRngListAttribute);
1767void DWARFLinker::generateUnitLocations(
1768 CompileUnit &Unit,
const DWARFFile &File,
1769 ExpressionHandlerRef ExprHandler)
const {
1774 Unit.getLocationAttributes();
1776 if (AllLocListAttributes.empty())
1782 for (
auto &CurLocAttr : AllLocListAttributes) {
1785 Expected<DWARFLocationExpressionsVector> OriginalLocations =
1786 Unit.getOrigUnit().findLoclistFromOffset((CurLocAttr.first).get());
1788 if (!OriginalLocations) {
1790 reportWarning(
"Invalid location attribute ignored.", File);
1795 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
1797 DWARFLocationExpression LinkedExpression;
1799 if (CurExpression.Range) {
1801 LinkedExpression.Range = {
1802 CurExpression.Range->LowPC + CurLocAttr.second,
1803 CurExpression.Range->HighPC + CurLocAttr.second};
1807 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
1808 ExprHandler(CurExpression.Expr, LinkedExpression.Expr);
1810 LinkedLocationExpressions.push_back(LinkedExpression);
1815 Unit, LinkedLocationExpressions, CurLocAttr.first);
1825 std::vector<DWARFDebugLine::Row> &Rows) {
1829 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
1843 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
1844 InsertPoint->EndSequence) {
1845 *InsertPoint = Seq.front();
1846 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
1848 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
1855 for (
auto &V : Die.
values())
1856 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
1867void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
1868 DWARFContext &OrigDwarf,
1869 const DWARFFile &File) {
1870 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
1876 if (
auto *OutputDIE = Unit.getOutputUnitDIE())
1880 RangesTy &Ranges = File.Addresses->getValidAddressRanges();
1883 DWARFDebugLine::LineTable LineTable;
1885 DWARFDataExtractor LineExtractor(
1886 OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(),
1887 OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize());
1888 if (needToTranslateStrings())
1892 LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf,
1893 &Unit.getOrigUnit(), OrigDwarf.getWarningHandler()))
1894 OrigDwarf.getWarningHandler()(std::move(Err));
1897 std::vector<DWARFDebugLine::Row> NewRows;
1898 NewRows.reserve(LineTable.Rows.size());
1902 std::vector<DWARFDebugLine::Row> Seq;
1903 const auto &FunctionRanges = Unit.getFunctionRanges();
1904 std::optional<AddressRangeValuePair> CurrRange;
1917 for (
auto &Row : LineTable.Rows) {
1923 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address) ||
1924 (Row.Address.Address == CurrRange->Range.end() && !Row.EndSequence)) {
1928 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
1929 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
1931 if (StopAddress != -1ULL) {
1938 if (std::optional<AddressRangeValuePair> Range =
1939 Ranges.getRangeThatContains(Row.Address.Address))
1940 StopAddress = Row.Address.Address + (*Range).Value;
1943 if (StopAddress != -1ULL && !Seq.empty()) {
1946 auto NextLine = Seq.back();
1947 NextLine.Address.Address = StopAddress;
1948 NextLine.EndSequence = 1;
1949 NextLine.PrologueEnd = 0;
1950 NextLine.BasicBlock = 0;
1951 NextLine.EpilogueBegin = 0;
1952 Seq.push_back(NextLine);
1961 if (Row.EndSequence && Seq.empty())
1965 Row.Address.Address += CurrRange->Value;
1966 Seq.emplace_back(Row);
1968 if (Row.EndSequence)
1977 if (LineTable.Prologue.getVersion() < 2 ||
1978 LineTable.Prologue.getVersion() > 5 ||
1980 LineTable.Prologue.OpcodeBase > 13)
1981 reportWarning(
"line table parameters mismatch. Cannot emit.", File);
1983 uint32_t PrologueEnd = *StmtList + 10 + LineTable.Prologue.PrologueLength;
1986 if (LineTable.Prologue.getVersion() == 5)
1988 StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data;
1989 MCDwarfLineTableParams Params;
1990 Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
1991 Params.DWARF2LineBase = LineTable.Prologue.LineBase;
1992 Params.DWARF2LineRange = LineTable.Prologue.LineRange;
1994 Params, LineData.slice(*StmtList + 4, PrologueEnd),
1995 LineTable.Prologue.MinInstLength, NewRows,
1996 Unit.getOrigUnit().getAddressByteSize());
2000void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2001 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2002 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2004 if (std::optional<uint64_t> MacroAttr =
2006 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2010 if (std::optional<uint64_t> MacroAttr =
2012 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2017void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2022 for (
const auto &Namespace : Unit.getNamespaces())
2023 AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() +
2024 Unit.getStartOffset());
2026 for (
const auto &Pubname : Unit.getPubnames())
2027 AppleNames.addName(Pubname.Name,
2028 Pubname.Die->getOffset() + Unit.getStartOffset());
2030 for (
const auto &Pubtype : Unit.getPubtypes())
2032 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
2033 Pubtype.Die->getTag(),
2036 Pubtype.QualifiedNameHash);
2038 for (
const auto &ObjC : Unit.getObjC())
2039 AppleObjc.addName(
ObjC.Name,
2040 ObjC.Die->getOffset() + Unit.getStartOffset());
2047 for (
const auto &Namespace : Unit.getNamespaces())
2048 DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
2049 Namespace.Die->getTag(), Unit.getUniqueID());
2050 for (
const auto &Pubname : Unit.getPubnames())
2051 DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(),
2052 Pubname.Die->getTag(), Unit.getUniqueID());
2053 for (
const auto &Pubtype : Unit.getPubtypes())
2054 DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(),
2055 Pubtype.Die->getTag(), Unit.getUniqueID());
2067void DWARFLinker::patchFrameInfoForObject(
const DWARFFile &File,
2069 DWARFContext &OrigDwarf,
2070 unsigned AddrSize) {
2071 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2075 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian(), 0);
2080 DenseMap<uint64_t, StringRef> LocalCIES;
2082 while (
Data.isValidOffset(InputOffset)) {
2083 uint64_t EntryOffset = InputOffset;
2085 if (InitialLength == 0xFFFFFFFF)
2086 return reportWarning(
"Dwarf64 bits no supported", File);
2089 if (CIEId == 0xFFFFFFFF) {
2091 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
2092 LocalCIES[EntryOffset] = CIEData;
2094 InputOffset += InitialLength - 4;
2098 uint64_t Loc =
Data.getUnsigned(&InputOffset, AddrSize);
2104 std::optional<AddressRangeValuePair>
Range =
2105 Ranges.getRangeThatContains(Loc);
2108 InputOffset = EntryOffset + InitialLength + 4;
2114 StringRef CIEData = LocalCIES[CIEId];
2115 if (CIEData.empty())
2116 return reportWarning(
"Inconsistent debug_frame content. Dropping.", File);
2120 auto IteratorInserted = EmittedCIEs.
insert(
2123 if (IteratorInserted.second) {
2125 IteratorInserted.first->getValue() = LastCIEOffset;
2126 TheDwarfEmitter->
emitCIE(CIEData);
2132 unsigned FDERemainingBytes = InitialLength - (4 + AddrSize);
2133 TheDwarfEmitter->
emitFDE(IteratorInserted.first->getValue(), AddrSize,
2135 FrameData.substr(InputOffset, FDERemainingBytes));
2136 InputOffset += FDERemainingBytes;
2140uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2142 const DWARFFile &File,
2143 int ChildRecurseDepth) {
2144 const char *
Name =
nullptr;
2145 DWARFUnit *OrigUnit = &
U.getOrigUnit();
2146 CompileUnit *
CU = &
U;
2147 std::optional<DWARFFormValue>
Ref;
2153 if (!(
Ref = DIE.find(dwarf::DW_AT_specification)) &&
2154 !(
Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2162 Linker.resolveDIEReference(File, CompileUnits, *
Ref, DIE, RefCU)) {
2164 OrigUnit = &RefCU->getOrigUnit();
2169 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2170 if (!
Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2171 Name =
"(anonymous namespace)";
2173 if (
CU->getInfo(
Idx).ParentIdx == 0 ||
2175 CU->getOrigUnit().getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx).getTag() ==
2176 dwarf::DW_TAG_module)
2179 DWARFDie Die = OrigUnit->getDIEAtIndex(
CU->getInfo(
Idx).ParentIdx);
2183 hashFullyQualifiedName(Die, *
CU, File, ++ChildRecurseDepth)));
2188 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2196 if (ObjectPrefixMap.empty())
2200 for (
const auto &Entry : ObjectPrefixMap)
2203 return p.str().str();
2209 CUDie.
find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2211 if (PCMFile.empty())
2214 if (ObjectPrefixMap)
2215 PCMFile =
remapPath(PCMFile, *ObjectPrefixMap);
2220std::pair<bool, bool> DWARFLinker::isClangModuleRef(
const DWARFDie &CUDie,
2221 std::string &PCMFile,
2222 LinkContext &Context,
2225 if (PCMFile.empty())
2226 return std::make_pair(
false,
false);
2234 reportWarning(
"Anonymous module skeleton CU for " + PCMFile,
2236 return std::make_pair(
true,
true);
2239 if (!
Quiet && Options.Verbose) {
2241 outs() <<
"Found clang module reference " << PCMFile;
2244 auto Cached = ClangModules.
find(PCMFile);
2245 if (Cached != ClangModules.
end()) {
2249 if (!
Quiet && Options.Verbose && (Cached->second != DwoId))
2250 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2251 "different version of the module ") +
2254 if (!
Quiet && Options.Verbose)
2255 outs() <<
" [cached].\n";
2256 return std::make_pair(
true,
true);
2259 return std::make_pair(
true,
false);
2262bool DWARFLinker::registerModuleReference(
const DWARFDie &CUDie,
2263 LinkContext &Context,
2267 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2268 std::pair<bool, bool> IsClangModuleRef =
2269 isClangModuleRef(CUDie, PCMFile, Context, Indent,
false);
2271 if (!IsClangModuleRef.first)
2274 if (IsClangModuleRef.second)
2277 if (Options.Verbose)
2284 if (Error
E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded,
2293 const std::string &PCMFile,
2294 LinkContext &Context,
2302 SmallString<0>
Path(Options.PrependPath);
2309 if (Loader ==
nullptr) {
2310 reportError(
"Could not load clang module: loader is not specified.\n",
2315 auto ErrOrObj = Loader(
Context.File.FileName, Path);
2319 std::unique_ptr<CompileUnit> Unit;
2320 for (
const auto &
CU : ErrOrObj->Dwarf->compile_units()) {
2323 auto ChildCUDie =
CU->getUnitDIE();
2326 if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded,
2331 ": Clang modules are expected to have exactly 1 compile unit.\n");
2332 reportError(Err,
Context.File);
2339 if (PCMDwoId != DwoId) {
2340 if (Options.Verbose)
2342 Twine(
"hash mismatch: this object file was built against a "
2343 "different version of the module ") +
2347 ClangModules[PCMFile] = PCMDwoId;
2351 Unit = std::make_unique<CompileUnit>(*
CU, UniqueUnitID++, !Options.NoODR,
2357 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2362uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2363 DWARFContext &DwarfContext,
const DWARFFile &File,
2366 Linker.Options.NoOutput ? 0 :
Emitter->getDebugInfoSectionSize();
2367 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2369 for (
auto &CurrentUnit : CompileUnits) {
2370 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2371 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2372 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2373 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2375 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2378 if (CurrentUnit->getInfo(0).Keep) {
2381 CurrentUnit->createOutputDIE();
2382 rememberUnitForMacroOffset(*CurrentUnit);
2383 cloneDIE(InputDIE, File, *CurrentUnit, StringPool, 0 ,
2384 UnitHeaderSize, 0, IsLittleEndian,
2385 CurrentUnit->getOutputUnitDIE());
2388 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2390 if (!Linker.Options.NoOutput) {
2394 Linker.needToTranslateStrings())
2395 Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext, File);
2397 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2402 Linker.generateUnitRanges(*CurrentUnit, File);
2404 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2405 SmallVectorImpl<uint8_t> &OutBytes) {
2406 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2407 DataExtractor
Data(SrcBytes, IsLittleEndian,
2408 OrigUnit.getAddressByteSize());
2409 cloneExpression(
Data,
2410 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2411 OrigUnit.getFormParams().Format),
2412 File, *CurrentUnit, OutBytes);
2414 Linker.generateUnitLocations(*CurrentUnit, File, ProcessExpr);
2418 if (!Linker.Options.NoOutput) {
2421 Emitter->emitMacroTables(
File.Dwarf, UnitMacroMap, StringPool);
2424 for (
auto &CurrentUnit : CompileUnits) {
2425 CurrentUnit->fixupForwardReferences();
2427 if (!CurrentUnit->getOutputUnitDIE())
2430 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2433 CurrentUnit->getStartOffset());
2434 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2435 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2437 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2441 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2444bool DWARFLinker::emitPaperTrailWarnings(
const DWARFFile &File,
2447 if (
File.Warnings.empty())
2450 DIE *CUDie =
DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit);
2451 CUDie->setOffset(11);
2453 StringRef WarningHeader;
2455 switch (DwarfLinkerClientID) {
2457 Producer = StringPool.internString(
"dsymutil");
2458 WarningHeader =
"dsymutil_warning";
2462 Producer = StringPool.internString(
"dwarfopt");
2463 WarningHeader =
"dwarfopt_warning";
2467 StringRef FileName = StringPool.internString(
File.FileName);
2468 CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp,
2469 DIEInteger(StringPool.getStringOffset(Producer)));
2470 DIEBlock *
String =
new (DIEAlloc) DIEBlock();
2471 DIEBlocks.push_back(
String);
2472 for (
auto &
C : FileName)
2478 CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string,
String);
2480 DIE &ConstDie = CUDie->addChild(
DIE::get(DIEAlloc, dwarf::DW_TAG_constant));
2481 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp,
2482 DIEInteger(StringPool.getStringOffset(WarningHeader)));
2483 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag,
2485 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp,
2486 DIEInteger(StringPool.getStringOffset(
Warning)));
2488 unsigned Size = 4 + FileName.size() + 1 +
2489 File.Warnings.size() * (4 + 1 + 4) + 1 ;
2490 DIEAbbrev Abbrev = CUDie->generateAbbrev();
2491 assignAbbrev(Abbrev);
2492 CUDie->setAbbrevNumber(Abbrev.getNumber());
2495 for (
auto &Child : CUDie->children()) {
2496 Abbrev = Child.generateAbbrev();
2497 assignAbbrev(Abbrev);
2498 Child.setAbbrevNumber(Abbrev.getNumber());
2501 CUDie->setSize(
Size);
2507void DWARFLinker::copyInvariantDebugSection(DWARFContext &
Dwarf) {
2508 if (!needToTranslateStrings())
2510 Dwarf.getDWARFObj().getLineSection().Data,
"debug_line");
2514 Dwarf.getDWARFObj().getRangesSection().Data,
"debug_ranges");
2516 Dwarf.getDWARFObj().getFrameSection().Data,
"debug_frame");
2520 Dwarf.getDWARFObj().getAddrSection().Data,
"debug_addr");
2522 Dwarf.getDWARFObj().getRnglistsSection().Data,
"debug_rnglists");
2524 Dwarf.getDWARFObj().getLoclistsSection().Data,
"debug_loclists");
2529 ObjectContexts.emplace_back(LinkContext(File));
2531 if (ObjectContexts.back().File.Dwarf) {
2532 for (
const std::unique_ptr<DWARFUnit> &
CU :
2533 ObjectContexts.back().File.Dwarf->compile_units()) {
2542 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
2549 assert(Options.NoOutput || TheDwarfEmitter);
2550 assert((Options.TargetDWARFVersion != 0) &&
2551 "TargetDWARFVersion should be set");
2555 unsigned NumObjects = ObjectContexts.size();
2565 for (LinkContext &OptContext : ObjectContexts) {
2566 if (Options.Verbose) {
2568 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
2570 outs() <<
"OBJECT FILE: " << OptContext.File.FileName <<
"\n";
2576 if (!OptContext.File.Dwarf)
2579 if (Options.VerifyInputDWARF)
2587 !OptContext.File.Addresses->hasValidRelocs()) {
2588 if (Options.Verbose)
2589 outs() <<
"No valid relocations found. Skipping.\n";
2593 OptContext.Skip =
true;
2598 if (!OptContext.File.Dwarf)
2602 if (!OptContext.File.Dwarf->types_section_units().empty()) {
2603 reportWarning(
"type units are not currently supported: file will "
2606 OptContext.Skip =
true;
2611 OptContext.CompileUnits.reserve(
2612 OptContext.File.Dwarf->getNumCompileUnits());
2614 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
2615 auto CUDie =
CU->getUnitDIE(
false);
2616 if (Options.Verbose) {
2617 outs() <<
"Input compilation unit:";
2620 DumpOpts.
Verbose = Options.Verbose;
2621 CUDie.dump(
outs(), 0, DumpOpts);
2625 for (
auto &
CU : OptContext.ModuleUnits) {
2628 reportWarning(
toString(std::move(Err)),
CU.File);
2642 std::mutex ProcessedFilesMutex;
2643 std::condition_variable ProcessedFilesConditionVariable;
2644 BitVector ProcessedFiles(NumObjects,
false);
2648 auto AnalyzeLambda = [&](
size_t I) {
2654 for (
const auto &
CU :
Context.File.Dwarf->compile_units()) {
2657 auto CUDie =
CU->getUnitDIE();
2658 std::string PCMFile =
getPCMFile(CUDie, Options.ObjectPrefixMap);
2661 !isClangModuleRef(CUDie, PCMFile,
Context, 0,
true).first) {
2662 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
2663 *
CU, UniqueUnitID++, !Options.NoODR && !Options.Update,
""));
2668 for (
auto &CurrentUnit :
Context.CompileUnits) {
2669 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
2673 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
2674 ModulesEndOffset, Options.ParseableSwiftInterfaces,
2676 reportWarning(Warning, Context.File, &DIE);
2688 auto CloneLambda = [&](
size_t I) {
2689 auto &OptContext = ObjectContexts[
I];
2690 if (OptContext.Skip || !OptContext.File.Dwarf)
2699 for (
auto &CurrentUnit : OptContext.CompileUnits)
2700 CurrentUnit->markEverythingAsKept();
2701 copyInvariantDebugSection(*OptContext.File.Dwarf);
2703 for (
auto &CurrentUnit : OptContext.CompileUnits) {
2704 lookForDIEsToKeep(*OptContext.File.Addresses,
2705 OptContext.File.Addresses->getValidAddressRanges(),
2706 OptContext.CompileUnits,
2707 CurrentUnit->getOrigUnit().getUnitDIE(),
2708 OptContext.File, *CurrentUnit, 0);
2718 if (OptContext.File.Addresses->hasValidRelocs() ||
2720 SizeByObject[OptContext.File.FileName].Input =
2722 SizeByObject[OptContext.File.FileName].Output =
2723 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
2724 OptContext.CompileUnits, Options.Update)
2725 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
2727 OptContext.File.Dwarf->isLittleEndian());
2729 if (!Options.NoOutput && !OptContext.CompileUnits.empty() &&
2731 patchFrameInfoForObject(
2732 OptContext.File, OptContext.File.Addresses->getValidAddressRanges(),
2733 *OptContext.File.Dwarf,
2734 OptContext.CompileUnits[0]->getOrigUnit().getAddressByteSize());
2737 cleanupAuxiliarryData(OptContext);
2740 auto EmitLambda = [&]() {
2742 if (!Options.NoOutput) {
2743 TheDwarfEmitter->
emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
2746 switch (TableKind) {
2765 auto AnalyzeAll = [&]() {
2766 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2769 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2770 ProcessedFiles.
set(
I);
2771 ProcessedFilesConditionVariable.notify_one();
2775 auto CloneAll = [&]() {
2776 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2778 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2779 if (!ProcessedFiles[
I]) {
2780 ProcessedFilesConditionVariable.wait(
2781 LockGuard, [&]() {
return ProcessedFiles[
I]; });
2793 if (Options.Threads == 1) {
2794 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2801 Pool.
async(AnalyzeAll);
2802 Pool.
async(CloneAll);
2806 if (Options.Statistics) {
2808 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
2809 for (
auto &
E : SizeByObject)
2810 Sorted.emplace_back(
E.first(),
E.second);
2812 return LHS.second.Output >
RHS.second.Output;
2815 auto ComputePercentange = [](int64_t Input, int64_t Output) ->
float {
2816 const float Difference = Output - Input;
2817 const float Sum = Input + Output;
2820 return (Difference / (Sum / 2));
2823 int64_t InputTotal = 0;
2824 int64_t OutputTotal = 0;
2825 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
2828 outs() <<
".debug_info section size (in bytes)\n";
2829 outs() <<
"----------------------------------------------------------------"
2830 "---------------\n";
2831 outs() <<
"Filename Object "
2833 outs() <<
"----------------------------------------------------------------"
2834 "---------------\n";
2837 for (
auto &
E : Sorted) {
2838 InputTotal +=
E.second.Input;
2839 OutputTotal +=
E.second.Output;
2842 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
2845 outs() <<
"----------------------------------------------------------------"
2846 "---------------\n";
2848 ComputePercentange(InputTotal, OutputTotal));
2849 outs() <<
"----------------------------------------------------------------"
2850 "---------------\n\n";
2856Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
2860 assert(Unit.Unit.get() !=
nullptr);
2862 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
2865 if (Options.Verbose) {
2867 outs() <<
"cloning .debug_info from " << Unit.File.FileName <<
"\n";
2872 &ODRContexts.
getRoot(), ODRContexts, 0,
2873 Options.ParseableSwiftInterfaces,
2874 [&](
const Twine &
Warning,
const DWARFDie &DIE) {
2875 reportWarning(Warning, Context.File, &DIE);
2878 Unit.Unit->markEverythingAsKept();
2882 CompileUnits.emplace_back(std::move(Unit.Unit));
2884 DIECloner(*
this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
2887 Unit.File.Dwarf->isLittleEndian());
2891bool DWARFLinker::verify(
const DWARFFile &File) {
2894 DIDumpOptions DumpOpts;
2895 if (!
File.Dwarf->verify(
llvm::outs(), DumpOpts.noImplicitRecursion())) {
2896 reportWarning(
"input verification failed", File);
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.
#define DWARF2_LINE_DEFAULT_IS_STMT
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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
Encoding
Size and signedness of expression operations' operands.
This class represents DWARF information for source file and its address map.
Error link()
Link debug info for added objFiles.
void addObjectFile(DWARFFile &File, objFileLoader Loader=nullptr, CompileUnitHandler OnCUDieLoaded=[](const DWARFUnit &) {})
Add object file to be linked.
This class gives a tree-like API to the DenseMap that stores the DeclContext objects.
PointerIntPair< DeclContext *, 1 > getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, CompileUnit &Unit, bool InClangModule)
Get the child of Context described by DIE in Unit.
A DeclContext is a named program scope that is used for ODR uniquing of types.
virtual void emitPaperTrailWarningsDie(DIE &Die)=0
Emit DIE containing warnings.
virtual void emitCIE(StringRef CIEBytes)=0
Emit a CIE.
virtual void emitPubNamesForUnit(const CompileUnit &Unit)=0
Emit the .debug_pubnames contribution for Unit.
virtual void emitDwarfDebugArangesTable(const CompileUnit &Unit, const AddressRanges &LinkedRanges)=0
Emit .debug_aranges entries for Unit.
virtual uint64_t getLineSectionSize() const =0
Returns size of generated .debug_line section.
virtual MCSymbol * emitDwarfDebugRangeListHeader(const CompileUnit &Unit)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) header.
virtual void emitAppleNames(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple names accelerator table.
virtual void emitDebugNames(AccelTable< DWARF5AccelTableStaticData > &Table)=0
Emit DWARF debug names.
virtual void translateLineTable(DataExtractor LineData, uint64_t Offset)=0
Copy the .debug_line over to the updated binary while unobfuscating the file names and directories.
virtual void emitStrings(const NonRelocatableStringpool &Pool)=0
Emit the string table described by Pool.
virtual void emitPubTypesForUnit(const CompileUnit &Unit)=0
Emit the .debug_pubtypes contribution for Unit.
virtual MCSymbol * emitDwarfDebugLocListHeader(const CompileUnit &Unit)=0
Emit debug locations (.debug_loc, .debug_loclists) header.
virtual void emitAppleNamespaces(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple namespaces accelerator table.
virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address, StringRef Bytes)=0
Emit an FDE with data Bytes.
virtual void emitLineTableForUnit(MCDwarfLineTableParams Params, StringRef PrologueBytes, unsigned MinInstLength, std::vector< DWARFDebugLine::Row > &Rows, unsigned AdddressSize)=0
Emit the line table described in Rows into the .debug_line section.
virtual uint64_t getDebugInfoSectionSize() const =0
Returns size of generated .debug_info section.
virtual void emitDwarfDebugLocListFragment(const CompileUnit &Unit, const DWARFLocationExpressionsVector &LinkedLocationExpression, PatchLocation Patch)=0
Emit debug locations (.debug_loc, .debug_loclists) fragment.
virtual void emitAbbrevs(const std::vector< std::unique_ptr< DIEAbbrev > > &Abbrevs, unsigned DwarfVersion)=0
Emit the abbreviation table Abbrevs to the .debug_abbrev section.
virtual void emitAppleTypes(AccelTable< AppleAccelTableStaticTypeData > &Table)=0
Emit Apple type accelerator table.
virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit, MCSymbol *EndLabel)=0
Emit debug locations (.debug_loc, .debug_loclists) footer.
virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, MCSymbol *EndLabel)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
virtual void emitSectionContents(StringRef SecData, StringRef SecName)=0
Emit section named SecName with data SecData.
virtual void emitDwarfDebugRangeListFragment(const CompileUnit &Unit, const AddressRanges &LinkedRanges, PatchLocation Patch)=0
Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
virtual uint64_t getFrameSectionSize() const =0
Returns size of generated .debug_frame section.
virtual void emitAppleObjc(AccelTable< AppleAccelTableStaticOffsetData > &Table)=0
Emit Apple Objective-C accelerator table.
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.
static constexpr size_t npos
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.
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.
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.
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.
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...
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
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
static CompileUnit * getUnitForOffset(const UnitListTy &Units, uint64_t Offset)
Similar to DWARFUnitSection::getUnitForOffset(), but returning our CompileUnit object instead.
static void resolveRelativeObjectPath(SmallVectorImpl< char > &Buf, DWARFDie CU)
Resolve the relative path to a build artifact referenced by DWARF by applying DW_AT_comp_dir.
SmallVector< std::pair< PatchLocation, int64_t > > LocListAttributesTy
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.
auto reverse(ContainerTy &&C)
std::function< ErrorOr< DWARFFile & >(StringRef ContainerName, StringRef Path)> objFileLoader
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)
AccelTableKind
The kind of accelerator tables we should emit.
@ 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.
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.
static std::optional< StringRef > StripTemplateParameters(StringRef Name)
unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
DwarfLinkerAccelTableKind
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
static bool shouldSkipAttribute(bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, uint16_t Tag, bool InDebugMap, bool SkipPC, bool InFunctionScope)
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...
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.
static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag)
static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU)
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
static bool isObjCSelector(StringRef Name)
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.
Hold the input and output of the debug info size in bytes.