47 for (
auto &Unit :
Dwarf.compile_units()) {
48 Size += Unit->getLength();
57 Units, Offset, [](
uint64_t LHS,
const std::unique_ptr<CompileUnit> &
RHS) {
58 return LHS <
RHS->getOrigUnit().getNextUnitOffset();
60 return CU != Units.end() ?
CU->get() :
nullptr;
66 DWARFDie DWARFLinker::resolveDIEReference(
const DWARFFile &File,
68 const DWARFFormValue &RefValue,
70 CompileUnit *&RefCU) {
72 uint64_t RefOffset = *RefValue.getAsReference();
74 if (
const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
81 reportWarning(
"could not find referenced DIE", File, &DIE);
91 case dwarf::DW_AT_type:
92 case dwarf::DW_AT_containing_type:
93 case dwarf::DW_AT_specification:
94 case dwarf::DW_AT_abstract_origin:
95 case dwarf::DW_AT_import:
103 case dwarf::DW_TAG_array_type:
104 case dwarf::DW_TAG_class_type:
105 case dwarf::DW_TAG_enumeration_type:
106 case dwarf::DW_TAG_pointer_type:
107 case dwarf::DW_TAG_reference_type:
108 case dwarf::DW_TAG_string_type:
109 case dwarf::DW_TAG_structure_type:
110 case dwarf::DW_TAG_subroutine_type:
111 case dwarf::DW_TAG_typedef:
112 case dwarf::DW_TAG_union_type:
113 case dwarf::DW_TAG_ptr_to_member_type:
114 case dwarf::DW_TAG_set_type:
115 case dwarf::DW_TAG_subrange_type:
116 case dwarf::DW_TAG_base_type:
117 case dwarf::DW_TAG_const_type:
118 case dwarf::DW_TAG_constant:
119 case dwarf::DW_TAG_file_type:
120 case dwarf::DW_TAG_namelist:
121 case dwarf::DW_TAG_packed_type:
122 case dwarf::DW_TAG_volatile_type:
123 case dwarf::DW_TAG_restrict_type:
124 case dwarf::DW_TAG_atomic_type:
125 case dwarf::DW_TAG_interface_type:
126 case dwarf::DW_TAG_unspecified_type:
127 case dwarf::DW_TAG_shared_type:
128 case dwarf::DW_TAG_immutable_type:
147 if (!
Name.endswith(
">") ||
Name.count(
"<") == 0 ||
Name.endswith(
"<=>"))
151 size_t NumLeftAnglesToSkip = 1;
154 NumLeftAnglesToSkip +=
Name.count(
"<=>");
156 size_t RightAngleCount =
Name.count(
'>');
157 size_t LeftAngleCount =
Name.count(
'<');
161 if (LeftAngleCount > RightAngleCount)
162 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
164 size_t StartOfTemplate = 0;
165 while (NumLeftAnglesToSkip--)
166 StartOfTemplate =
Name.find(
'<', StartOfTemplate) + 1;
168 return Name.substr(0, StartOfTemplate - 1);
171 bool DWARFLinker::DIECloner::getDIENames(
const DWARFDie &Die,
172 AttributesInfo &
Info,
174 bool StripTemplate) {
178 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
181 if (!
Info.MangledName)
182 if (
const char *MangledName = Die.getLinkageName())
183 Info.MangledName = StringPool.getEntry(MangledName);
186 if (
const char *
Name = Die.getShortName())
187 Info.Name = StringPool.getEntry(
Name);
189 if (!
Info.MangledName)
192 if (StripTemplate &&
Info.Name &&
Info.MangledName !=
Info.Name) {
193 StringRef
Name =
Info.Name.getString();
195 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
198 return Info.Name ||
Info.MangledName;
213 if (
CU.getLanguage() != dwarf::DW_LANG_Swift)
216 if (!ParseableSwiftInterfaces)
220 if (!Path.endswith(
".swiftinterface"))
225 SysRoot =
CU.getSysRoot();
226 if (!SysRoot.
empty() && Path.startswith(SysRoot))
231 auto &Entry = (*ParseableSwiftInterfaces)[*
Name];
233 DWARFDie CUDie =
CU.getOrigUnit().getUnitDIE();
238 if (!Entry.empty() && Entry != ResolvedPath)
239 ReportWarning(
Twine(
"Conflicting parseable interfaces for Swift Module ") +
240 *
Name +
": " + Entry +
" and " + Path,
242 Entry = std::string(ResolvedPath.
str());
285 Info.Prune &= (Die.
getTag() == dwarf::DW_TAG_module) ||
291 if (ModulesEndOffset == 0)
292 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset();
294 Info.Prune &=
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset() > 0 &&
295 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
319 bool InImportedModule =
false) {
321 std::vector<ContextWorklistItem> Worklist;
322 Worklist.emplace_back(
DIE, CurrentDeclContext, ParentIdx, InImportedModule);
324 while (!Worklist.empty()) {
328 switch (Current.
Type) {
339 unsigned Idx =
CU.getOrigUnit().getDIEIndex(Current.
Die);
354 if (Current.
Die.
getTag() == dwarf::DW_TAG_module &&
357 CU.getClangModuleName()) {
365 if (
CU.hasODR() || InClangModule) {
369 Current.
Context = PtrInvalidPair.getPointer();
371 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
373 Info.Ctxt->setDefinedInClangModule(InClangModule);
384 Worklist.emplace_back(
386 Worklist.emplace_back(Child, Current.
Context, Idx,
391 return CU.getInfo(
DIE).Prune;
398 case dwarf::DW_TAG_class_type:
399 case dwarf::DW_TAG_common_block:
400 case dwarf::DW_TAG_lexical_block:
401 case dwarf::DW_TAG_structure_type:
402 case dwarf::DW_TAG_subprogram:
403 case dwarf::DW_TAG_subroutine_type:
404 case dwarf::DW_TAG_union_type:
410 void DWARFLinker::cleanupAuxiliarryData(LinkContext &
Context) {
413 for (DIEBlock *
I : DIEBlocks)
415 for (DIELoc *
I : DIELocs)
425 unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
427 CompileUnit::DIEInfo &MyInfo,
429 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
432 if (!(Flags & TF_InFunctionScope) &&
433 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
434 MyInfo.InDebugMap =
true;
435 return Flags | TF_Keep;
443 const bool HasLiveMemoryLocation = RelocMgr.isLiveVariable(DIE, MyInfo);
444 if (!HasLiveMemoryLocation || ((Flags & TF_InFunctionScope) &&
448 if (Options.Verbose) {
449 outs() <<
"Keeping variable DIE:";
450 DIDumpOptions DumpOpts;
451 DumpOpts.ChildRecurseDepth = 0;
452 DumpOpts.Verbose = Options.Verbose;
453 DIE.dump(
outs(), 8 , DumpOpts);
456 return Flags | TF_Keep;
461 unsigned DWARFLinker::shouldKeepSubprogramDIE(
462 AddressesMap &RelocMgr,
RangesTy &Ranges,
const DWARFDie &DIE,
463 const DWARFFile &File, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
465 Flags |= TF_InFunctionScope;
471 assert(LowPc &&
"low_pc attribute is not an address.");
472 if (!RelocMgr.isLiveSubprogram(DIE, MyInfo))
475 if (Options.Verbose) {
476 outs() <<
"Keeping subprogram DIE:";
477 DIDumpOptions DumpOpts;
478 DumpOpts.ChildRecurseDepth = 0;
479 DumpOpts.Verbose = Options.Verbose;
480 DIE.dump(
outs(), 8 , DumpOpts);
483 if (DIE.getTag() == dwarf::DW_TAG_label) {
484 if (Unit.hasLabelAt(*LowPc))
487 DWARFUnit &OrigUnit = Unit.getOrigUnit();
495 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
496 return Flags | TF_Keep;
501 Optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
503 reportWarning(
"Function without high_pc. Range will be discarded.\n", File,
509 Ranges[*LowPc] = ObjFileAddressRange(*HighPc, MyInfo.AddrAdjust);
510 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
516 unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr,
RangesTy &Ranges,
517 const DWARFDie &DIE,
const DWARFFile &File,
519 CompileUnit::DIEInfo &MyInfo,
521 switch (DIE.getTag()) {
522 case dwarf::DW_TAG_constant:
523 case dwarf::DW_TAG_variable:
524 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
525 case dwarf::DW_TAG_subprogram:
526 case dwarf::DW_TAG_label:
527 return shouldKeepSubprogramDIE(RelocMgr, Ranges, DIE, File, Unit, MyInfo,
529 case dwarf::DW_TAG_base_type:
532 case dwarf::DW_TAG_imported_module:
533 case dwarf::DW_TAG_imported_declaration:
534 case dwarf::DW_TAG_imported_unit:
536 return Flags | TF_Keep;
550 case dwarf::DW_TAG_structure_type:
551 case dwarf::DW_TAG_class_type:
552 case dwarf::DW_TAG_union_type:
570 case dwarf::DW_TAG_typedef:
571 case dwarf::DW_TAG_member:
572 case dwarf::DW_TAG_reference_type:
573 case dwarf::DW_TAG_ptr_to_member_type:
574 case dwarf::DW_TAG_pointer_type:
591 void DWARFLinker::lookForChildDIEsToKeep(
592 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
593 SmallVectorImpl<WorklistItem> &Worklist) {
604 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
609 for (
auto Child :
reverse(Die.children())) {
612 CompileUnit::DIEInfo &ChildInfo =
CU.getInfo(Child);
613 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateChildIncompleteness,
615 Worklist.emplace_back(Child,
CU, Flags);
621 void DWARFLinker::lookForRefDIEsToKeep(
622 const DWARFDie &Die, CompileUnit &
CU,
unsigned Flags,
623 const UnitListTy &Units,
const DWARFFile &File,
624 SmallVectorImpl<WorklistItem> &Worklist) {
625 bool UseOdr = (Flags & DWARFLinker::TF_DependencyWalk)
626 ? (Flags & DWARFLinker::TF_ODR)
628 DWARFUnit &Unit =
CU.getOrigUnit();
629 DWARFDataExtractor
Data = Unit.getDebugInfoExtractor();
630 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
633 SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs;
634 for (
const auto &AttrSpec : Abbrev->attributes()) {
635 DWARFFormValue Val(AttrSpec.Form);
637 AttrSpec.Attr == dwarf::DW_AT_sibling) {
639 Unit.getFormParams());
643 Val.extractValue(
Data, &Offset, Unit.getFormParams(), &Unit);
644 CompileUnit *ReferencedCU;
646 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
647 CompileUnit::DIEInfo &
Info = ReferencedCU->getInfo(RefDie);
648 bool IsModuleRef =
Info.Ctxt &&
Info.Ctxt->getCanonicalDIEOffset() &&
649 Info.Ctxt->isDefinedInClangModule();
660 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && (UseOdr || IsModuleRef) &&
662 Info.Ctxt != ReferencedCU->getInfo(
Info.ParentIdx).Ctxt &&
668 Info.Ctxt->getCanonicalDIEOffset()))
670 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
674 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
678 for (
auto &
P :
reverse(ReferencedDIEs)) {
681 CompileUnit::DIEInfo &
Info =
P.second.getInfo(
P.first);
682 Worklist.emplace_back(Die,
CU, WorklistItemType::UpdateRefIncompleteness,
684 Worklist.emplace_back(
P.first,
P.second,
685 DWARFLinker::TF_Keep |
686 DWARFLinker::TF_DependencyWalk | ODRFlag);
691 void DWARFLinker::lookForParentDIEsToKeep(
692 unsigned AncestorIdx, CompileUnit &
CU,
unsigned Flags,
693 SmallVectorImpl<WorklistItem> &Worklist) {
695 if (
CU.getInfo(AncestorIdx).Keep)
698 DWARFUnit &Unit =
CU.getOrigUnit();
699 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);
700 Worklist.emplace_back(
CU.getInfo(AncestorIdx).ParentIdx,
CU, Flags);
701 Worklist.emplace_back(ParentDIE,
CU, Flags);
729 void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
731 const DWARFDie &Die,
const DWARFFile &File,
732 CompileUnit &Cu,
unsigned Flags) {
734 SmallVector<WorklistItem, 4> Worklist;
735 Worklist.emplace_back(Die, Cu, Flags);
737 while (!Worklist.empty()) {
738 WorklistItem Current = Worklist.pop_back_val();
741 switch (Current.Type) {
742 case WorklistItemType::UpdateChildIncompleteness:
745 case WorklistItemType::UpdateRefIncompleteness:
748 case WorklistItemType::LookForChildDIEsToKeep:
749 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
751 case WorklistItemType::LookForRefDIEsToKeep:
752 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
755 case WorklistItemType::LookForParentDIEsToKeep:
756 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
759 case WorklistItemType::LookForDIEsToKeep:
763 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
764 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx);
771 bool AlreadyKept = MyInfo.Keep;
772 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
777 if (!(Current.Flags & TF_DependencyWalk))
778 Current.Flags = shouldKeepDIE(AddressesMap, Ranges, Current.Die, File,
779 Current.CU, MyInfo, Current.Flags);
784 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
785 WorklistItemType::LookForChildDIEsToKeep);
787 if (AlreadyKept || !(Current.Flags & TF_Keep))
796 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
797 Current.Die.getTag() != dwarf::DW_TAG_member &&
803 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
804 WorklistItemType::LookForRefDIEsToKeep);
806 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
807 : Current.CU.hasODR();
808 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
809 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
812 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
822 void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
827 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(
ID, InsertToken);
832 Abbrev.setNumber(InSet->getNumber());
835 Abbreviations.push_back(
836 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
837 for (
const auto &Attr : Abbrev.getData())
838 Abbreviations.back()->AddAttribute(Attr.getAttribute(), Attr.getForm());
839 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
841 Abbrev.setNumber(Abbreviations.size());
842 Abbreviations.back()->setNumber(Abbreviations.size());
846 unsigned DWARFLinker::DIECloner::cloneStringAttribute(
847 DIE &Die, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
854 auto StringEntry = StringPool.getEntry(*String);
857 if (AttrSpec.Attr == dwarf::DW_AT_name)
858 Info.Name = StringEntry;
859 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
860 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
861 Info.MangledName = StringEntry;
863 Die.addValue(DIEAlloc,
dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp,
864 DIEInteger(StringEntry.getOffset()));
869 unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
870 DIE &Die,
const DWARFDie &InputDIE, AttributeSpec AttrSpec,
871 unsigned AttrSize,
const DWARFFormValue &Val,
const DWARFFile &File,
873 const DWARFUnit &U = Unit.getOrigUnit();
876 DIE *NewRefDie =
nullptr;
877 CompileUnit *RefUnit =
nullptr;
878 DeclContext *Ctxt =
nullptr;
881 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
884 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
887 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
893 if (Ctxt && Ctxt->getCanonicalDIEOffset()) {
894 DIEInteger Attr(Ctxt->getCanonicalDIEOffset());
896 dwarf::DW_FORM_ref_addr, Attr);
897 return U.getRefAddrByteSize();
901 if (!RefInfo.Clone) {
902 assert(Ref > InputDIE.getOffset());
907 NewRefDie = RefInfo.Clone;
909 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
917 if (Ref < InputDIE.getOffset()) {
920 RefUnit->getStartOffset() + NewRefDie->getOffset();
923 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));
927 Unit.noteForwardReference(
928 NewRefDie, RefUnit, Ctxt,
930 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
932 return U.getRefAddrByteSize();
941 void DWARFLinker::DIECloner::cloneExpression(
942 DataExtractor &
Data, DWARFExpression Expression,
const DWARFFile &File,
943 CompileUnit &Unit, SmallVectorImpl<uint8_t> &
OutputBuffer) {
947 for (
auto &
Op : Expression) {
948 auto Description =
Op.getDescription();
951 auto Op0 = Description.Op[0];
952 auto Op1 = Description.Op[1];
953 if ((Op0 == Encoding::BaseTypeRef && Op1 != Encoding::SizeNA) ||
954 (Op1 == Encoding::BaseTypeRef && Op0 != Encoding::Size1))
955 Linker.reportWarning(
"Unsupported DW_OP encoding.", File);
957 if ((Op0 == Encoding::BaseTypeRef && Op1 == Encoding::SizeNA) ||
958 (Op1 == Encoding::BaseTypeRef && Op0 == Encoding::Size1)) {
960 assert(OpOffset <
Op.getEndOffset());
961 uint32_t ULEBsize =
Op.getEndOffset() - OpOffset - 1;
967 if (Op1 == Encoding::SizeNA) {
968 RefOffset =
Op.getRawOperand(0);
971 RefOffset =
Op.getRawOperand(1);
977 if (RefOffset > 0 ||
Op.getCode() != dwarf::DW_OP_convert) {
978 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
979 CompileUnit::DIEInfo &
Info = Unit.getInfo(RefDie);
980 if (DIE *Clone =
Info.Clone)
981 Offset = Clone->getOffset();
983 Linker.reportWarning(
984 "base type ref doesn't point to DW_TAG_base_type.", File);
988 if (RealSize > ULEBsize) {
991 Linker.reportWarning(
"base type ref doesn't fit.", File);
993 assert(RealSize == ULEBsize &&
"padding failed");
994 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
995 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
998 StringRef Bytes =
Data.getData().slice(OpOffset,
Op.getEndOffset());
1001 OpOffset =
Op.getEndOffset();
1005 unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1006 DIE &Die,
const DWARFFile &File, CompileUnit &Unit, AttributeSpec AttrSpec,
1007 const DWARFFormValue &Val,
unsigned AttrSize,
bool IsLittleEndian) {
1010 DIELoc *Loc =
nullptr;
1011 DIEBlock *
Block =
nullptr;
1012 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1013 Loc =
new (DIEAlloc) DIELoc;
1014 Linker.DIELocs.push_back(Loc);
1016 Block =
new (DIEAlloc) DIEBlock;
1017 Linker.DIEBlocks.push_back(Block);
1019 Attr = Loc ?
static_cast<DIEValueList *
>(Loc)
1020 :
static_cast<DIEValueList *
>(Block);
1031 SmallVector<uint8_t, 32> Buffer;
1032 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1036 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1037 DataExtractor
Data(StringRef((
const char *)Bytes.data(), Bytes.size()),
1038 IsLittleEndian, OrigUnit.getAddressByteSize());
1039 DWARFExpression Expr(
Data, OrigUnit.getAddressByteSize(),
1040 OrigUnit.getFormParams().Format);
1041 cloneExpression(
Data, Expr, File, Unit, Buffer);
1044 for (
auto Byte : Bytes)
1046 dwarf::DW_FORM_data1, DIEInteger(Byte));
1052 Loc->setSize(Bytes.size());
1054 Block->setSize(Bytes.size());
1056 Die.addValue(DIEAlloc,
Value);
1060 unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1061 DIE &Die, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1062 const CompileUnit &Unit, AttributesInfo &
Info) {
1064 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1065 Info.HasLowPc =
true;
1067 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1068 return Unit.getOrigUnit().getAddressByteSize();
1073 if (
Form == dwarf::DW_FORM_addrx) {
1074 if (Optional<uint64_t> AddrOffsetSectionBase =
1075 Unit.getOrigUnit().getAddrOffsetSectionBase()) {
1076 uint64_t StartOffset = *AddrOffsetSectionBase + Val.getRawUValue();
1078 StartOffset + Unit.getOrigUnit().getAddressByteSize();
1080 ObjFile.Addresses->relocateIndexedAddr(StartOffset, EndOffset))
1083 Linker.reportWarning(
toString(RelocAddr.takeError()), ObjFile);
1085 Linker.reportWarning(
"no base offset for address table", ObjFile);
1088 Form = dwarf::DW_FORM_addr;
1090 Addr = *Val.getAsAddress();
1092 if (AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1093 if (Die.getTag() == dwarf::DW_TAG_inlined_subroutine ||
1094 Die.getTag() == dwarf::DW_TAG_lexical_block ||
1095 Die.getTag() == dwarf::DW_TAG_label) {
1104 }
else if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
1105 Addr = Unit.getLowPc();
1109 Info.HasLowPc =
true;
1110 }
else if (AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1111 if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
1112 if (
uint64_t HighPc = Unit.getHighPc())
1121 }
else if (AttrSpec.Attr == dwarf::DW_AT_call_return_pc) {
1123 if (Die.getTag() == dwarf::DW_TAG_call_site)
1126 }
else if (AttrSpec.Attr == dwarf::DW_AT_call_pc) {
1128 if (Die.getTag() == dwarf::DW_TAG_call_site)
1134 return Unit.getOrigUnit().getAddressByteSize();
1137 unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1138 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1139 CompileUnit &Unit, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
1140 unsigned AttrSize, AttributesInfo &
Info) {
1144 if (
auto OptionalValue = Val.getAsUnsignedConstant())
1145 Value = *OptionalValue;
1146 else if (
auto OptionalValue = Val.getAsSignedConstant())
1147 Value = *OptionalValue;
1148 else if (
auto OptionalValue = Val.getAsSectionOffset())
1149 Value = *OptionalValue;
1151 Linker.reportWarning(
1152 "Unsupported scalar attribute form. Dropping attribute.", File,
1156 if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1157 Info.IsDeclaration =
true;
1163 if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1164 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1165 if (Unit.getLowPc() == -1ULL)
1168 Value = Unit.getHighPc() - Unit.getLowPc();
1169 }
else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1170 Value = *Val.getAsSectionOffset();
1171 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1172 Value = *Val.getAsSignedConstant();
1173 else if (
auto OptionalValue = Val.getAsUnsignedConstant())
1174 Value = *OptionalValue;
1176 Linker.reportWarning(
1177 "Unsupported scalar attribute form. Dropping attribute.", File,
1181 PatchLocation
Patch =
1184 if (AttrSpec.Attr == dwarf::DW_AT_ranges) {
1185 Unit.noteRangeAttribute(Die, Patch);
1186 Info.HasRanges =
true;
1193 else if (AttrSpec.Attr == dwarf::DW_AT_location ||
1194 AttrSpec.Attr == dwarf::DW_AT_frame_base) {
1195 Unit.noteLocationAttribute(Patch,
Info.PCOffset);
1196 }
else if (AttrSpec.Attr == dwarf::DW_AT_declaration &&
Value)
1197 Info.IsDeclaration =
true;
1205 unsigned DWARFLinker::DIECloner::cloneAttribute(
1206 DIE &Die,
const DWARFDie &InputDIE,
const DWARFFile &File,
1208 const AttributeSpec AttrSpec,
unsigned AttrSize, AttributesInfo &
Info,
1209 bool IsLittleEndian) {
1210 const DWARFUnit &U = Unit.getOrigUnit();
1212 switch (AttrSpec.Form) {
1213 case dwarf::DW_FORM_strp:
1214 case dwarf::DW_FORM_string:
1215 case dwarf::DW_FORM_strx:
1216 case dwarf::DW_FORM_strx1:
1217 case dwarf::DW_FORM_strx2:
1218 case dwarf::DW_FORM_strx3:
1219 case dwarf::DW_FORM_strx4:
1220 return cloneStringAttribute(Die, AttrSpec, Val, U, StringPool,
Info);
1221 case dwarf::DW_FORM_ref_addr:
1222 case dwarf::DW_FORM_ref1:
1223 case dwarf::DW_FORM_ref2:
1224 case dwarf::DW_FORM_ref4:
1225 case dwarf::DW_FORM_ref8:
1226 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1228 case dwarf::DW_FORM_block:
1229 case dwarf::DW_FORM_block1:
1230 case dwarf::DW_FORM_block2:
1231 case dwarf::DW_FORM_block4:
1232 case dwarf::DW_FORM_exprloc:
1233 return cloneBlockAttribute(Die, File, Unit, AttrSpec, Val, AttrSize,
1235 case dwarf::DW_FORM_addr:
1236 case dwarf::DW_FORM_addrx:
1237 return cloneAddressAttribute(Die, AttrSpec, Val, Unit,
Info);
1238 case dwarf::DW_FORM_data1:
1239 case dwarf::DW_FORM_data2:
1240 case dwarf::DW_FORM_data4:
1241 case dwarf::DW_FORM_data8:
1242 case dwarf::DW_FORM_udata:
1243 case dwarf::DW_FORM_sdata:
1244 case dwarf::DW_FORM_sec_offset:
1245 case dwarf::DW_FORM_flag:
1246 case dwarf::DW_FORM_flag_present:
1247 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1250 Linker.reportWarning(
"Unsupported attribute form " +
1252 " in cloneAttribute. Dropping.",
1260 return Name.size() > 2 && (
Name[0] ==
'-' ||
Name[0] ==
'+') &&
1264 void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1266 DwarfStringPoolEntryRef
Name,
1268 bool SkipPubSection) {
1272 StringRef ClassNameStart(
Name.getString().drop_front(2));
1273 size_t FirstSpace = ClassNameStart.find(
' ');
1277 StringRef SelectorStart(ClassNameStart.data() + FirstSpace + 1);
1278 if (!SelectorStart.size())
1281 StringRef Selector(SelectorStart.data(), SelectorStart.size() - 1);
1282 Unit.addNameAccelerator(Die, StringPool.getEntry(Selector), SkipPubSection);
1286 StringRef ClassName(ClassNameStart.data(), FirstSpace);
1287 Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassName), SkipPubSection);
1289 if (ClassName[ClassName.size() - 1] ==
')') {
1290 size_t OpenParens = ClassName.find(
'(');
1292 StringRef ClassNameNoCategory(ClassName.data(), OpenParens);
1293 Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassNameNoCategory),
1296 std::string MethodNameNoCategory(
Name.getString().data(), OpenParens + 2);
1299 MethodNameNoCategory.append(std::string(SelectorStart));
1300 Unit.addNameAccelerator(Die, StringPool.getEntry(MethodNameNoCategory),
1309 bool InFunctionScope) {
1310 switch (AttrSpec.
Attr) {
1313 case dwarf::DW_AT_low_pc:
1314 case dwarf::DW_AT_high_pc:
1315 case dwarf::DW_AT_ranges:
1317 case dwarf::DW_AT_str_offsets_base:
1320 case dwarf::DW_AT_location:
1321 case dwarf::DW_AT_frame_base:
1327 return (SkipPC || (!InFunctionScope &&
Tag == dwarf::DW_TAG_variable &&
1333 DIE *DWARFLinker::DIECloner::cloneDIE(
const DWARFDie &InputDIE,
1334 const DWARFFile &File, CompileUnit &Unit,
1336 int64_t PCOffset,
uint32_t OutOffset,
1337 unsigned Flags,
bool IsLittleEndian,
1339 DWARFUnit &U = Unit.getOrigUnit();
1340 unsigned Idx = U.getDIEIndex(InputDIE);
1341 CompileUnit::DIEInfo &
Info = Unit.getInfo(Idx);
1344 if (!Unit.getInfo(Idx).Keep)
1347 uint64_t Offset = InputDIE.getOffset();
1348 assert(!(Die &&
Info.Clone) &&
"Can't supply a DIE and a cloned DIE");
1357 assert(Die->getTag() == InputDIE.getTag());
1358 Die->setOffset(OutOffset);
1359 if ((Unit.hasODR() || Unit.isClangModule()) && !
Info.Incomplete &&
1360 Die->getTag() != dwarf::DW_TAG_namespace &&
Info.Ctxt &&
1361 Info.Ctxt != Unit.getInfo(
Info.ParentIdx).Ctxt &&
1362 !
Info.Ctxt->getCanonicalDIEOffset()) {
1366 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1370 DWARFDataExtractor
Data = U.getDebugInfoExtractor();
1374 uint64_t NextOffset = (Idx + 1 < U.getNumDIEs())
1375 ? U.getDIEAtIndex(Idx + 1).getOffset()
1376 : U.getNextUnitOffset();
1377 AttributesInfo AttrInfo;
1382 SmallString<40> DIECopy(
Data.getData().substr(Offset, NextOffset - Offset));
1384 DWARFDataExtractor(DIECopy,
Data.isLittleEndian(),
Data.getAddressSize());
1387 if (ObjFile.Addresses->applyValidRelocs(DIECopy, Offset,
1388 Data.isLittleEndian())) {
1396 AttrInfo.OrigHighPc =
1403 AttrInfo.OrigCallReturnPc =
1405 AttrInfo.OrigCallPc =
1413 const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr();
1417 if (Die->getTag() == dwarf::DW_TAG_subprogram)
1418 PCOffset =
Info.AddrAdjust;
1419 AttrInfo.PCOffset = PCOffset;
1421 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1422 Flags |= TF_InFunctionScope;
1425 }
else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1428 if ((Flags & TF_InFunctionScope) &&
Info.InDebugMap)
1429 Flags &= ~TF_SkipPC;
1432 for (
const auto &AttrSpec : Abbrev->attributes()) {
1435 Flags & TF_SkipPC, Flags & TF_InFunctionScope)) {
1441 DWARFFormValue Val(AttrSpec.Form);
1443 Val.extractValue(
Data, &Offset, U.getFormParams(), &U);
1444 AttrSize =
Offset - AttrSize;
1446 OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, StringPool, Val,
1447 AttrSpec, AttrSize, AttrInfo, IsLittleEndian);
1455 if ((
Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
1456 Tag != dwarf::DW_TAG_compile_unit &&
1457 getDIENames(InputDIE, AttrInfo, StringPool,
1458 Tag != dwarf::DW_TAG_inlined_subroutine)) {
1459 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
1460 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
1461 Tag == dwarf::DW_TAG_inlined_subroutine);
1462 if (AttrInfo.Name) {
1463 if (AttrInfo.NameWithoutTemplate)
1464 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
1466 Unit.addNameAccelerator(Die, AttrInfo.Name,
1467 Tag == dwarf::DW_TAG_inlined_subroutine);
1470 addObjCAccelerator(Unit, Die, AttrInfo.Name, StringPool,
1473 }
else if (Tag == dwarf::DW_TAG_namespace) {
1475 AttrInfo.Name = StringPool.getEntry(
"(anonymous namespace)");
1476 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
1477 }
else if (
isTypeTag(Tag) && !AttrInfo.IsDeclaration &&
1478 getDIENames(InputDIE, AttrInfo, StringPool) && AttrInfo.Name &&
1479 AttrInfo.Name.getString()[0]) {
1480 uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit, File);
1484 bool ObjCClassIsImplementation =
1485 (RuntimeLang == dwarf::DW_LANG_ObjC ||
1486 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
1489 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
1494 bool HasChildren =
false;
1495 for (
auto Child : InputDIE.children()) {
1496 unsigned Idx = U.getDIEIndex(Child);
1497 if (Unit.getInfo(Idx).Keep) {
1503 DIEAbbrev NewAbbrev = Die->generateAbbrev();
1507 Linker.assignAbbrev(NewAbbrev);
1508 Die->setAbbrevNumber(NewAbbrev.getNumber());
1515 Die->setSize(OutOffset - Die->getOffset());
1520 for (
auto Child : InputDIE.children()) {
1521 if (DIE *Clone = cloneDIE(Child, File, Unit, StringPool, PCOffset,
1522 OutOffset, Flags, IsLittleEndian)) {
1523 Die->addChild(Clone);
1524 OutOffset = Clone->getOffset() + Clone->getSize();
1529 OutOffset +=
sizeof(int8_t);
1531 Die->setSize(OutOffset - Die->getOffset());
1538 void DWARFLinker::patchRangesForUnit(
const CompileUnit &Unit,
1539 DWARFContext &OrigDwarf,
1540 const DWARFFile &File)
const {
1541 DWARFDebugRangeList RangeList;
1542 const auto &FunctionRanges = Unit.getFunctionRanges();
1543 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
1544 DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
1545 OrigDwarf.getDWARFObj().getRangesSection(),
1546 OrigDwarf.isLittleEndian(), AddressSize);
1547 auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
1548 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1549 auto OrigUnitDie = OrigUnit.getUnitDIE(
false);
1554 int64_t UnitPcOffset = 0;
1555 if (OrigLowPc != -1ULL)
1556 UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
1558 for (
const auto &RangeAttribute : Unit.getRangesAttributes()) {
1561 if (Error
E = RangeList.extract(RangeExtractor, &Offset)) {
1563 reportWarning(
"invalid range list ignored.", File);
1566 const auto &Entries = RangeList.getEntries();
1567 if (!Entries.empty()) {
1568 const DWARFDebugRangeList::RangeListEntry &
First = Entries.front();
1570 if (CurrRange == InvalidRange ||
1571 First.StartAddress + OrigLowPc < CurrRange.start() ||
1572 First.StartAddress + OrigLowPc >= CurrRange.stop()) {
1573 CurrRange = FunctionRanges.find(
First.StartAddress + OrigLowPc);
1574 if (CurrRange == InvalidRange ||
1575 CurrRange.start() >
First.StartAddress + OrigLowPc) {
1576 reportWarning(
"no mapping for range.", File);
1583 Entries, AddressSize);
1593 void DWARFLinker::generateUnitRanges(CompileUnit &Unit)
const {
1594 auto Attr = Unit.getUnitRangesAttribute();
1603 std::vector<DWARFDebugLine::Row> &Rows) {
1607 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
1621 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
1622 InsertPoint->EndSequence) {
1623 *InsertPoint = Seq.front();
1624 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
1626 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
1633 for (
auto &V : Die.
values())
1634 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
1635 V =
DIEValue(V.getAttribute(), V.getForm(), Offset);
1645 void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
1646 DWARFContext &OrigDwarf,
1647 const DWARFFile &File) {
1648 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
1654 if (
auto *OutputDIE = Unit.getOutputUnitDIE())
1658 RangesTy &Ranges = File.Addresses->getValidAddressRanges();
1661 DWARFDebugLine::LineTable LineTable;
1663 DWARFDataExtractor LineExtractor(
1664 OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(),
1665 OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize());
1666 if (needToTranslateStrings())
1670 LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf,
1671 &Unit.getOrigUnit(), OrigDwarf.getWarningHandler()))
1672 OrigDwarf.getWarningHandler()(
std::move(Err));
1675 std::vector<DWARFDebugLine::Row> NewRows;
1676 NewRows.reserve(LineTable.Rows.size());
1680 std::vector<DWARFDebugLine::Row> Seq;
1681 const auto &FunctionRanges = Unit.getFunctionRanges();
1682 auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
1695 for (
auto &Row : LineTable.Rows) {
1701 if (CurrRange == InvalidRange || Row.Address.Address < CurrRange.start() ||
1702 Row.Address.Address > CurrRange.stop() ||
1703 (Row.Address.Address == CurrRange.stop() && !Row.EndSequence)) {
1706 uint64_t StopAddress = CurrRange != InvalidRange
1707 ? CurrRange.stop() + CurrRange.value()
1709 CurrRange = FunctionRanges.find(Row.Address.Address);
1710 bool CurrRangeValid =
1711 CurrRange != InvalidRange && CurrRange.start() <= Row.Address.Address;
1712 if (!CurrRangeValid) {
1713 CurrRange = InvalidRange;
1714 if (StopAddress != -1ULL) {
1721 auto Range = Ranges.lower_bound(Row.Address.Address);
1722 if (Range != Ranges.begin() && Range != Ranges.end())
1725 if (Range != Ranges.end() && Range->first <= Row.Address.Address &&
1726 Range->second.HighPC >= Row.Address.Address) {
1727 StopAddress = Row.Address.Address + Range->second.Offset;
1731 if (StopAddress != -1ULL && !Seq.empty()) {
1734 auto NextLine = Seq.back();
1735 NextLine.Address.Address = StopAddress;
1736 NextLine.EndSequence = 1;
1737 NextLine.PrologueEnd = 0;
1738 NextLine.BasicBlock = 0;
1739 NextLine.EpilogueBegin = 0;
1740 Seq.push_back(NextLine);
1744 if (!CurrRangeValid)
1749 if (Row.EndSequence && Seq.empty())
1753 Row.Address.Address += CurrRange.value();
1754 Seq.emplace_back(Row);
1756 if (Row.EndSequence)
1765 if (LineTable.Prologue.getVersion() < 2 ||
1766 LineTable.Prologue.getVersion() > 5 ||
1768 LineTable.Prologue.OpcodeBase > 13)
1769 reportWarning(
"line table parameters mismatch. Cannot emit.", File);
1771 uint32_t PrologueEnd = *StmtList + 10 + LineTable.Prologue.PrologueLength;
1774 if (LineTable.Prologue.getVersion() == 5)
1776 StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data;
1777 MCDwarfLineTableParams Params;
1778 Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
1779 Params.DWARF2LineBase = LineTable.Prologue.LineBase;
1780 Params.DWARF2LineRange = LineTable.Prologue.LineRange;
1782 Params, LineData.slice(*StmtList + 4, PrologueEnd),
1783 LineTable.Prologue.MinInstLength, NewRows,
1784 Unit.getOrigUnit().getAddressByteSize());
1788 void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
1789 switch (Options.TheAccelTableKind) {
1794 emitAppleAcceleratorEntriesForUnit(Unit);
1797 emitDwarfAcceleratorEntriesForUnit(Unit);
1800 emitPubAcceleratorEntriesForUnit(Unit);
1808 void DWARFLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) {
1810 for (
const auto &Namespace : Unit.getNamespaces())
1811 AppleNamespaces.addName(Namespace.Name,
1812 Namespace.Die->getOffset() + Unit.getStartOffset());
1815 for (
const auto &Pubname : Unit.getPubnames())
1816 AppleNames.addName(Pubname.Name,
1817 Pubname.Die->getOffset() + Unit.getStartOffset());
1820 for (
const auto &Pubtype : Unit.getPubtypes())
1822 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
1823 Pubtype.Die->getTag(),
1826 Pubtype.QualifiedNameHash);
1829 for (
const auto &ObjC : Unit.getObjC())
1830 AppleObjc.addName(ObjC.Name, ObjC.Die->getOffset() + Unit.getStartOffset());
1833 void DWARFLinker::emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit) {
1834 for (
const auto &Namespace : Unit.getNamespaces())
1835 DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
1836 Namespace.Die->getTag(), Unit.getUniqueID());
1837 for (
const auto &Pubname : Unit.getPubnames())
1838 DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(),
1839 Pubname.Die->getTag(), Unit.getUniqueID());
1840 for (
const auto &Pubtype : Unit.getPubtypes())
1841 DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(),
1842 Pubtype.Die->getTag(), Unit.getUniqueID());
1845 void DWARFLinker::emitPubAcceleratorEntriesForUnit(CompileUnit &Unit) {
1856 void DWARFLinker::patchFrameInfoForObject(
const DWARFFile &File,
1858 DWARFContext &OrigDwarf,
1859 unsigned AddrSize) {
1860 StringRef
FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
1864 DataExtractor
Data(FrameData, OrigDwarf.isLittleEndian(), 0);
1869 DenseMap<uint64_t, StringRef> LocalCIES;
1871 while (
Data.isValidOffset(InputOffset)) {
1872 uint64_t EntryOffset = InputOffset;
1874 if (InitialLength == 0xFFFFFFFF)
1875 return reportWarning(
"Dwarf64 bits no supported", File);
1878 if (CIEId == 0xFFFFFFFF) {
1880 StringRef CIEData =
FrameData.substr(EntryOffset, InitialLength + 4);
1881 LocalCIES[EntryOffset] = CIEData;
1883 InputOffset += InitialLength - 4;
1887 uint32_t Loc =
Data.getUnsigned(&InputOffset, AddrSize);
1893 auto Range = Ranges.upper_bound(Loc);
1894 if (Range != Ranges.begin())
1896 if (Range == Ranges.end() || Range->first > Loc ||
1897 Range->second.HighPC <= Loc) {
1899 InputOffset = EntryOffset + InitialLength + 4;
1905 StringRef CIEData = LocalCIES[CIEId];
1906 if (CIEData.empty())
1907 return reportWarning(
"Inconsistent debug_frame content. Dropping.", File);
1911 auto IteratorInserted = EmittedCIEs.
insert(
1914 if (IteratorInserted.second) {
1916 IteratorInserted.first->getValue() = LastCIEOffset;
1917 TheDwarfEmitter->
emitCIE(CIEData);
1923 unsigned FDERemainingBytes = InitialLength - (4 + AddrSize);
1924 TheDwarfEmitter->
emitFDE(IteratorInserted.first->getValue(), AddrSize,
1925 Loc + Range->second.Offset,
1926 FrameData.substr(InputOffset, FDERemainingBytes));
1927 InputOffset += FDERemainingBytes;
1931 uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
1933 const DWARFFile &File,
1934 int ChildRecurseDepth) {
1935 const char *
Name =
nullptr;
1936 DWARFUnit *OrigUnit = &U.getOrigUnit();
1937 CompileUnit *
CU = &U;
1938 Optional<DWARFFormValue>
Ref;
1944 if (!(Ref = DIE.find(dwarf::DW_AT_specification)) &&
1945 !(Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
1953 Linker.resolveDIEReference(File, CompileUnits, *Ref, DIE, RefCU)) {
1955 OrigUnit = &RefCU->getOrigUnit();
1960 unsigned Idx = OrigUnit->getDIEIndex(DIE);
1961 if (!
Name && DIE.getTag() == dwarf::DW_TAG_namespace)
1962 Name =
"(anonymous namespace)";
1964 if (
CU->getInfo(Idx).ParentIdx == 0 ||
1966 CU->getOrigUnit().getDIEAtIndex(
CU->getInfo(Idx).ParentIdx).getTag() ==
1967 dwarf::DW_TAG_module)
1970 DWARFDie Die = OrigUnit->getDIEAtIndex(
CU->getInfo(Idx).ParentIdx);
1974 hashFullyQualifiedName(Die, *
CU, File, ++ChildRecurseDepth)));
1979 CUDie.
find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
1987 if (ObjectPrefixMap.empty())
1991 for (
const auto &Entry : ObjectPrefixMap)
1994 return p.str().str();
1997 bool DWARFLinker::registerModuleReference(DWARFDie CUDie,
const DWARFUnit &Unit,
1998 const DWARFFile &File,
2000 DeclContextTree &ODRContexts,
2002 unsigned &UnitID,
bool IsLittleEndian,
2003 unsigned Indent,
bool Quiet) {
2005 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
"");
2006 if (PCMfile.empty())
2008 if (Options.ObjectPrefixMap)
2009 PCMfile =
remapPath(PCMfile, *Options.ObjectPrefixMap);
2017 reportWarning(
"Anonymous module skeleton CU for " + PCMfile, File);
2021 if (!Quiet && Options.Verbose) {
2023 outs() <<
"Found clang module reference " << PCMfile;
2026 auto Cached = ClangModules.
find(PCMfile);
2027 if (Cached != ClangModules.
end()) {
2031 if (!Quiet && Options.Verbose && (Cached->second != DwoId))
2032 reportWarning(Twine(
"hash mismatch: this object file was built against a "
2033 "different version of the module ") +
2036 if (!Quiet && Options.Verbose)
2037 outs() <<
" [cached].\n";
2040 if (!Quiet && Options.Verbose)
2045 ClangModules.
insert({PCMfile, DwoId});
2047 if (Error
E = loadClangModule(CUDie, PCMfile,
Name, DwoId, File, StringPool,
2048 ODRContexts, ModulesEndOffset, UnitID,
2049 IsLittleEndian, Indent + 2, Quiet)) {
2056 Error DWARFLinker::loadClangModule(
2059 DeclContextTree &ODRContexts,
uint64_t ModulesEndOffset,
unsigned &UnitID,
2060 bool IsLittleEndian,
unsigned Indent,
bool Quiet) {
2062 SmallString<0>
Path(Options.PrependPath);
2069 if (Options.ObjFileLoader ==
nullptr)
2072 auto ErrOrObj = Options.ObjFileLoader(
File.FileName, Path);
2076 std::unique_ptr<CompileUnit> Unit;
2078 for (
const auto &
CU : ErrOrObj->Dwarf->compile_units()) {
2079 updateDwarfVersion(
CU->getVersion());
2081 auto CUDie =
CU->getUnitDIE(
false);
2084 if (!registerModuleReference(CUDie, *
CU, File, StringPool, ODRContexts,
2085 ModulesEndOffset, UnitID, IsLittleEndian,
2090 ": Clang modules are expected to have exactly 1 compile unit.\n")
2092 reportError(Err, File);
2099 if (PCMDwoId != DwoId) {
2100 if (!Quiet && Options.Verbose)
2102 Twine(
"hash mismatch: this object file was built against a "
2103 "different version of the module ") +
2107 ClangModules[Filename] = PCMDwoId;
2111 Unit = std::make_unique<CompileUnit>(*
CU, UnitID++, !Options.NoODR,
2114 ModulesEndOffset, Options.ParseableSwiftInterfaces,
2115 [&](
const Twine &Warning,
const DWARFDie &DIE) {
2116 reportWarning(Warning, File, &DIE);
2119 Unit->markEverythingAsKept();
2122 assert(Unit &&
"CompileUnit is not set!");
2123 if (!Unit->getOrigUnit().getUnitDIE().hasChildren())
2125 if (!Quiet && Options.Verbose) {
2127 outs() <<
"cloning .debug_info from " << Filename <<
"\n";
2131 CompileUnits.push_back(
std::move(Unit));
2133 DIECloner(*
this, TheDwarfEmitter, *ErrOrObj, DIEAlloc, CompileUnits,
2135 .cloneAllCompileUnits(*(ErrOrObj->Dwarf), File, StringPool,
2140 uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2141 DWARFContext &DwarfContext,
const DWARFFile &File,
2144 Linker.Options.NoOutput ? 0 : Emitter->getDebugInfoSectionSize();
2145 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2147 for (
auto &CurrentUnit : CompileUnits) {
2148 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2149 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2150 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2151 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2153 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2156 if (CurrentUnit->getInfo(0).Keep) {
2159 CurrentUnit->createOutputDIE();
2160 cloneDIE(InputDIE, File, *CurrentUnit, StringPool, 0 ,
2161 UnitHeaderSize, 0, IsLittleEndian,
2162 CurrentUnit->getOutputUnitDIE());
2165 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2167 if (!Linker.Options.NoOutput) {
2171 Linker.needToTranslateStrings())
2172 Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext, File);
2174 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2179 Linker.patchRangesForUnit(*CurrentUnit, DwarfContext, File);
2180 auto ProcessExpr = [&](StringRef Bytes,
2181 SmallVectorImpl<uint8_t> &Buffer) {
2182 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2183 DataExtractor
Data(Bytes, IsLittleEndian,
2184 OrigUnit.getAddressByteSize());
2185 cloneExpression(
Data,
2186 DWARFExpression(
Data, OrigUnit.getAddressByteSize(),
2187 OrigUnit.getFormParams().Format),
2188 File, *CurrentUnit, Buffer);
2190 Emitter->emitLocationsForUnit(*CurrentUnit, DwarfContext, ProcessExpr);
2194 if (!Linker.Options.NoOutput) {
2197 for (
auto &CurrentUnit : CompileUnits) {
2199 Linker.generateUnitRanges(*CurrentUnit);
2201 CurrentUnit->fixupForwardReferences();
2203 if (!CurrentUnit->getOutputUnitDIE())
2206 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2208 assert(Emitter->getDebugInfoSectionSize() ==
2209 CurrentUnit->getStartOffset());
2210 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2211 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2212 assert(Emitter->getDebugInfoSectionSize() ==
2213 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2217 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2220 void DWARFLinker::updateAccelKind(DWARFContext &Dwarf) {
2224 auto &DwarfObj =
Dwarf.getDWARFObj();
2226 if (!AtLeastOneDwarfAccelTable &&
2227 (!DwarfObj.getAppleNamesSection().Data.empty() ||
2228 !DwarfObj.getAppleTypesSection().Data.empty() ||
2229 !DwarfObj.getAppleNamespacesSection().Data.empty() ||
2230 !DwarfObj.getAppleObjCSection().Data.empty())) {
2231 AtLeastOneAppleAccelTable =
true;
2234 if (!AtLeastOneDwarfAccelTable && !DwarfObj.getNamesSection().Data.empty()) {
2235 AtLeastOneDwarfAccelTable =
true;
2239 bool DWARFLinker::emitPaperTrailWarnings(
const DWARFFile &File,
2242 if (
File.Warnings.empty())
2245 DIE *CUDie =
DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit);
2246 CUDie->setOffset(11);
2248 StringRef WarningHeader;
2250 switch (DwarfLinkerClientID) {
2252 Producer = StringPool.internString(
"dsymutil");
2253 WarningHeader =
"dsymutil_warning";
2257 Producer = StringPool.internString(
"dwarfopt");
2258 WarningHeader =
"dwarfopt_warning";
2262 StringRef FileName = StringPool.internString(
File.FileName);
2263 CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp,
2264 DIEInteger(StringPool.getStringOffset(Producer)));
2265 DIEBlock *
String =
new (DIEAlloc) DIEBlock();
2266 DIEBlocks.push_back(String);
2267 for (
auto &
C : FileName)
2273 CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string, String);
2274 for (
const auto &Warning :
File.Warnings) {
2275 DIE &ConstDie = CUDie->addChild(
DIE::get(DIEAlloc, dwarf::DW_TAG_constant));
2276 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp,
2277 DIEInteger(StringPool.getStringOffset(WarningHeader)));
2278 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag,
2280 ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp,
2281 DIEInteger(StringPool.getStringOffset(Warning)));
2283 unsigned Size = 4 + FileName.size() + 1 +
2284 File.Warnings.size() * (4 + 1 + 4) + 1 ;
2285 DIEAbbrev Abbrev = CUDie->generateAbbrev();
2286 assignAbbrev(Abbrev);
2287 CUDie->setAbbrevNumber(Abbrev.getNumber());
2290 for (
auto &Child : CUDie->children()) {
2291 Abbrev = Child.generateAbbrev();
2292 assignAbbrev(Abbrev);
2293 Child.setAbbrevNumber(Abbrev.getNumber());
2296 CUDie->setSize(Size);
2302 void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) {
2303 if (!needToTranslateStrings())
2305 Dwarf.getDWARFObj().getLineSection().Data,
"debug_line");
2309 Dwarf.getDWARFObj().getRangesSection().Data,
"debug_ranges");
2311 Dwarf.getDWARFObj().getFrameSection().Data,
"debug_frame");
2317 ObjectContexts.emplace_back(LinkContext(File));
2319 if (ObjectContexts.back().File.Dwarf)
2320 updateAccelKind(*ObjectContexts.back().File.Dwarf);
2324 assert(Options.NoOutput || TheDwarfEmitter);
2327 unsigned UnitID = 0;
2331 unsigned NumObjects = ObjectContexts.size();
2348 if (AtLeastOneDwarfAccelTable && !AtLeastOneAppleAccelTable)
2354 for (LinkContext &OptContext : ObjectContexts) {
2355 if (Options.Verbose) {
2357 outs() <<
"DEBUG MAP OBJECT: " << OptContext.File.FileName <<
"\n";
2359 outs() <<
"OBJECT FILE: " << OptContext.File.FileName <<
"\n";
2365 if (!OptContext.File.Dwarf)
2368 if (Options.VerifyInputDWARF)
2369 verify(OptContext.File);
2376 !OptContext.File.Addresses->hasValidRelocs()) {
2377 if (Options.Verbose)
2378 outs() <<
"No valid relocations found. Skipping.\n";
2382 OptContext.Skip =
true;
2387 if (!OptContext.File.Dwarf)
2391 OptContext.CompileUnits.reserve(
2392 OptContext.File.Dwarf->getNumCompileUnits());
2394 for (
const auto &
CU : OptContext.File.Dwarf->compile_units()) {
2395 updateDwarfVersion(
CU->getVersion());
2396 auto CUDie =
CU->getUnitDIE(
false);
2397 if (Options.Verbose) {
2398 outs() <<
"Input compilation unit:";
2401 DumpOpts.
Verbose = Options.Verbose;
2402 CUDie.dump(
outs(), 0, DumpOpts);
2406 ODRContexts, 0, UnitID,
2407 OptContext.File.Dwarf->isLittleEndian());
2412 if (MaxDwarfVersion == 0)
2413 MaxDwarfVersion = 3;
2425 std::mutex ProcessedFilesMutex;
2426 std::condition_variable ProcessedFilesConditionVariable;
2427 BitVector ProcessedFiles(NumObjects,
false);
2431 auto AnalyzeLambda = [&](
size_t I) {
2437 for (
const auto &
CU :
Context.File.Dwarf->compile_units()) {
2438 updateDwarfVersion(
CU->getVersion());
2445 auto CUDie =
CU->getUnitDIE(
false);
2448 ODRContexts, ModulesEndOffset, UnitID,
2450 Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
2451 *
CU, UnitID++, !Options.NoODR && !Options.Update,
""));
2456 for (
auto &CurrentUnit :
Context.CompileUnits) {
2457 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
2461 *CurrentUnit, &ODRContexts.
getRoot(), ODRContexts,
2462 ModulesEndOffset, Options.ParseableSwiftInterfaces,
2464 reportWarning(Warning, Context.File, &DIE);
2476 auto CloneLambda = [&](
size_t I) {
2477 auto &OptContext = ObjectContexts[
I];
2478 if (OptContext.Skip || !OptContext.File.Dwarf)
2487 for (
auto &CurrentUnit : OptContext.CompileUnits)
2488 CurrentUnit->markEverythingAsKept();
2489 copyInvariantDebugSection(*OptContext.File.Dwarf);
2491 for (
auto &CurrentUnit : OptContext.CompileUnits)
2492 lookForDIEsToKeep(*OptContext.File.Addresses,
2493 OptContext.File.Addresses->getValidAddressRanges(),
2494 OptContext.CompileUnits,
2495 CurrentUnit->getOrigUnit().getUnitDIE(),
2496 OptContext.File, *CurrentUnit, 0);
2502 if (OptContext.File.Addresses->hasValidRelocs() ||
2504 SizeByObject[OptContext.File.FileName].Input =
2506 SizeByObject[OptContext.File.FileName].Output =
2507 DIECloner(*
this, TheDwarfEmitter, OptContext.File, DIEAlloc,
2508 OptContext.CompileUnits, Options.Update)
2509 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
2511 OptContext.File.Dwarf->isLittleEndian());
2513 if (!Options.NoOutput && !OptContext.CompileUnits.empty() &&
2515 patchFrameInfoForObject(
2516 OptContext.File, OptContext.File.Addresses->getValidAddressRanges(),
2517 *OptContext.File.Dwarf,
2518 OptContext.CompileUnits[0]->getOrigUnit().getAddressByteSize());
2521 cleanupAuxiliarryData(OptContext);
2524 auto EmitLambda = [&]() {
2526 if (!Options.NoOutput) {
2527 TheDwarfEmitter->
emitAbbrevs(Abbreviations, MaxDwarfVersion);
2529 switch (Options.TheAccelTableKind) {
2552 auto AnalyzeAll = [&]() {
2553 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2556 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2557 ProcessedFiles.
set(
I);
2558 ProcessedFilesConditionVariable.notify_one();
2562 auto CloneAll = [&]() {
2563 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2565 std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex);
2566 if (!ProcessedFiles[
I]) {
2567 ProcessedFilesConditionVariable.wait(
2568 LockGuard, [&]() {
return ProcessedFiles[
I]; });
2580 if (Options.Threads == 1) {
2581 for (
unsigned I = 0,
E = NumObjects;
I !=
E; ++
I) {
2588 Pool.
async(AnalyzeAll);
2589 Pool.
async(CloneAll);
2593 if (Options.Statistics) {
2595 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
2596 for (
auto &
E : SizeByObject)
2597 Sorted.emplace_back(
E.first(),
E.second);
2599 return LHS.second.Output >
RHS.second.Output;
2602 auto ComputePercentange = [](int64_t Input, int64_t Output) ->
float {
2603 const float Difference = Output - Input;
2604 const float Sum = Input + Output;
2607 return (Difference / (Sum / 2));
2610 int64_t InputTotal = 0;
2611 int64_t OutputTotal = 0;
2612 const char *FormatStr =
"{0,-45} {1,10}b {2,10}b {3,8:P}\n";
2615 outs() <<
".debug_info section size (in bytes)\n";
2616 outs() <<
"----------------------------------------------------------------"
2617 "---------------\n";
2618 outs() <<
"Filename Object "
2620 outs() <<
"----------------------------------------------------------------"
2621 "---------------\n";
2624 for (
auto &
E : Sorted) {
2625 InputTotal +=
E.second.Input;
2626 OutputTotal +=
E.second.Output;
2629 E.second.Output, ComputePercentange(
E.second.Input,
E.second.Output));
2632 outs() <<
"----------------------------------------------------------------"
2633 "---------------\n";
2635 ComputePercentange(InputTotal, OutputTotal));
2636 outs() <<
"----------------------------------------------------------------"
2637 "---------------\n\n";
2643 bool DWARFLinker::verify(
const DWARFFile &File) {
2648 reportWarning(
"input verification failed", File);