LLVM: lib/DWARFLinker/Classic/DWARFLinker.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
39#include
40
41namespace llvm {
42
45
46
51
52
55 for (auto &Unit : Dwarf.compile_units()) {
56 Size += Unit->getLength();
57 }
59}
60
61
62
66 return LHS < RHS->getOrigUnit().getNextUnitOffset();
67 });
68 return CU != Units.end() ? CU->get() : nullptr;
69}
70
71
72
73
74DWARFDie DWARFLinker::resolveDIEReference(const DWARFFile &File,
76 const DWARFFormValue &RefValue,
77 const DWARFDie &DIE,
78 CompileUnit *&RefCU) {
81 if (std::optional<uint64_t> Off = RefValue.getAsRelativeReference()) {
82 RefOffset = RefValue.getUnit()->getOffset() + *Off;
83 } else if (Off = RefValue.getAsDebugInfoReference(); Off) {
84 RefOffset = *Off;
85 } else {
86 reportWarning("Unsupported reference type", File, &DIE);
87 return DWARFDie();
88 }
90 if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
91
92
93 if (!RefDie.isNULL())
94 return RefDie;
95 }
96
97 reportWarning("could not find referenced DIE", File, &DIE);
98 return DWARFDie();
99}
100
101
102
104 switch (Attr) {
105 default:
106 return false;
107 case dwarf::DW_AT_type:
108 case dwarf::DW_AT_containing_type:
109 case dwarf::DW_AT_specification:
110 case dwarf::DW_AT_abstract_origin:
111 case dwarf::DW_AT_import:
112 case dwarf::DW_AT_LLVM_alloc_type:
113 return true;
114 }
116}
117
119 switch (Tag) {
120 case dwarf::DW_TAG_array_type:
121 case dwarf::DW_TAG_class_type:
122 case dwarf::DW_TAG_enumeration_type:
123 case dwarf::DW_TAG_pointer_type:
124 case dwarf::DW_TAG_reference_type:
125 case dwarf::DW_TAG_string_type:
126 case dwarf::DW_TAG_structure_type:
127 case dwarf::DW_TAG_subroutine_type:
128 case dwarf::DW_TAG_template_alias:
129 case dwarf::DW_TAG_typedef:
130 case dwarf::DW_TAG_union_type:
131 case dwarf::DW_TAG_ptr_to_member_type:
132 case dwarf::DW_TAG_set_type:
133 case dwarf::DW_TAG_subrange_type:
134 case dwarf::DW_TAG_base_type:
135 case dwarf::DW_TAG_const_type:
136 case dwarf::DW_TAG_constant:
137 case dwarf::DW_TAG_file_type:
138 case dwarf::DW_TAG_namelist:
139 case dwarf::DW_TAG_packed_type:
140 case dwarf::DW_TAG_volatile_type:
141 case dwarf::DW_TAG_restrict_type:
142 case dwarf::DW_TAG_atomic_type:
143 case dwarf::DW_TAG_interface_type:
144 case dwarf::DW_TAG_unspecified_type:
145 case dwarf::DW_TAG_shared_type:
146 case dwarf::DW_TAG_immutable_type:
147 return true;
148 default:
149 break;
150 }
151 return false;
152}
153
154
155
157DWARFLinker::DIECloner::getCanonicalDIEName(DWARFDie Die, const DWARFFile &File,
158 CompileUnit *Unit) {
159 if (!Die)
160 return {};
161
162 std::optional Ref;
163
164 auto GetDieName = [](const DWARFDie &D) -> llvm::StringRef {
165 auto NameForm = D.find(llvm::dwarf::DW_AT_name);
166 if (!NameForm)
167 return {};
168
169 auto NameOrErr = NameForm->getAsCString();
170 if (!NameOrErr) {
172 return {};
173 }
174
175 return *NameOrErr;
176 };
177
178 llvm::StringRef Name = GetDieName(Die);
179 if (.empty())
181
182 while (true) {
183 if (!(Ref = Die.find(llvm::dwarf::DW_AT_specification)) &&
184 !(Ref = Die.find(llvm::dwarf::DW_AT_abstract_origin)))
185 break;
186
187 Die = Linker.resolveDIEReference(File, CompileUnits, *Ref, Die, Unit);
188 if (!Die)
189 break;
190
192
193 unsigned SpecIdx = Unit->getOrigUnit().getDIEIndex(Die);
194 CompileUnit::DIEInfo &SpecInfo = Unit->getInfo(SpecIdx);
195 if (SpecInfo.Ctxt && SpecInfo.Ctxt->hasCanonicalDIE()) {
196 if (!SpecInfo.Ctxt->getCanonicalName().empty()) {
197 Name = SpecInfo.Ctxt->getCanonicalName();
198 break;
199 }
200 }
201
202 Name = GetDieName(Die);
203 if (.empty())
204 break;
205 }
206
208}
209
210bool DWARFLinker::DIECloner::getDIENames(
212 const DWARFFile &File, CompileUnit &Unit, bool StripTemplate) {
213
214
215
216 if (Die.getTag() == dwarf::DW_TAG_lexical_block)
217 return false;
218
219
220
221
222 if (.MangledName)
223 if (const char *MangledName = Die.getLinkageName())
224 Info.MangledName = StringPool.getEntry(MangledName);
225
226
227
228
229 if (.Name)
230 if (llvm::StringRef Name = getCanonicalDIEName(Die, File, &Unit);
231 .empty())
232 Info.Name = StringPool.getEntry(Name);
233
234 if (.MangledName)
235 Info.MangledName = Info.Name;
236
237 if (StripTemplate && Info.Name && Info.MangledName != Info.Name) {
238 StringRef Name = Info.Name.getString();
240 Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
241 }
242
243 return Info.Name || Info.MangledName;
244}
245
246
247
251
252
253
257 std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {
258 if (CU.getLanguage() != dwarf::DW_LANG_Swift)
259 return;
260
261 if (!ParseableSwiftInterfaces)
262 return;
263
265 if (!Path.ends_with(".swiftinterface"))
266 return;
267
269 if (SysRoot.empty())
270 SysRoot = CU.getSysRoot();
271 if (!SysRoot.empty() && Path.starts_with(SysRoot))
272 return;
273
274
276 if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))
277 return;
279 return;
280 std::optional<const char *> Name =
282 if (!Name)
283 return;
284 auto &Entry = (*ParseableSwiftInterfaces)[*Name];
285
286 DWARFDie CUDie = CU.getOrigUnit().getUnitDIE();
291 if (!Entry.empty() && Entry != ResolvedPath)
292 ReportWarning(Twine("Conflicting parseable interfaces for Swift Module ") +
293 *Name + ": " + Entry + " and " + Path,
295 Entry = std::string(ResolvedPath);
296}
297
298
299
305
306
307
308
312 union {
315 };
318
323
329};
330
334
335
336
337
338 Info.Prune &= (Die.getTag() == dwarf::DW_TAG_module) ||
341
342
343
344 if (ModulesEndOffset == 0)
345 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();
346 else
347 Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 &&
348 Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset;
349
350 return Info.Prune;
351}
352
358
359
360
361
362
363
364
365
366
372 std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {
373
374 std::vector Worklist;
375 Worklist.emplace_back(DIE, CurrentDeclContext, ParentIdx, false);
376
377 while (!Worklist.empty()) {
379 Worklist.pop_back();
380
381 switch (Current.Type) {
384 continue;
387 continue;
389 break;
390 }
391
392 unsigned Idx = CU.getOrigUnit().getDIEIndex(Current.Die);
394
395
396
397
398
399
400
401
402
403
404
405
406
407 if (Current.Die.getTag() == dwarf::DW_TAG_module &&
410 CU.getClangModuleName()) {
413 ReportWarning);
414 }
415
418 if (CU.hasODR() || Info.InModuleScope) {
422 Current.Context = PtrInvalidPair.getPointer();
424 PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
425 if (Info.Ctxt)
426 Info.Ctxt->setDefinedInClangModule(Info.InModuleScope);
427 } else
429 }
430
432
433
437 Worklist.emplace_back(
439 Worklist.emplace_back(Child, Current.Context, Idx,
441 }
442 }
443}
444
446 switch (Tag) {
447 default:
448 return false;
449 case dwarf::DW_TAG_class_type:
450 case dwarf::DW_TAG_common_block:
451 case dwarf::DW_TAG_lexical_block:
452 case dwarf::DW_TAG_structure_type:
453 case dwarf::DW_TAG_subprogram:
454 case dwarf::DW_TAG_subroutine_type:
455 case dwarf::DW_TAG_union_type:
456 return true;
457 }
459}
460
461void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
462 Context.clear();
463
464 for (DIEBlock *I : DIEBlocks)
465 I->~DIEBlock();
466 for (DIELoc *I : DIELocs)
467 I->~DIELoc();
468
469 DIEBlocks.clear();
470 DIELocs.clear();
471 DIEAlloc.Reset();
472}
473
475 return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
476 DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
477}
478
482
483
484 std::map<uint64_t, unsigned> LineTableMapping;
485
486
489
490
491
492 auto StmtAttrs = Unit.getStmtSeqListAttributes();
495 });
496
497 std::vector SeqStartRows;
498 SeqStartRows.push_back(0);
500 if (Row.EndSequence)
501 SeqStartRows.push_back(I + 1);
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532 ArrayRef StmtAttrsRef(StmtAttrs);
533 ArrayRef SeqStartRowsRef(SeqStartRows);
534
535
536
538 constexpr unsigned DummyVal = UINT32_MAX;
539 LineTableMapping[DummyKey] = DummyVal;
540
541 for (auto [NextSeqOff, NextRow] : LineTableMapping) {
542
543
544 auto StmtAttrSmallerThanNext = [N = NextSeqOff](const PatchLocation &SA) {
545 return SA.get() < N;
546 };
547 auto SeqStartSmallerThanNext = [N = NextRow](const unsigned &Row) {
548 return Row < N;
549 };
550
551
552
553 while (!StmtAttrsRef.empty() && !SeqStartRowsRef.empty() &&
554 StmtAttrSmallerThanNext(StmtAttrsRef.front()) &&
555 SeqStartSmallerThanNext(SeqStartRowsRef.front())) {
556 SeqOffToOrigRow[StmtAttrsRef.consume_front().get()] =
558 }
559
560
561
562 StmtAttrsRef = StmtAttrsRef.drop_while(StmtAttrSmallerThanNext);
563 SeqStartRowsRef = SeqStartRowsRef.drop_while(SeqStartSmallerThanNext);
564
565
566 if (NextSeqOff != DummyKey) {
567 SeqOffToOrigRow[NextSeqOff] = NextRow;
568 }
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583 if (!StmtAttrsRef.empty() && StmtAttrsRef.front().get() == NextSeqOff)
585 if (!SeqStartRowsRef.empty() && SeqStartRowsRef.front() == NextRow)
587 }
588}
589
590std::pair<bool, std::optional<int64_t>>
591DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
592 const DWARFDie &DIE) {
593 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
594 DIE.getTag() == dwarf::DW_TAG_constant) &&
595 "Wrong type of input die");
596
597 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
598
599
600 DWARFUnit *U = DIE.getDwarfUnit();
601 std::optional<uint32_t> LocationIdx =
602 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
603 if (!LocationIdx)
604 return std::make_pair(false, std::nullopt);
605
606
608 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
609
610
611 std::optional LocationValue =
612 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
613 if (!LocationValue)
614 return std::make_pair(false, std::nullopt);
615
616
617
618
619 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
620 if (!Expr)
621 return std::make_pair(false, std::nullopt);
622
623
624 DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(),
625 U->getAddressByteSize());
626 DWARFExpression Expression(Data, U->getAddressByteSize(),
627 U->getFormParams().Format);
628
629 bool HasLocationAddress = false;
631 for (DWARFExpression::iterator It = Expression.begin();
632 It != Expression.end(); ++It) {
633 DWARFExpression::iterator NextIt = It;
634 ++NextIt;
635
636 const DWARFExpression::Operation &Op = *It;
638 case dwarf::DW_OP_const2u:
639 case dwarf::DW_OP_const4u:
640 case dwarf::DW_OP_const8u:
641 case dwarf::DW_OP_const2s:
642 case dwarf::DW_OP_const4s:
643 case dwarf::DW_OP_const8s:
644 if (NextIt == Expression.end() || (NextIt->getCode()))
645 break;
646 [[fallthrough]];
647 case dwarf::DW_OP_addr: {
648 HasLocationAddress = true;
649
650 if (std::optional<int64_t> RelocAdjustment =
651 RelocMgr.getExprOpAddressRelocAdjustment(
652 *U, Op, AttrOffset + CurExprOffset,
654 return std::make_pair(HasLocationAddress, *RelocAdjustment);
655 } break;
656 case dwarf::DW_OP_constx:
657 case dwarf::DW_OP_addrx: {
658 HasLocationAddress = true;
659 if (std::optional<uint64_t> AddressOffset =
660 DIE.getDwarfUnit()->getIndexedAddressOffset(
662
663 if (std::optional<int64_t> RelocAdjustment =
664 RelocMgr.getExprOpAddressRelocAdjustment(
665 *U, Op, *AddressOffset,
666 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
667 Options.Verbose))
668 return std::make_pair(HasLocationAddress, *RelocAdjustment);
669 }
670 } break;
671 default: {
672
673 } break;
674 }
676 }
677
678 return std::make_pair(HasLocationAddress, std::nullopt);
679}
680
681
682
683unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
684 const DWARFDie &DIE,
685 CompileUnit::DIEInfo &MyInfo,
686 unsigned Flags) {
687 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
688
689
690 if (!(Flags & TF_InFunctionScope) &&
691 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
692 MyInfo.InDebugMap = true;
693 return Flags | TF_Keep;
694 }
695
696
697
698
699
700
701 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
702 getVariableRelocAdjustment(RelocMgr, DIE);
703
704 if (LocExprAddrAndRelocAdjustment.first)
705 MyInfo.HasLocationExpressionAddr = true;
706
707 if (!LocExprAddrAndRelocAdjustment.second)
709
710 MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second;
711 MyInfo.InDebugMap = true;
712
713 if (((Flags & TF_InFunctionScope) &&
716
717 if (Options.Verbose) {
718 outs() << "Keeping variable DIE:";
719 DIDumpOptions DumpOpts;
720 DumpOpts.ChildRecurseDepth = 0;
721 DumpOpts.Verbose = Options.Verbose;
722 DIE.dump(outs(), 8 , DumpOpts);
723 }
724
725 return Flags | TF_Keep;
726}
727
728
729
730unsigned DWARFLinker::shouldKeepSubprogramDIE(
731 AddressesMap &RelocMgr, const DWARFDie &DIE, const DWARFFile &File,
732 CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) {
733 Flags |= TF_InFunctionScope;
734
735 auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc));
736 if (!LowPc)
738
739 assert(LowPc && "low_pc attribute is not an address.");
740 std::optional<int64_t> RelocAdjustment =
741 RelocMgr.getSubprogramRelocAdjustment(DIE, Options.Verbose);
742 if (!RelocAdjustment)
744
745 MyInfo.AddrAdjust = *RelocAdjustment;
746 MyInfo.InDebugMap = true;
747
748 if (Options.Verbose) {
749 outs() << "Keeping subprogram DIE:";
750 DIDumpOptions DumpOpts;
751 DumpOpts.ChildRecurseDepth = 0;
752 DumpOpts.Verbose = Options.Verbose;
753 DIE.dump(outs(), 8 , DumpOpts);
754 }
755
756 if (DIE.getTag() == dwarf::DW_TAG_label) {
757 if (Unit.hasLabelAt(*LowPc))
759
760 DWARFUnit &OrigUnit = Unit.getOrigUnit();
761
762
763
764
765 if (dwarf::toAddress(OrigUnit.getUnitDIE().find(dwarf::DW_AT_high_pc))
768 Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
769 return Flags | TF_Keep;
770 }
771
772 Flags |= TF_Keep;
773
774 std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
775 if (!HighPc) {
776 reportWarning("Function without high_pc. Range will be discarded.\n", File,
777 &DIE);
779 }
780 if (*LowPc > *HighPc) {
781 reportWarning("low_pc greater than high_pc. Range will be discarded.\n",
782 File, &DIE);
784 }
785
786
787 Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
789}
790
791
792
793unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
794 const DWARFFile &File, CompileUnit &Unit,
795 CompileUnit::DIEInfo &MyInfo,
796 unsigned Flags) {
797 switch (DIE.getTag()) {
798 case dwarf::DW_TAG_constant:
799 case dwarf::DW_TAG_variable:
800 return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags);
801 case dwarf::DW_TAG_subprogram:
802 case dwarf::DW_TAG_label:
803 return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags);
804 case dwarf::DW_TAG_base_type:
805
806
807 case dwarf::DW_TAG_imported_module:
808 case dwarf::DW_TAG_imported_declaration:
809 case dwarf::DW_TAG_imported_unit:
810
811 return Flags | TF_Keep;
812 default:
813 break;
814 }
815
817}
818
819
820
821
824 switch (Die.getTag()) {
825 case dwarf::DW_TAG_structure_type:
826 case dwarf::DW_TAG_class_type:
827 case dwarf::DW_TAG_union_type:
828 break;
829 default:
830 return;
831 }
832
834
837}
838
839
840
841
844 switch (Die.getTag()) {
845 case dwarf::DW_TAG_typedef:
846 case dwarf::DW_TAG_member:
847 case dwarf::DW_TAG_reference_type:
848 case dwarf::DW_TAG_ptr_to_member_type:
849 case dwarf::DW_TAG_pointer_type:
850 break;
851 default:
852 return;
853 }
854
856
858 return;
859
862}
863
864
865
866void DWARFLinker::lookForChildDIEsToKeep(
867 const DWARFDie &Die, CompileUnit &CU, unsigned Flags,
868 SmallVectorImpl &Worklist) {
869
870
871
872
873
875 Flags &= ~DWARFLinker::TF_ParentWalk;
876
877
878
879 if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk))
880 return;
881
882
883
884 for (auto Child : reverse(Die.children())) {
885
886
887 CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child);
888 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateChildIncompleteness,
889 &ChildInfo);
890 Worklist.emplace_back(Child, CU, Flags);
891 }
892}
893
896
897 if (.Ctxt || (Die.getTag() == dwarf::DW_TAG_namespace))
898 return false;
899
900 if (.hasODR() &&
.InModuleScope)
901 return false;
902
903 return .Incomplete && Info.Ctxt != CU.getInfo(Info.ParentIdx).Ctxt;
904}
905
906void DWARFLinker::markODRCanonicalDie(const DWARFDie &Die, CompileUnit &CU) {
907 CompileUnit::DIEInfo &Info = CU.getInfo(Die);
908
909 Info.ODRMarkingDone = true;
911 .Ctxt->hasCanonicalDIE())
912 Info.Ctxt->setHasCanonicalDIE();
913}
914
915
916
917void DWARFLinker::lookForRefDIEsToKeep(
918 const DWARFDie &Die, CompileUnit &CU, unsigned Flags,
919 const UnitListTy &Units, const DWARFFile &File,
920 SmallVectorImpl &Worklist) {
921 bool UseOdr = (Flags & DWARFLinker::TF_DependencyWalk)
922 ? (Flags & DWARFLinker::TF_ODR)
923 : CU.hasODR();
924 DWARFUnit &Unit = CU.getOrigUnit();
925 DWARFDataExtractor Data = Unit.getDebugInfoExtractor();
926 const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
928
930 for (const auto &AttrSpec : Abbrev->attributes()) {
931 DWARFFormValue Val(AttrSpec.Form);
933 AttrSpec.Attr == dwarf::DW_AT_sibling) {
935 Unit.getFormParams());
936 continue;
937 }
938
939 Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit);
940 CompileUnit *ReferencedCU;
941 if (auto RefDie =
942 resolveDIEReference(File, Units, Val, Die, ReferencedCU)) {
943 CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefDie);
944
945
946
947
948
949
950
951
952
953
954 if (AttrSpec.Form != dwarf::DW_FORM_ref_addr &&
956 Info.Ctxt->hasCanonicalDIE())
957 continue;
958
959
961 Info.Ctxt->hasCanonicalDIE()))
962 Info.Prune = false;
963 ReferencedDIEs.emplace_back(RefDie, *ReferencedCU);
964 }
965 }
966
967 unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0;
968
969
970
971 for (auto &P : reverse(ReferencedDIEs)) {
972
973
974 CompileUnit::DIEInfo &Info = P.second.getInfo(P.first);
975 Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness,
977 Worklist.emplace_back(P.first, P.second,
978 DWARFLinker::TF_Keep |
979 DWARFLinker::TF_DependencyWalk | ODRFlag);
980 }
981}
982
983
984void DWARFLinker::lookForParentDIEsToKeep(
985 unsigned AncestorIdx, CompileUnit &CU, unsigned Flags,
986 SmallVectorImpl &Worklist) {
987
988 if (CU.getInfo(AncestorIdx).Keep)
989 return;
990
991 DWARFUnit &Unit = CU.getOrigUnit();
992 DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx);
993 Worklist.emplace_back(CU.getInfo(AncestorIdx).ParentIdx, CU, Flags);
994 Worklist.emplace_back(ParentDIE, CU, Flags);
995}
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
1024 const DWARFDie &Die, const DWARFFile &File,
1025 CompileUnit &Cu, unsigned Flags) {
1026
1028 Worklist.emplace_back(Die, Cu, Flags);
1029
1030 while (!Worklist.empty()) {
1031 WorklistItem Current = Worklist.pop_back_val();
1032
1033
1034 switch (Current.Type) {
1035 case WorklistItemType::UpdateChildIncompleteness:
1037 continue;
1038 case WorklistItemType::UpdateRefIncompleteness:
1040 continue;
1041 case WorklistItemType::LookForChildDIEsToKeep:
1042 lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist);
1043 continue;
1044 case WorklistItemType::LookForRefDIEsToKeep:
1045 lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File,
1046 Worklist);
1047 continue;
1048 case WorklistItemType::LookForParentDIEsToKeep:
1049 lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags,
1050 Worklist);
1051 continue;
1052 case WorklistItemType::MarkODRCanonicalDie:
1053 markODRCanonicalDie(Current.Die, Current.CU);
1054 continue;
1055 case WorklistItemType::LookForDIEsToKeep:
1056 break;
1057 }
1058
1059 unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die);
1060 CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx);
1061
1062 if (MyInfo.Prune) {
1063
1064
1065 if (Current.Flags & TF_DependencyWalk)
1066 MyInfo.Prune = false;
1067 else
1068 continue;
1069 }
1070
1071
1072
1073 bool AlreadyKept = MyInfo.Keep;
1074 if ((Current.Flags & TF_DependencyWalk) && AlreadyKept)
1075 continue;
1076
1077 if (!(Current.Flags & TF_DependencyWalk))
1078 Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU,
1079 MyInfo, Current.Flags);
1080
1081
1082
1083
1084 if (!(Current.Flags & TF_DependencyWalk) ||
1085 (MyInfo.ODRMarkingDone && !MyInfo.Keep)) {
1086 if (Current.CU.hasODR() || MyInfo.InModuleScope)
1087 Worklist.emplace_back(Current.Die, Current.CU,
1088 WorklistItemType::MarkODRCanonicalDie);
1089 }
1090
1091
1092
1093
1094 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1095 WorklistItemType::LookForChildDIEsToKeep);
1096
1097 if (AlreadyKept || !(Current.Flags & TF_Keep))
1098 continue;
1099
1100
1101
1102 MyInfo.Keep = true;
1103
1104
1105 MyInfo.Incomplete =
1106 Current.Die.getTag() != dwarf::DW_TAG_subprogram &&
1107 Current.Die.getTag() != dwarf::DW_TAG_member &&
1108 dwarf::toUnsigned(Current.Die.find(dwarf::DW_AT_declaration), 0);
1109
1110
1111
1112
1113 Worklist.emplace_back(Current.Die, Current.CU, Current.Flags,
1114 WorklistItemType::LookForRefDIEsToKeep);
1115
1116 bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR)
1117 : Current.CU.hasODR();
1118 unsigned ODRFlag = UseOdr ? TF_ODR : 0;
1119 unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag;
1120
1121
1122 Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags);
1123 }
1124}
1125
1126#ifndef NDEBUG
1127
1128
1134
1135
1136
1138 std::vector Worklist;
1139 Worklist.push_back(CU.getOrigUnit().getUnitDIE());
1140
1141
1142 std::vector BrokenLinks;
1143
1144 while (!Worklist.empty()) {
1145 const DWARFDie Current = Worklist.back();
1146 Worklist.pop_back();
1147
1148 const bool CurrentDieIsKept = CU.getInfo(Current).Keep;
1149
1151 Worklist.push_back(Child);
1152
1153 const bool ChildDieIsKept = CU.getInfo(Child).Keep;
1154 if (!CurrentDieIsKept && ChildDieIsKept)
1155 BrokenLinks.emplace_back(Current, Child);
1156 }
1157 }
1158
1159 if (!BrokenLinks.empty()) {
1160 for (BrokenLink Link : BrokenLinks) {
1162 "Found invalid link in keep chain between {0:x} and {1:x}\n",
1163 Link.Parent.getOffset(), Link.Child.getOffset());
1164
1165 errs() << "Parent:";
1166 Link.Parent.dump(errs(), 0, {});
1167 CU.getInfo(Link.Parent).dump();
1168
1169 errs() << "Child:";
1170 Link.Child.dump(errs(), 2, {});
1171 CU.getInfo(Link.Child).dump();
1172 }
1174 }
1175}
1176#endif
1177
1178
1179
1180
1181
1182
1183
1184void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
1185
1186 FoldingSetNodeID ID;
1187 Abbrev.Profile(ID);
1188 void *InsertToken;
1189 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
1190
1191
1192 if (InSet) {
1193
1194 Abbrev.setNumber(InSet->getNumber());
1195 } else {
1196
1197 Abbreviations.push_back(
1198 std::make_unique(Abbrev.getTag(), Abbrev.hasChildren()));
1199 for (const auto &Attr : Abbrev.getData())
1200 Abbreviations.back()->AddAttribute(Attr);
1201 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
1202
1203 Abbrev.setNumber(Abbreviations.size());
1204 Abbreviations.back()->setNumber(Abbreviations.size());
1205 }
1206}
1207
1208unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
1209 AttributeSpec AttrSpec,
1210 const DWARFFormValue &Val,
1211 const DWARFUnit &U,
1212 AttributesInfo &Info) {
1215 return 0;
1217 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
1219 } else {
1221
1222 if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
1223 Info.HasAppleOrigin = true;
1224 if (std::optional FileName =
1225 ObjFile.Addresses->getLibraryInstallName()) {
1226 StringEntry = DebugStrPool.getEntry(*FileName);
1227 }
1228 }
1229
1230
1231 if (AttrSpec.Attr == dwarf::DW_AT_name)
1233 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
1234 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
1236 if (U.getVersion() >= 5) {
1237
1238 auto StringOffsetIndex =
1239 StringOffsetPool.getValueIndex(StringEntry.getOffset());
1240 return Die
1242 dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
1243 ->sizeOf(U.getFormParams());
1244 }
1245
1246 AttrSpec.Form = dwarf::DW_FORM_strp;
1247 }
1248 Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form,
1250 return 4;
1251}
1252
1253unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
1254 DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1255 unsigned AttrSize, const DWARFFormValue &Val, const DWARFFile &File,
1256 CompileUnit &Unit) {
1257 const DWARFUnit &U = Unit.getOrigUnit();
1258 uint64_t Ref;
1259 if (std::optional<uint64_t> Off = Val.getAsRelativeReference())
1260 Ref = Val.getUnit()->getOffset() + *Off;
1261 else if (Off = Val.getAsDebugInfoReference(); Off)
1263 else
1264 return 0;
1265
1266 DIE *NewRefDie = nullptr;
1267 CompileUnit *RefUnit = nullptr;
1268
1269 DWARFDie RefDie =
1270 Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit);
1271
1272
1273 if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
1274 return 0;
1275
1276 CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie);
1277
1278
1279
1280 if (isODRAttribute(AttrSpec.Attr) && RefInfo.Ctxt &&
1281 RefInfo.Ctxt->getCanonicalDIEOffset()) {
1282 assert(RefInfo.Ctxt->hasCanonicalDIE() &&
1283 "Offset to canonical die is set, but context is not marked");
1284 DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset());
1286 dwarf::DW_FORM_ref_addr, Attr);
1287 return U.getRefAddrByteSize();
1288 }
1289
1290 if (!RefInfo.Clone) {
1291
1292
1293 RefInfo.UnclonedReference = true;
1295 }
1296 NewRefDie = RefInfo.Clone;
1297
1298 if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
1300
1301
1302
1303
1304
1305 uint64_t Attr;
1306 if (Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) {
1307
1308 uint32_t NewRefOffset =
1309 RefUnit->getStartOffset() + NewRefDie->getOffset();
1310 Attr = NewRefOffset;
1312 dwarf::DW_FORM_ref_addr, DIEInteger(Attr));
1313 } else {
1314
1315 Attr = 0xBADDEF;
1316 Unit.noteForwardReference(
1317 NewRefDie, RefUnit, RefInfo.Ctxt,
1319 dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
1320 }
1321 return U.getRefAddrByteSize();
1322 }
1323
1325 dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
1326
1327 return AttrSize;
1328}
1329
1330void DWARFLinker::DIECloner::cloneExpression(
1331 DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File,
1332 CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer,
1333 int64_t AddrRelocAdjustment, bool IsLittleEndian) {
1335
1336 uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize();
1337
1338 uint64_t OpOffset = 0;
1339 for (auto &Op : Expression) {
1341
1342
1343 if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1344 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1345 Desc.Op[0] != Encoding::Size1))
1346 Linker.reportWarning("Unsupported DW_OP encoding.", File);
1347
1348 if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1349 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1350 Desc.Op[0] == Encoding::Size1)) {
1351
1353 uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
1354 assert(ULEBsize <= 16);
1355
1356
1358 OutputBuffer.push_back(Op.getCode());
1359 uint64_t RefOffset;
1362 } else {
1365 }
1366 uint32_t Offset = 0;
1367
1368
1369
1370 if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
1371 RefOffset += Unit.getOrigUnit().getOffset();
1372 auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
1373 CompileUnit::DIEInfo &Info = Unit.getInfo(RefDie);
1374 if (DIE *Clone = Info.Clone)
1375 Offset = Clone->getOffset();
1376 else
1377 Linker.reportWarning(
1378 "base type ref doesn't point to DW_TAG_base_type.", File);
1379 }
1380 uint8_t ULEB[16];
1382 if (RealSize > ULEBsize) {
1383
1385 Linker.reportWarning("base type ref doesn't fit.", File);
1386 }
1387 assert(RealSize == ULEBsize && "padding failed");
1388 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
1389 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
1390 } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_addrx) {
1391 if (std::optionalobject::SectionedAddress SA =
1392 Unit.getOrigUnit().getAddrOffsetSectionItem(
1394
1395
1396
1397
1398 OutputBuffer.push_back(dwarf::DW_OP_addr);
1399 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1402 ArrayRef<uint8_t> AddressBytes(
1403 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1404 OrigAddressByteSize);
1405 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1406 } else
1407 Linker.reportWarning("cannot read DW_OP_addrx operand.", File);
1408 } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_constx) {
1409 if (std::optionalobject::SectionedAddress SA =
1410 Unit.getOrigUnit().getAddrOffsetSectionItem(
1412
1413
1414
1415
1416 std::optional<uint8_t> OutOperandKind;
1417 switch (OrigAddressByteSize) {
1418 case 4:
1419 OutOperandKind = dwarf::DW_OP_const4u;
1420 break;
1421 case 8:
1422 OutOperandKind = dwarf::DW_OP_const8u;
1423 break;
1424 default:
1425 Linker.reportWarning(
1426 formatv(("unsupported address size: {0}."), OrigAddressByteSize),
1427 File);
1428 break;
1429 }
1430
1431 if (OutOperandKind) {
1432 OutputBuffer.push_back(*OutOperandKind);
1433 uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
1436 ArrayRef<uint8_t> AddressBytes(
1437 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1438 OrigAddressByteSize);
1439 OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
1440 }
1441 } else
1442 Linker.reportWarning("cannot read DW_OP_constx operand.", File);
1443 } else {
1444
1445 StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset());
1446 OutputBuffer.append(Bytes.begin(), Bytes.end());
1447 }
1449 }
1450}
1451
1452unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
1453 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
1454 CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
1455 bool IsLittleEndian) {
1456 DIEValueList *Attr;
1458 DIELoc *Loc = nullptr;
1459 DIEBlock *Block = nullptr;
1460 if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
1461 Loc = new (DIEAlloc) DIELoc;
1462 Linker.DIELocs.push_back(Loc);
1463 } else {
1464 Block = new (DIEAlloc) DIEBlock;
1465 Linker.DIEBlocks.push_back(Block);
1466 }
1467 Attr = Loc ? static_cast<DIEValueList *>(Loc)
1468 : static_cast<DIEValueList *>(Block);
1469
1470 DWARFUnit &OrigUnit = Unit.getOrigUnit();
1471
1472
1473 SmallVector<uint8_t, 32> Buffer;
1474 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
1478 DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
1479 IsLittleEndian, OrigUnit.getAddressByteSize());
1480 DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
1481 OrigUnit.getFormParams().Format);
1482 cloneExpression(Data, Expr, File, Unit, Buffer,
1483 Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian);
1484 Bytes = Buffer;
1485 }
1486 for (auto Byte : Bytes)
1488 dwarf::DW_FORM_data1, DIEInteger(Byte));
1489
1490
1491
1492
1493 if (Loc)
1494 Loc->setSize(Bytes.size());
1495 else
1496 Block->setSize(Bytes.size());
1497
1498 if (Loc)
1501 else {
1502
1503
1504 if ((AttrSpec.Form == dwarf::DW_FORM_block1 &&
1505 (Bytes.size() > UINT8_MAX)) ||
1506 (AttrSpec.Form == dwarf::DW_FORM_block2 &&
1507 (Bytes.size() > UINT16_MAX)) ||
1508 (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX)))
1509 AttrSpec.Form = dwarf::DW_FORM_block;
1510
1511 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
1512 dwarf::Form(AttrSpec.Form), Block);
1513 }
1514
1515 return Die.addValue(DIEAlloc, Value)->sizeOf(OrigUnit.getFormParams());
1516}
1517
1518unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
1519 DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
1520 unsigned AttrSize, const DWARFFormValue &Val, const CompileUnit &Unit,
1521 AttributesInfo &Info) {
1522 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
1523 Info.HasLowPc = true;
1524
1527 dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
1528 return AttrSize;
1529 }
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 std::optional AddrAttribute = InputDIE.find(AttrSpec.Attr);
1544 if (!AddrAttribute)
1546
1547 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
1548 if (!Addr) {
1549 Linker.reportWarning("Cann't read address attribute value.", ObjFile);
1550 return 0;
1551 }
1552
1553 if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1554 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
1555 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
1556 Addr = *LowPC;
1557 else
1558 return 0;
1559 } else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit &&
1560 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
1561 if (uint64_t HighPc = Unit.getHighPc())
1562 Addr = HighPc;
1563 else
1564 return 0;
1565 } else {
1566 *Addr += Info.PCOffset;
1567 }
1568
1569 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
1570 Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
1571 AttrSpec.Form, DIEInteger(*Addr));
1572 return Unit.getOrigUnit().getAddressByteSize();
1573 }
1574
1575 auto AddrIndex = AddrPool.getValueIndex(*Addr);
1576
1577 return Die
1578 .addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
1579 dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex))
1580 ->sizeOf(Unit.getOrigUnit().getFormParams());
1581}
1582
1583unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
1584 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
1585 CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
1586 unsigned AttrSize, AttributesInfo &Info) {
1588
1589
1590
1591 if (AttrSpec.Attr == dwarf::DW_AT_GNU_dwo_id ||
1592 AttrSpec.Attr == dwarf::DW_AT_dwo_id)
1593 return 0;
1594
1595
1596
1597 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
1598 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
1599 const llvm::DWARFDebugMacro *Macro = File.Dwarf->getDebugMacinfo();
1601 return 0;
1602 }
1603 }
1604
1605 if (AttrSpec.Attr == dwarf::DW_AT_macros) {
1606 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
1607 const llvm::DWARFDebugMacro *Macro = File.Dwarf->getDebugMacro();
1609 return 0;
1610 }
1611 }
1612
1613 if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1614
1615
1616
1617 Info.AttrStrOffsetBaseSeen = true;
1618 return Die
1619 .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1620 dwarf::DW_FORM_sec_offset, DIEInteger(8))
1621 ->sizeOf(Unit.getOrigUnit().getFormParams());
1622 }
1623
1624 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
1625
1626 auto Patch = Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1627 dwarf::DW_FORM_sec_offset,
1628 DIEInteger(*Val.getAsSectionOffset()));
1629
1630
1631 Unit.noteStmtSeqListAttribute(Patch);
1632
1633 return Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1634 }
1635
1637 if (auto OptionalValue = Val.getAsUnsignedConstant())
1638 Value = *OptionalValue;
1639 else if (auto OptionalValue = Val.getAsSignedConstant())
1640 Value = *OptionalValue;
1641 else if (auto OptionalValue = Val.getAsSectionOffset())
1642 Value = *OptionalValue;
1643 else {
1644 Linker.reportWarning(
1645 "Unsupported scalar attribute form. Dropping attribute.", File,
1646 &InputDIE);
1647 return 0;
1648 }
1649 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1650 Info.IsDeclaration = true;
1651
1652 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
1655 else
1658 return AttrSize;
1659 }
1660
1661 [[maybe_unused]] dwarf::Form OriginalForm = AttrSpec.Form;
1662 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
1663
1664
1665
1666 std::optional<uint64_t> Index = Val.getAsSectionOffset();
1667 if (!Index) {
1668 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1669 &InputDIE);
1670 return 0;
1671 }
1672 std::optional<uint64_t> Offset =
1673 Unit.getOrigUnit().getRnglistOffset(*Index);
1675 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1676 &InputDIE);
1677 return 0;
1678 }
1679
1681 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1682 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1683 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
1684
1685
1686
1687 std::optional<uint64_t> Index = Val.getAsSectionOffset();
1688 if (!Index) {
1689 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1690 &InputDIE);
1691 return 0;
1692 }
1693 std::optional<uint64_t> Offset =
1694 Unit.getOrigUnit().getLoclistOffset(*Index);
1696 Linker.reportWarning("Cannot read the attribute. Dropping.", File,
1697 &InputDIE);
1698 return 0;
1699 }
1700
1702 AttrSpec.Form = dwarf::DW_FORM_sec_offset;
1703 AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
1704 } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
1705 Die.getTag() == dwarf::DW_TAG_compile_unit) {
1706 std::optional<uint64_t> LowPC = Unit.getLowPc();
1707 if (!LowPC)
1708 return 0;
1709
1710 Value = Unit.getHighPc() - *LowPC;
1711 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
1712 Value = *Val.getAsSectionOffset();
1713 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
1714 Value = *Val.getAsSignedConstant();
1715 else if (auto OptionalValue = Val.getAsUnsignedConstant())
1716 Value = *OptionalValue;
1717 else {
1718 Linker.reportWarning(
1719 "Unsupported scalar attribute form. Dropping attribute.", File,
1720 &InputDIE);
1721 return 0;
1722 }
1723
1724 DIE::value_iterator Patch =
1727 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
1728 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
1729 Unit.noteRangeAttribute(Die, Patch);
1730 Info.HasRanges = true;
1734 Unit.getOrigUnit().getVersion())) {
1735
1736 CompileUnit::DIEInfo &LocationDieInfo = Unit.getInfo(InputDIE);
1737 Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
1738 ? LocationDieInfo.AddrAdjust
1739 : Info.PCOffset});
1740 } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
1741 Info.IsDeclaration = true;
1742
1743
1744 assert((Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) &&
1745 "Unhandled DW_FORM_rnglistx attribute");
1746
1747 return AttrSize;
1748}
1749
1750
1751
1752
1753unsigned DWARFLinker::DIECloner::cloneAttribute(
1754 DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
1755 CompileUnit &Unit, const DWARFFormValue &Val, const AttributeSpec AttrSpec,
1756 unsigned AttrSize, AttributesInfo &Info, bool IsLittleEndian) {
1757 const DWARFUnit &U = Unit.getOrigUnit();
1758
1759 switch (AttrSpec.Form) {
1760 case dwarf::DW_FORM_strp:
1761 case dwarf::DW_FORM_line_strp:
1762 case dwarf::DW_FORM_string:
1763 case dwarf::DW_FORM_strx:
1764 case dwarf::DW_FORM_strx1:
1765 case dwarf::DW_FORM_strx2:
1766 case dwarf::DW_FORM_strx3:
1767 case dwarf::DW_FORM_strx4:
1768 return cloneStringAttribute(Die, AttrSpec, Val, U, Info);
1769 case dwarf::DW_FORM_ref_addr:
1770 case dwarf::DW_FORM_ref1:
1771 case dwarf::DW_FORM_ref2:
1772 case dwarf::DW_FORM_ref4:
1773 case dwarf::DW_FORM_ref8:
1774 return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
1775 File, Unit);
1776 case dwarf::DW_FORM_block:
1777 case dwarf::DW_FORM_block1:
1778 case dwarf::DW_FORM_block2:
1779 case dwarf::DW_FORM_block4:
1780 case dwarf::DW_FORM_exprloc:
1781 return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1782 IsLittleEndian);
1783 case dwarf::DW_FORM_addr:
1784 case dwarf::DW_FORM_addrx:
1785 case dwarf::DW_FORM_addrx1:
1786 case dwarf::DW_FORM_addrx2:
1787 case dwarf::DW_FORM_addrx3:
1788 case dwarf::DW_FORM_addrx4:
1789 return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit,
1791 case dwarf::DW_FORM_data1:
1792 case dwarf::DW_FORM_data2:
1793 case dwarf::DW_FORM_data4:
1794 case dwarf::DW_FORM_data8:
1795 case dwarf::DW_FORM_udata:
1796 case dwarf::DW_FORM_sdata:
1797 case dwarf::DW_FORM_sec_offset:
1798 case dwarf::DW_FORM_flag:
1799 case dwarf::DW_FORM_flag_present:
1800 case dwarf::DW_FORM_rnglistx:
1801 case dwarf::DW_FORM_loclistx:
1802 case dwarf::DW_FORM_implicit_const:
1803 return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
1804 AttrSize, Info);
1805 default:
1806 Linker.reportWarning("Unsupported attribute form " +
1808 " in cloneAttribute. Dropping.",
1809 File, &InputDIE);
1810 }
1811
1812 return 0;
1813}
1814
1815void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
1816 const DIE *Die,
1817 DwarfStringPoolEntryRef Name,
1819 bool SkipPubSection) {
1820 std::optional Names =
1822 if (!Names)
1823 return;
1824 Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector),
1825 SkipPubSection);
1826 Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName),
1827 SkipPubSection);
1828 if (Names->ClassNameNoCategory)
1829 Unit.addObjCAccelerator(
1830 Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection);
1831 if (Names->MethodNameNoCategory)
1832 Unit.addNameAccelerator(
1833 Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection);
1834}
1835
1836static bool
1839 bool SkipPC) {
1840 switch (AttrSpec.Attr) {
1841 default:
1842 return false;
1843 case dwarf::DW_AT_low_pc:
1844 case dwarf::DW_AT_high_pc:
1845 case dwarf::DW_AT_ranges:
1846 return !Update && SkipPC;
1847 case dwarf::DW_AT_rnglists_base:
1848
1849
1850
1851
1852 return !Update;
1853 case dwarf::DW_AT_loclists_base:
1854
1855
1856
1857
1858 return !Update;
1859 case dwarf::DW_AT_location:
1860 case dwarf::DW_AT_frame_base:
1861 return !Update && SkipPC;
1862 }
1863}
1864
1870
1871DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
1873 int64_t PCOffset, uint32_t OutOffset,
1874 unsigned Flags, bool IsLittleEndian,
1875 DIE *Die) {
1876 DWARFUnit &U = Unit.getOrigUnit();
1877 unsigned Idx = U.getDIEIndex(InputDIE);
1879
1880
1881 if (!Unit.getInfo(Idx).Keep)
1882 return nullptr;
1883
1885 assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE");
1886 if (!Die) {
1887
1888
1889 if (.Clone)
1891 Die = Info.Clone;
1892 }
1893
1897 (Info.Ctxt->getCanonicalDIEOffset() == 0)) {
1898 if (.Ctxt->hasCanonicalDIE())
1899 Info.Ctxt->setHasCanonicalDIE();
1900
1901
1902
1903 Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
1904 }
1905
1906
1907 DWARFDataExtractor Data = U.getDebugInfoExtractor();
1908
1909
1910
1911 uint64_t NextOffset = (Idx + 1 < U.getNumDIEs())
1912 ? U.getDIEAtIndex(Idx + 1).getOffset()
1913 : U.getNextUnitOffset();
1914 AttributesInfo AttrInfo;
1915
1916
1917
1918
1919 SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
1921 DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
1922
1923
1924 ObjFile.Addresses->applyValidRelocs(DIECopy, Offset, Data.isLittleEndian());
1925
1926
1927
1929
1932
1933
1934 if (Die->getTag() == dwarf::DW_TAG_subprogram)
1935 PCOffset = Info.AddrAdjust;
1936 AttrInfo.PCOffset = PCOffset;
1937
1938 if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) {
1939 Flags |= TF_InFunctionScope;
1941 Flags |= TF_SkipPC;
1942 } else if (Abbrev->getTag() == dwarf::DW_TAG_variable) {
1943
1944
1945 if ((Flags & TF_InFunctionScope) && Info.InDebugMap)
1946 Flags &= ~TF_SkipPC;
1947
1948
1949 else if (.InDebugMap && Info.HasLocationExpressionAddr &&
1951 Flags |= TF_SkipPC;
1952 }
1953
1954 std::optional LibraryInstallName =
1955 ObjFile.Addresses->getLibraryInstallName();
1957 for (const auto &AttrSpec : Abbrev->attributes()) {
1960 U.getFormParams());
1961 continue;
1962 }
1963
1964 AttributeLinkedOffsetFixup CurAttrFixup;
1965 CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset;
1966 CurAttrFixup.LinkedOffsetFixupVal =
1967 Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1968
1969 DWARFFormValue Val = AttrSpec.getFormValue();
1970 uint64_t AttrSize = Offset;
1971 Val.extractValue(Data, &Offset, U.getFormParams(), &U);
1972 CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset;
1973 AttrSize = Offset - AttrSize;
1974
1975 uint64_t FinalAttrSize =
1976 cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
1977 AttrInfo, IsLittleEndian);
1978 if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
1979 AttributesFixups.push_back(CurAttrFixup);
1980
1981 OutOffset += FinalAttrSize;
1982 }
1983
1984 uint16_t Tag = InputDIE.getTag();
1985
1986
1987 const bool NeedsAppleOrigin = (Tag == dwarf::DW_TAG_compile_unit) &&
1988 LibraryInstallName.has_value() &&
1989 !AttrInfo.HasAppleOrigin;
1990 if (NeedsAppleOrigin) {
1991 auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
1993 dwarf::DW_FORM_strp, DIEInteger(StringEntry.getOffset()));
1995 OutOffset += 4;
1996 }
1997
1998
1999
2000
2001
2002 if ((Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
2003 Tag != dwarf::DW_TAG_compile_unit &&
2004 getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit,
2005 Tag != dwarf::DW_TAG_inlined_subroutine)) {
2006 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
2007 Unit.addNameAccelerator(Die, AttrInfo.MangledName,
2008 Tag == dwarf::DW_TAG_inlined_subroutine);
2009 if (AttrInfo.Name) {
2010 if (AttrInfo.NameWithoutTemplate)
2011 Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
2012 true);
2013 Unit.addNameAccelerator(Die, AttrInfo.Name,
2014 Tag == dwarf::DW_TAG_inlined_subroutine);
2015 }
2016 if (AttrInfo.Name)
2017 addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool,
2018 true);
2019
2020 } else if (Tag == dwarf::DW_TAG_namespace) {
2021 if (!AttrInfo.Name)
2022 AttrInfo.Name = DebugStrPool.getEntry("(anonymous namespace)");
2023 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
2024 } else if (Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) {
2025 Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
2026 } else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration) {
2027 bool Success = getDIENames(InputDIE, AttrInfo, DebugStrPool, File, Unit);
2028 uint64_t RuntimeLang =
2030 .value_or(0);
2031 bool ObjCClassIsImplementation =
2032 (RuntimeLang == dwarf::DW_LANG_ObjC ||
2033 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
2035 .value_or(0);
2036 if (Success && AttrInfo.Name && !AttrInfo.Name.getString().empty()) {
2038 Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
2039 Hash);
2040 }
2041
2042
2043 if (Success && AttrInfo.MangledName &&
2044 RuntimeLang == dwarf::DW_LANG_Swift &&
2045 !AttrInfo.MangledName.getString().empty() &&
2046 AttrInfo.MangledName != AttrInfo.Name) {
2047 auto Hash = djbHash(AttrInfo.MangledName.getString().data());
2048 Unit.addTypeAccelerator(Die, AttrInfo.MangledName,
2049 ObjCClassIsImplementation, Hash);
2050 }
2051 }
2052
2053
2054 bool HasChildren = false;
2055 for (auto Child : InputDIE.children()) {
2056 unsigned Idx = U.getDIEIndex(Child);
2057 if (Unit.getInfo(Idx).Keep) {
2058 HasChildren = true;
2059 break;
2060 }
2061 }
2062
2063 if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
2064 Die->getTag() == dwarf::DW_TAG_compile_unit) {
2065
2066 Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
2067 dwarf::DW_FORM_sec_offset, DIEInteger(8));
2068 OutOffset += 4;
2069 }
2070
2072 if (HasChildren)
2074
2075 Linker.assignAbbrev(NewAbbrev);
2077
2079
2080
2081 OutOffset += AbbrevNumberSize;
2082
2083
2084 for (AttributeLinkedOffsetFixup &F : AttributesFixups)
2085 F.LinkedOffsetFixupVal += AbbrevNumberSize;
2086
2087 for (AttributeLinkedOffsetFixup &F : AttributesFixups)
2088 ObjFile.Addresses->updateAndSaveValidRelocs(
2089 Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(),
2090 F.LinkedOffsetFixupVal, F.InputAttrStartOffset, F.InputAttrEndOffset);
2091
2092 if (!HasChildren) {
2093
2095 return Die;
2096 }
2097
2098
2099 for (auto Child : InputDIE.children()) {
2100 if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags,
2101 IsLittleEndian)) {
2103 OutOffset = Clone->getOffset() + Clone->getSize();
2104 }
2105 }
2106
2107
2108 OutOffset += sizeof(int8_t);
2109
2111 return Die;
2112}
2113
2114
2115
2116
2117void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
2120 return;
2121
2122 const auto &FunctionRanges = Unit.getFunctionRanges();
2123
2124
2125 AddressRanges LinkedFunctionRanges;
2126 for (const AddressRangeValuePair &Range : FunctionRanges)
2127 LinkedFunctionRanges.insert(
2129
2130
2131 if (!LinkedFunctionRanges.empty())
2132 TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
2133
2135 std::optional UnitRngListAttribute =
2136 Unit.getUnitRangesAttribute();
2137
2138 if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
2139 std::optional CachedRange;
2140 MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
2141
2142
2143
2144 for (PatchLocation &AttributePatch : AllRngListAttributes) {
2145
2146
2147 AddressRanges LinkedRanges;
2148 if (Expected OriginalRanges =
2149 Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) {
2150
2151 for (const auto &Range : *OriginalRanges) {
2152 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
2153 CachedRange = FunctionRanges.getRangeThatContains(Range.LowPC);
2154
2155
2156 if (!CachedRange) {
2157 reportWarning("inconsistent range data.", File);
2158 continue;
2159 }
2160
2161
2162 LinkedRanges.insert({Range.LowPC + CachedRange->Value,
2163 Range.HighPC + CachedRange->Value});
2164 }
2165 } else {
2167 reportWarning("invalid range list ignored.", File);
2168 }
2169
2170
2171 TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2172 Unit, LinkedRanges, AttributePatch, AddrPool);
2173 }
2174
2175
2176 if (UnitRngListAttribute.has_value())
2177 TheDwarfEmitter->emitDwarfDebugRangeListFragment(
2178 Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);
2179
2180
2181 TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
2182 }
2183}
2184
2185void DWARFLinker::DIECloner::generateUnitLocations(
2186 CompileUnit &Unit, const DWARFFile &File,
2187 ExpressionHandlerRef ExprHandler) {
2189 return;
2190
2192 Unit.getLocationAttributes();
2193
2194 if (AllLocListAttributes.empty())
2195 return;
2196
2197
2198 MCSymbol *EndLabel = Emitter->emitDwarfDebugLocListHeader(Unit);
2199
2200 for (auto &CurLocAttr : AllLocListAttributes) {
2201
2202
2203 Expected OriginalLocations =
2204 Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
2205
2206 if (!OriginalLocations) {
2208 Linker.reportWarning("Invalid location attribute ignored.", File);
2209 continue;
2210 }
2211
2213 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
2214 DWARFLocationExpression LinkedExpression;
2215
2216 if (CurExpression.Range) {
2217
2218 LinkedExpression.Range = {
2219 CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
2220 CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
2221 }
2222
2223
2224 LinkedExpression.Expr.reserve(CurExpression.Expr.size());
2225 ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
2226 CurLocAttr.RelocAdjustment);
2227
2228 LinkedLocationExpressions.push_back(LinkedExpression);
2229 }
2230
2231
2232 Emitter->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions,
2233 CurLocAttr, AddrPool);
2234 }
2235
2236
2237 Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
2238}
2239
2241 for (auto &V : Die.values())
2242 if (V.getAttribute() == dwarf::DW_AT_addr_base) {
2243 V = DIEValue(V.getAttribute(), V.getForm(), Offset);
2244 return;
2245 }
2246
2247 llvm_unreachable("Didn't find a DW_AT_addr_base in cloned DIE!");
2248}
2249
2250void DWARFLinker::DIECloner::emitDebugAddrSection(
2251 CompileUnit &Unit, const uint16_t DwarfVersion) const {
2252
2254 return;
2255
2256 if (DwarfVersion < 5)
2257 return;
2258
2259 if (AddrPool.getValues().empty())
2260 return;
2261
2262 MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit);
2264 DIEInteger(Emitter->getDebugAddrSectionSize()));
2265 Emitter->emitDwarfDebugAddrs(AddrPool.getValues(),
2266 Unit.getOrigUnit().getAddressByteSize());
2267 Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
2268}
2269
2270
2271
2272
2273
2279
2280
2281
2283 std::vector &Rows) {
2284 if (Seq.empty())
2285 return;
2286
2287
2288
2289 Seq.front().isStartSeqInOutput = true;
2290
2291 if (!Rows.empty() && Rows.back().Row.Address < Seq.front().Row.Address) {
2293 Seq.clear();
2294 return;
2295 }
2296
2299 Rows, [=](const TrackedRow &O) { return O.Row.Address < Front; });
2300
2301
2302
2303
2304
2305 if (InsertPoint != Rows.end() && InsertPoint->Row.Address == Front &&
2306 InsertPoint->Row.EndSequence) {
2307 *InsertPoint = Seq.front();
2308 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
2309 } else {
2310 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
2311 }
2312
2313 Seq.clear();
2314}
2315
2317 for (auto &V : Die.values())
2318 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
2319 V = DIEValue(V.getAttribute(), V.getForm(), Offset);
2320 return;
2321 }
2322
2323 llvm_unreachable("Didn't find DW_AT_stmt_list in cloned DIE!");
2324}
2325
2326void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
2327 DWARFUnit &OrigUnit = Unit.getOrigUnit();
2328 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
2329
2330 if (std::optional<uint64_t> MacroAttr =
2332 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2333 return;
2334 }
2335
2336 if (std::optional<uint64_t> MacroAttr =
2338 UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit));
2339 return;
2340 }
2341}
2342
2343void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2345 return;
2346
2347
2348 DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
2350 if (!StmtList)
2351 return;
2352
2353
2354 if (auto *OutputDIE = Unit.getOutputUnitDIE())
2356
2357 if (const DWARFDebugLine::LineTable *LT =
2358 ObjFile.Dwarf->getLineTableForUnit(&Unit.getOrigUnit())) {
2359
2360 DWARFDebugLine::LineTable LineTable;
2361
2362
2363 LineTable.Prologue = LT->Prologue;
2364
2365
2366 if (Linker.Options.Update) {
2367 LineTable.Rows = LT->Rows;
2368
2369
2370 if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence)
2371 LineTable.Rows.clear();
2372
2373 LineTable.Sequences = LT->Sequences;
2374
2375 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2376 DebugLineStrPool);
2377 } else {
2378
2379 std::vector InputRows;
2380 InputRows.reserve(LT->Rows.size());
2381 for (size_t i = 0; i < LT->Rows.size(); i++)
2382 InputRows.emplace_back(TrackedRow{LT->Rows[i], i, false});
2383
2384
2385 std::vector OutputRows;
2386 OutputRows.reserve(InputRows.size());
2387
2388
2389
2390 std::vector Seq;
2391 Seq.reserve(InputRows.size());
2392
2393 const auto &FunctionRanges = Unit.getFunctionRanges();
2394 std::optional CurrRange;
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407 for (size_t i = 0; i < InputRows.size(); i++) {
2408 TrackedRow TR = InputRows[i];
2409
2410
2411
2412
2413
2414
2415 if (!CurrRange || !CurrRange->Range.contains(TR.Row.Address.Address)) {
2416
2417
2418 uint64_t StopAddress =
2419 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
2420 CurrRange =
2421 FunctionRanges.getRangeThatContains(TR.Row.Address.Address);
2422 if (StopAddress != -1ULL && !Seq.empty()) {
2423
2424
2425 auto NextLine = Seq.back();
2426 NextLine.Row.Address.Address = StopAddress;
2427 NextLine.Row.EndSequence = 1;
2428 NextLine.Row.PrologueEnd = 0;
2429 NextLine.Row.BasicBlock = 0;
2430 NextLine.Row.EpilogueBegin = 0;
2431 Seq.push_back(NextLine);
2433 }
2434
2435 if (!CurrRange)
2436 continue;
2437 }
2438
2439
2440 if (TR.Row.EndSequence && Seq.empty())
2441 continue;
2442
2443
2444 TR.Row.Address.Address += CurrRange->Value;
2445 Seq.push_back(TR);
2446
2447 if (TR.Row.EndSequence)
2449 }
2450
2451
2452 LineTable.Rows.clear();
2453 LineTable.Rows.reserve(OutputRows.size());
2454 for (auto &TR : OutputRows)
2455 LineTable.Rows.push_back(TR.Row);
2456
2457
2458
2459 std::vector<uint64_t> OutputRowOffsets;
2460
2461
2462
2463 bool hasStmtSeq = Unit.getStmtSeqListAttributes().size() > 0;
2464 Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
2465 DebugLineStrPool,
2466 hasStmtSeq ? &OutputRowOffsets : nullptr);
2467
2468 if (hasStmtSeq) {
2469 assert(OutputRowOffsets.size() == OutputRows.size() &&
2470 "must have an offset for each row");
2471
2472
2473 DenseMap<uint64_t, unsigned> SeqOffToOrigRow;
2474
2475
2476
2477
2478 if (->Rows.empty())
2480
2481
2482 DenseMap<size_t, size_t> OrigRowToNewRow;
2483 for (size_t i = 0; i < OutputRows.size(); ++i)
2484 OrigRowToNewRow[OutputRows[i].OriginalRowIndex] = i;
2485
2486
2487
2488 for (const auto &StmtSeq : Unit.getStmtSeqListAttributes()) {
2489 uint64_t OrigStmtSeq = StmtSeq.get();
2490
2491 auto OrigRowIter = SeqOffToOrigRow.find(OrigStmtSeq);
2492 const uint64_t InvalidOffset =
2493 Unit.getOrigUnit().getFormParams().getDwarfMaxOffset();
2494
2495
2496
2497 if (OrigRowIter == SeqOffToOrigRow.end()) {
2498 StmtSeq.set(InvalidOffset);
2499 continue;
2500 }
2501 size_t OrigRowIndex = OrigRowIter->second;
2502
2503
2504 auto NewRowIter = OrigRowToNewRow.find(OrigRowIndex);
2505 if (NewRowIter == OrigRowToNewRow.end()) {
2506
2507
2508 StmtSeq.set(InvalidOffset);
2509 continue;
2510 }
2511
2512
2513 assert(NewRowIter->second < OutputRowOffsets.size() &&
2514 "New row index out of bounds");
2515 uint64_t NewStmtSeqOffset = OutputRowOffsets[NewRowIter->second];
2516
2517
2518 StmtSeq.set(NewStmtSeqOffset);
2519 }
2520 }
2521 }
2522
2523 } else
2524 Linker.reportWarning("Cann't load line table.", ObjFile);
2525}
2526
2527void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
2531
2532 for (const auto &Namespace : Unit.getNamespaces())
2533 AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() +
2534 Unit.getStartOffset());
2535
2536 for (const auto &Pubname : Unit.getPubnames())
2537 AppleNames.addName(Pubname.Name,
2538 Pubname.Die->getOffset() + Unit.getStartOffset());
2539
2540 for (const auto &Pubtype : Unit.getPubtypes())
2541 AppleTypes.addName(
2542 Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
2543 Pubtype.Die->getTag(),
2545 : 0,
2546 Pubtype.QualifiedNameHash);
2547
2548 for (const auto &ObjC : Unit.getObjC())
2549 AppleObjc.addName(ObjC.Name,
2550 ObjC.Die->getOffset() + Unit.getStartOffset());
2551 } break;
2553 TheDwarfEmitter->emitPubNamesForUnit(Unit);
2554 TheDwarfEmitter->emitPubTypesForUnit(Unit);
2555 } break;
2557 for (const auto &Namespace : Unit.getNamespaces())
2558 DebugNames.addName(
2562 Unit.getTag() == dwarf::DW_TAG_type_unit);
2563 for (const auto &Pubname : Unit.getPubnames())
2564 DebugNames.addName(
2565 Pubname.Name, Pubname.Die->getOffset(),
2567 Pubname.Die->getTag(), Unit.getUniqueID(),
2568 Unit.getTag() == dwarf::DW_TAG_type_unit);
2569 for (const auto &Pubtype : Unit.getPubtypes())
2570 DebugNames.addName(
2571 Pubtype.Name, Pubtype.Die->getOffset(),
2573 Pubtype.Die->getTag(), Unit.getUniqueID(),
2574 Unit.getTag() == dwarf::DW_TAG_type_unit);
2575 } break;
2576 }
2577 }
2578}
2579
2580
2581
2582
2583
2584
2585
2586void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) {
2587 DWARFContext &OrigDwarf = *Context.File.Dwarf;
2588 unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize();
2589
2590 StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
2592 return;
2593
2595 for (std::unique_ptr &Unit : Context.CompileUnits) {
2596 for (auto CurRange : Unit->getFunctionRanges())
2597 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
2598 }
2599
2600 DataExtractor Data(FrameData, OrigDwarf.isLittleEndian(), 0);
2601 uint64_t InputOffset = 0;
2602
2603
2604
2605 DenseMap<uint64_t, StringRef> LocalCIES;
2606
2607 while (Data.isValidOffset(InputOffset)) {
2608 uint64_t EntryOffset = InputOffset;
2609 uint32_t InitialLength = Data.getU32(&InputOffset);
2610 if (InitialLength == 0xFFFFFFFF)
2611 return reportWarning("Dwarf64 bits no supported", Context.File);
2612
2613 uint32_t CIEId = Data.getU32(&InputOffset);
2614 if (CIEId == 0xFFFFFFFF) {
2615
2616 StringRef CIEData = FrameData.substr(EntryOffset, InitialLength + 4);
2617 LocalCIES[EntryOffset] = CIEData;
2618
2619 InputOffset += InitialLength - 4;
2620 continue;
2621 }
2622
2623 uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
2624
2625
2626
2627
2628
2629 std::optional Range =
2630 AllUnitsRanges.getRangeThatContains(Loc);
2632
2633 InputOffset = EntryOffset + InitialLength + 4;
2634 continue;
2635 }
2636
2637
2638
2639 StringRef CIEData = LocalCIES[CIEId];
2640 if (CIEData.empty())
2641 return reportWarning("Inconsistent debug_frame content. Dropping.",
2643
2644
2645
2646 auto IteratorInserted = EmittedCIEs.insert(
2647 std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
2648
2649 if (IteratorInserted.second) {
2650 LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
2651 IteratorInserted.first->getValue() = LastCIEOffset;
2652 TheDwarfEmitter->emitCIE(CIEData);
2653 }
2654
2655
2656
2657
2658 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
2659 TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
2660 Loc + Range->Value,
2661 FrameData.substr(InputOffset, FDERemainingBytes));
2662 InputOffset += FDERemainingBytes;
2663 }
2664}
2665
2666uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
2667 CompileUnit &U,
2668 const DWARFFile &File,
2669 int ChildRecurseDepth) {
2670 const char *Name = nullptr;
2671 DWARFUnit *OrigUnit = &U.getOrigUnit();
2672 CompileUnit *CU = &U;
2673 std::optional Ref;
2674
2675 while (true) {
2677 Name = CurrentName;
2678
2679 if (!(Ref = DIE.find(dwarf::DW_AT_specification)) &&
2680 !(Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
2681 break;
2682
2684 break;
2685
2686 CompileUnit *RefCU;
2687 if (auto RefDIE =
2688 Linker.resolveDIEReference(File, CompileUnits, *Ref, DIE, RefCU)) {
2689 CU = RefCU;
2690 OrigUnit = &RefCU->getOrigUnit();
2691 DIE = RefDIE;
2692 }
2693 }
2694
2695 unsigned Idx = OrigUnit->getDIEIndex(DIE);
2696 if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
2697 Name = "(anonymous namespace)";
2698
2699 if (CU->getInfo(Idx).ParentIdx == 0 ||
2700
2701 CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
2702 dwarf::DW_TAG_module)
2703 return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));
2704
2705 DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
2707 (Name ? Name : ""),
2708 djbHash((Name ? "::" : ""),
2710}
2711
2714 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2715 if (DwoId)
2716 return *DwoId;
2717 return 0;
2718}
2719
2720static std::string
2723 if (ObjectPrefixMap.empty())
2724 return Path.str();
2725
2727 for (const auto &Entry : ObjectPrefixMap)
2729 break;
2730 return p.str().str();
2731}
2732
2733static std::string
2737 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
2738
2739 if (PCMFile.empty())
2740 return PCMFile;
2741
2742 if (ObjectPrefixMap)
2743 PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
2744
2745 return PCMFile;
2746}
2747
2748std::pair<bool, bool> DWARFLinker::isClangModuleRef(const DWARFDie &CUDie,
2749 std::string &PCMFile,
2750 LinkContext &Context,
2751 unsigned Indent,
2753 if (PCMFile.empty())
2754 return std::make_pair(false, false);
2755
2756
2758
2759 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
2760 if (Name.empty()) {
2762 reportWarning("Anonymous module skeleton CU for " + PCMFile,
2763 Context.File);
2764 return std::make_pair(true, true);
2765 }
2766
2767 if ( && Options.Verbose) {
2769 outs() << "Found clang module reference " << PCMFile;
2770 }
2771
2772 auto Cached = ClangModules.find(PCMFile);
2773 if (Cached != ClangModules.end()) {
2774
2775
2776
2777 if ( && Options.Verbose && (Cached->second != DwoId))
2778 reportWarning(Twine("hash mismatch: this object file was built against a "
2779 "different version of the module ") +
2780 PCMFile,
2782 if ( && Options.Verbose)
2783 outs() << " [cached].\n";
2784 return std::make_pair(true, true);
2785 }
2786
2787 return std::make_pair(true, false);
2788}
2789
2790bool DWARFLinker::registerModuleReference(const DWARFDie &CUDie,
2794 unsigned Indent) {
2795 std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);
2796 std::pair<bool, bool> IsClangModuleRef =
2797 isClangModuleRef(CUDie, PCMFile, Context, Indent, false);
2798
2799 if (!IsClangModuleRef.first)
2800 return false;
2801
2802 if (IsClangModuleRef.second)
2803 return true;
2804
2805 if (Options.Verbose)
2806 outs() << " ...\n";
2807
2808
2809
2810 ClangModules.insert({PCMFile, getDwoId(CUDie)});
2811
2812 if (Error E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded,
2813 Indent + 2)) {
2815 return false;
2816 }
2817 return true;
2818}
2819
2820Error DWARFLinker::loadClangModule(
2821 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
2823
2824 uint64_t DwoId = getDwoId(CUDie);
2825 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
2826
2827
2828 SmallString<0> Path(Options.PrependPath);
2832
2833
2834
2835 if (Loader == nullptr) {
2836 reportError("Could not load clang module: loader is not specified.\n",
2839 }
2840
2841 auto ErrOrObj = Loader(Context.File.FileName, Path);
2842 if (!ErrOrObj)
2844
2845 std::unique_ptr Unit;
2846 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
2847 OnCUDieLoaded(*CU);
2848
2849 auto ChildCUDie = CU->getUnitDIE();
2850 if (!ChildCUDie)
2851 continue;
2852 if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded,
2853 Indent)) {
2854 if (Unit) {
2855 std::string Err =
2856 (PCMFile +
2857 ": Clang modules are expected to have exactly 1 compile unit.\n");
2858 reportError(Err, Context.File);
2860 }
2861
2862
2863
2864 uint64_t PCMDwoId = getDwoId(ChildCUDie);
2865 if (PCMDwoId != DwoId) {
2866 if (Options.Verbose)
2867 reportWarning(
2868 Twine("hash mismatch: this object file was built against a "
2869 "different version of the module ") +
2870 PCMFile,
2872
2873 ClangModules[PCMFile] = PCMDwoId;
2874 }
2875
2876
2877 Unit = std::make_unique(*CU, UniqueUnitID++, !Options.NoODR,
2878 ModuleName);
2879 }
2880 }
2881
2882 if (Unit)
2883 Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
2884
2886}
2887
2888uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
2889 DWARFContext &DwarfContext, const DWARFFile &File, bool IsLittleEndian) {
2890 uint64_t OutputDebugInfoSize =
2891 (Emitter == nullptr) ? 0 : Emitter->getDebugInfoSectionSize();
2892 const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
2893
2894 for (auto &CurrentUnit : CompileUnits) {
2895 const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2896 const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
2897 auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
2898 CurrentUnit->setStartOffset(OutputDebugInfoSize);
2899 if (!InputDIE) {
2900 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2901 continue;
2902 }
2903 if (CurrentUnit->getInfo(0).Keep) {
2904
2905
2906 CurrentUnit->createOutputDIE();
2907 rememberUnitForMacroOffset(*CurrentUnit);
2908 cloneDIE(InputDIE, File, *CurrentUnit, 0 , UnitHeaderSize,
2909 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
2910 }
2911
2912 OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
2913
2914 if (Emitter != nullptr) {
2915
2916 generateLineTableForUnit(*CurrentUnit);
2917
2918 Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
2919
2921 continue;
2922
2923 Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);
2924
2925 auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
2926 SmallVectorImpl<uint8_t> &OutBytes,
2927 int64_t RelocAdjustment) {
2928 DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
2929 DataExtractor Data(SrcBytes, IsLittleEndian,
2930 OrigUnit.getAddressByteSize());
2931 cloneExpression(Data,
2932 DWARFExpression(Data, OrigUnit.getAddressByteSize(),
2933 OrigUnit.getFormParams().Format),
2934 File, *CurrentUnit, OutBytes, RelocAdjustment,
2935 IsLittleEndian);
2936 };
2937 generateUnitLocations(*CurrentUnit, File, ProcessExpr);
2938 emitDebugAddrSection(*CurrentUnit, DwarfVersion);
2939 }
2940 AddrPool.clear();
2941 }
2942
2943 if (Emitter != nullptr) {
2945
2946 Emitter->emitMacroTables(File.Dwarf.get(), UnitMacroMap, DebugStrPool);
2947
2948
2949 for (auto &CurrentUnit : CompileUnits) {
2950 CurrentUnit->fixupForwardReferences();
2951
2952 if (!CurrentUnit->getOutputUnitDIE())
2953 continue;
2954
2955 unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
2956
2958 CurrentUnit->getStartOffset());
2959 Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
2960 Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
2962 CurrentUnit->computeNextUnitOffset(DwarfVersion));
2963 }
2964 }
2965
2966 return OutputDebugInfoSize - StartOutputDebugInfoSize;
2967}
2968
2969void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) {
2970 TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data,
2972 TheDwarfEmitter->emitSectionContents(
2973 Dwarf.getDWARFObj().getRangesSection().Data,
2975 TheDwarfEmitter->emitSectionContents(
2977 TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(),
2979 TheDwarfEmitter->emitSectionContents(
2981 TheDwarfEmitter->emitSectionContents(
2982 Dwarf.getDWARFObj().getRnglistsSection().Data,
2984 TheDwarfEmitter->emitSectionContents(
2985 Dwarf.getDWARFObj().getLoclistsSection().Data,
2987}
2988
2991 ObjectContexts.emplace_back(LinkContext(File));
2992
2993 if (ObjectContexts.back().File.Dwarf) {
2994 for (const std::unique_ptr &CU :
2995 ObjectContexts.back().File.Dwarf->compile_units()) {
2997
2998 if (!CUDie)
2999 continue;
3000
3001 OnCUDieLoaded(*CU);
3002
3004 registerModuleReference(CUDie, ObjectContexts.back(), Loader,
3005 OnCUDieLoaded);
3006 }
3007 }
3008}
3009
3011 assert((Options.TargetDWARFVersion != 0) &&
3012 "TargetDWARFVersion should be set");
3013
3014
3015
3016 unsigned NumObjects = ObjectContexts.size();
3017
3018
3019
3020
3024
3025
3027
3028 for (LinkContext &OptContext : ObjectContexts) {
3029 if (Options.Verbose)
3030 outs() << "DEBUG MAP OBJECT: " << OptContext.File.FileName << "\n";
3031
3032 if (!OptContext.File.Dwarf)
3033 continue;
3034
3035 if (Options.VerifyInputDWARF)
3036 verifyInput(OptContext.File);
3037
3038
3039
3040
3041
3043 !OptContext.File.Addresses->hasValidRelocs()) {
3044 if (Options.Verbose)
3045 outs() << "No valid relocations found. Skipping.\n";
3046
3047
3048
3049 OptContext.Skip = true;
3050 continue;
3051 }
3052
3053
3054 if (!OptContext.File.Dwarf)
3055 continue;
3056
3057
3058 if (!OptContext.File.Dwarf->types_section_units().empty()) {
3059 reportWarning("type units are not currently supported: file will "
3060 "be skipped",
3061 OptContext.File);
3062 OptContext.Skip = true;
3063 continue;
3064 }
3065
3066
3067
3068 OptContext.CompileUnits.reserve(
3069 OptContext.File.Dwarf->getNumCompileUnits());
3070 for (const auto &CU : OptContext.File.Dwarf->compile_units()) {
3071 auto CUDie = CU->getUnitDIE(true);
3072 if (Options.Verbose) {
3073 outs() << "Input compilation unit:";
3076 DumpOpts.Verbose = Options.Verbose;
3077 CUDie.dump(outs(), 0, DumpOpts);
3078 }
3079 }
3080
3081 for (auto &CU : OptContext.ModuleUnits) {
3082 if (Error Err = cloneModuleUnit(OptContext, CU, ODRContexts, DebugStrPool,
3083 DebugLineStrPool, StringOffsetPool))
3084 reportWarning(toString(std::move(Err)), CU.File);
3085 }
3086 }
3087
3088
3089
3090
3091
3092
3093 const uint64_t ModulesEndOffset =
3094 (TheDwarfEmitter == nullptr) ? 0
3095 : TheDwarfEmitter->getDebugInfoSectionSize();
3096
3097
3098
3099 std::mutex ProcessedFilesMutex;
3100 std::condition_variable ProcessedFilesConditionVariable;
3101 BitVector ProcessedFiles(NumObjects, false);
3102
3103
3104
3105 auto AnalyzeLambda = [&](size_t I) {
3106 auto &Context = ObjectContexts[I];
3107
3108 if (Context.Skip || !Context.File.Dwarf)
3109 return;
3110
3111 for (const auto &CU : Context.File.Dwarf->compile_units()) {
3112
3113
3114 auto CUDie = CU->getUnitDIE(false);
3115 std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);
3116
3118 !isClangModuleRef(CUDie, PCMFile, Context, 0, true).first) {
3119 Context.CompileUnits.push_back(std::make_unique(
3120 *CU, UniqueUnitID++, !Options.NoODR && !Options.Update, ""));
3121 }
3122 }
3123
3124
3125 for (auto &CurrentUnit : Context.CompileUnits) {
3126 auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE();
3127 if (!CUDie)
3128 continue;
3130 *CurrentUnit, &ODRContexts.getRoot(), ODRContexts,
3131 ModulesEndOffset, Options.ParseableSwiftInterfaces,
3133 reportWarning(Warning, Context.File, &DIE);
3134 });
3135 }
3136 };
3137
3138
3140
3141
3142
3143
3144
3145 auto CloneLambda = [&](size_t I) {
3146 auto &OptContext = ObjectContexts[I];
3147 if (OptContext.Skip || !OptContext.File.Dwarf)
3148 return;
3149
3150
3151
3152
3153
3154
3156 for (auto &CurrentUnit : OptContext.CompileUnits)
3157 CurrentUnit->markEverythingAsKept();
3158 copyInvariantDebugSection(*OptContext.File.Dwarf);
3159 } else {
3160 for (auto &CurrentUnit : OptContext.CompileUnits) {
3161 lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits,
3162 CurrentUnit->getOrigUnit().getUnitDIE(),
3163 OptContext.File, *CurrentUnit, 0);
3164#ifndef NDEBUG
3166#endif
3167 }
3168 }
3169
3170
3171
3172
3173 if (OptContext.File.Addresses->hasValidRelocs() ||
3175 SizeByObject[OptContext.File.FileName].Input =
3177 SizeByObject[OptContext.File.FileName].Output =
3178 DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc,
3179 OptContext.CompileUnits, Options.Update, DebugStrPool,
3180 DebugLineStrPool, StringOffsetPool)
3181 .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
3182 OptContext.File.Dwarf->isLittleEndian());
3183 }
3184 if ((TheDwarfEmitter != nullptr) && !OptContext.CompileUnits.empty() &&
3186 patchFrameInfoForObject(OptContext);
3187
3188
3189 cleanupAuxiliarryData(OptContext);
3190 };
3191
3192 auto EmitLambda = [&]() {
3193
3194 if (TheDwarfEmitter != nullptr) {
3195 TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
3196 TheDwarfEmitter->emitStrings(DebugStrPool);
3197 TheDwarfEmitter->emitStringOffsets(StringOffsetPool.getValues(),
3198 Options.TargetDWARFVersion);
3199 TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
3200 for (AccelTableKind TableKind : Options.AccelTables) {
3201 switch (TableKind) {
3203 TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
3204 TheDwarfEmitter->emitAppleNames(AppleNames);
3205 TheDwarfEmitter->emitAppleTypes(AppleTypes);
3206 TheDwarfEmitter->emitAppleObjc(AppleObjc);
3207 break;
3209
3210
3211 break;
3213 TheDwarfEmitter->emitDebugNames(DebugNames);
3214 break;
3215 }
3216 }
3217 }
3218 };
3219
3220 auto AnalyzeAll = [&]() {
3221 for (unsigned I = 0, E = NumObjects; I != E; ++I) {
3222 AnalyzeLambda(I);
3223
3224 std::unique_lockstd::mutex LockGuard(ProcessedFilesMutex);
3226 ProcessedFilesConditionVariable.notify_one();
3227 }
3228 };
3229
3230 auto CloneAll = [&]() {
3231 for (unsigned I = 0, E = NumObjects; I != E; ++I) {
3232 {
3233 std::unique_lockstd::mutex LockGuard(ProcessedFilesMutex);
3234 if (!ProcessedFiles[I]) {
3235 ProcessedFilesConditionVariable.wait(
3236 LockGuard, [&]() { return ProcessedFiles[I]; });
3237 }
3238 }
3239
3240 CloneLambda(I);
3241 }
3242 EmitLambda();
3243 };
3244
3245
3246
3247
3248 if (Options.Threads == 1) {
3249 for (unsigned I = 0, E = NumObjects; I != E; ++I) {
3250 AnalyzeLambda(I);
3251 CloneLambda(I);
3252 }
3253 EmitLambda();
3254 } else {
3256 Pool.async(AnalyzeAll);
3257 Pool.async(CloneAll);
3258 Pool.wait();
3259 }
3260
3261 if (Options.Statistics) {
3262
3263 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
3264 for (auto &E : SizeByObject)
3265 Sorted.emplace_back(E.first(), E.second);
3267 return LHS.second.Output > RHS.second.Output;
3268 });
3269
3270 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
3271 const float Difference = Output - Input;
3272 const float Sum = Input + Output;
3273 if (Sum == 0)
3274 return 0;
3275 return (Difference / (Sum / 2));
3276 };
3277
3278 int64_t InputTotal = 0;
3279 int64_t OutputTotal = 0;
3280 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
3281
3282
3283 outs() << ".debug_info section size (in bytes)\n";
3284 outs() << "----------------------------------------------------------------"
3285 "---------------\n";
3286 outs() << "Filename Object "
3287 " dSYM Change\n";
3288 outs() << "----------------------------------------------------------------"
3289 "---------------\n";
3290
3291
3292 for (auto &E : Sorted) {
3293 InputTotal += E.second.Input;
3294 OutputTotal += E.second.Output;
3297 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
3298 }
3299
3300 outs() << "----------------------------------------------------------------"
3301 "---------------\n";
3302 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
3303 ComputePercentange(InputTotal, OutputTotal));
3304 outs() << "----------------------------------------------------------------"
3305 "---------------\n\n";
3306 }
3307
3309}
3310
3311Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
3316 unsigned Indent) {
3317 assert(Unit.Unit.get() != nullptr);
3318
3319 if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren())
3321
3324 outs() << "cloning .debug_info from " << Unit.File.FileName << "\n";
3325 }
3326
3327
3328 analyzeContextInfo(Unit.Unit->getOrigUnit().getUnitDIE(), 0, *(Unit.Unit),
3329 &ODRContexts.getRoot(), ODRContexts, 0,
3330 Options.ParseableSwiftInterfaces,
3332 reportWarning(Warning, Context.File, &DIE);
3333 });
3334
3335 Unit.Unit->markEverythingAsKept();
3336
3337
3339 CompileUnits.emplace_back(std::move(Unit.Unit));
3340 assert(TheDwarfEmitter);
3341 DIECloner(*this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
3342 Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
3343 .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
3344 Unit.File.Dwarf->isLittleEndian());
3346}
3347
3348void DWARFLinker::verifyInput(const DWARFFile &File) {
3350
3351 std::string Buffer;
3355 if (Options.InputVerificationHandler)
3356 Options.InputVerificationHandler(File, OS.str());
3357 }
3358}
3359
3360}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE, int ChildRecurseDepth=0)
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
dxil DXContainer Global Emitter
Provides ErrorOr smart pointer.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
The Input class is used to parse a yaml document into in-memory structs and vectors.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_while(PredicateT Pred) const
Return a copy of *this with the first N elements satisfying the given predicate removed.
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
const T & consume_front()
consume_front() - Returns the first element and drops it from ArrayRef.
void setChildrenFlag(bool hasChild)
value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V)
A structured debug information entry.
unsigned getAbbrevNumber() const
DIE & addChild(DIE *Child)
Add a child to the DIE.
LLVM_ABI DIEAbbrev generateAbbrev() const
Generate the abbreviation for this DIE.
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
void setAbbrevNumber(unsigned I)
Set the abbreviation number for this DIE.
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
void setOffset(unsigned O)
dwarf::Tag getTag() const
static LLVM_ABI std::optional< uint64_t > getDefiningParentDieOffset(const DIE &Die)
If Die has a non-null parent and the parent is not a declaration, return its offset.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
uint64_t getOffset() const
Get the absolute offset into the debug info or types section.
iterator_range< iterator > children() const
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Get the abbreviation declaration for this DIE.
dwarf::Tag getTag() const
LLVM_ABI std::optional< unsigned > getSubCode() const
uint64_t getEndOffset() const
Encoding
Size and signedness of expression operations' operands.
const Description & getDescription() const
uint64_t getRawOperand(unsigned Idx) const
bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const
Skip a form's value in DebugInfoData at the offset specified by OffsetPtr.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
void wait() override
Blocking wait for all the tasks to execute first.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
This class represents DWARF information for source file and it's address map.
std::map< std::string, std::string > ObjectPrefixMapTy
function_ref< void(const DWARFUnit &Unit)> CompileUnitHandlerTy
AccelTableKind
The kind of accelerator tables to be emitted.
@ DebugNames
.debug_names.
@ Apple
.apple_names, .apple_namespaces, .apple_types, .apple_objc.
@ Pub
.debug_pubnames, .debug_pubtypes
std::map< std::string, std::string > SwiftInterfacesMapTy
std::function< ErrorOr< DWARFFile & >( StringRef ContainerName, StringRef Path)> ObjFileLoaderTy
const SmallVector< T > & getValues() const
Stores all information relating to a compile unit, be it in its original instance in the object file ...
void addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader=nullptr, CompileUnitHandlerTy OnCUDieLoaded=[](const DWARFUnit &) {}) override
Add object file to be linked.
Definition DWARFLinker.cpp:2989
Error link() override
Link debug info for added objFiles. Object files are linked all together.
Definition DWARFLinker.cpp:3010
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.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
LLVM_ABI 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.
SmallVector< PatchLocation > RngListAttributesTy
std::vector< std::unique_ptr< CompileUnit > > UnitListTy
IndexedValuesMap< uint64_t > DebugDieValuePool
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
SmallVector< PatchLocation > LocListAttributesTy
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
bool isInToolchainDir(StringRef Path)
Make a best effort to determine whether Path is inside a toolchain.
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
LLVM_ABI bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, uint16_t DwarfVersion)
Check whether specified Form belongs to the FC class.
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
@ DW_FLAG_type_implementation
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
LLVM_ABI bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
LLVM_ABI bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
constexpr bool IsLittleEndianHost
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
static void verifyKeepChain(CompileUnit &CU)
Verify the keep chain by looking for DIEs that are kept but who's parent isn't.
Definition DWARFLinker.cpp:1137
FunctionAddr VTableAddr Value
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...
Definition DWARFLinker.cpp:842
static bool isTlsAddressCode(uint8_t DW_OP_Code)
Definition DWARFLinker.cpp:474
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
static void patchAddrBase(DIE &Die, DIEInteger Offset)
Definition DWARFLinker.cpp:2240
static std::string remapPath(StringRef Path, const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap)
Definition DWARFLinker.cpp:2721
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.
Definition DWARFLinker.cpp:63
static void insertLineSequence(std::vector< TrackedRow > &Seq, std::vector< TrackedRow > &Rows)
Insert the new line info sequence Seq into the current set of already linked line info Rows.
Definition DWARFLinker.cpp:2282
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.
Definition DWARFLinker.cpp:248
static std::string getPCMFile(const DWARFDie &CUDie, const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap)
Definition DWARFLinker.cpp:2734
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
static bool shouldSkipAttribute(bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, bool SkipPC)
Definition DWARFLinker.cpp:1837
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
static uint64_t getDebugInfoSize(DWARFContext &Dwarf)
Compute the total size of the debug info.
Definition DWARFLinker.cpp:53
static bool isTypeTag(uint16_t Tag)
Definition DWARFLinker.cpp:118
@ Dwarf
DWARF v5 .debug_names.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI std::optional< StringRef > StripTemplateParameters(StringRef Name)
If Name is the name of a templated function that includes template parameters, returns a substring of...
static uint64_t getDwoId(const DWARFDie &CUDie)
Definition DWARFLinker.cpp:2712
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, uint64_t ModulesEndOffset)
Definition DWARFLinker.cpp:331
@ Success
The lock was released successfully.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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...
Definition DWARFLinker.cpp:822
SingleThreadExecutor DefaultThreadPool
DWARFExpression::Operation Op
static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU, CompileUnit::DIEInfo &ChildInfo)
Definition DWARFLinker.cpp:353
ArrayRef(const T &OneElt) -> ArrayRef< T >
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
LLVM_ABI std::optional< ObjCSelectorNames > getObjCNamesIfSelector(StringRef Name)
If Name is the AT_name of a DIE which refers to an Objective-C selector, returns an instance of ObjCS...
static void analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, DeclContext *CurrentDeclContext, DeclContextTree &Contexts, uint64_t ModulesEndOffset, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Recursive helper to build the global DeclContext information and gather the child->parent relationshi...
Definition DWARFLinker.cpp:367
static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag)
Definition DWARFLinker.cpp:445
StrongType< NonRelocatableStringpool, OffsetsTag > OffsetsStringPool
static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU)
Definition DWARFLinker.cpp:894
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
static void analyzeImportedModule(const DWARFDie &DIE, CompileUnit &CU, DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, std::function< void(const Twine &, const DWARFDie &)> ReportWarning)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
Definition DWARFLinker.cpp:254
ContextWorklistItemType
The distinct types of work performed by the work loop in analyzeContextInfo.
Definition DWARFLinker.cpp:300
@ UpdateChildPruning
Definition DWARFLinker.cpp:302
@ AnalyzeContextInfo
Definition DWARFLinker.cpp:301
@ UpdatePruning
Definition DWARFLinker.cpp:303
void consumeError(Error Err)
Consume a Error without doing anything.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
static bool isODRAttribute(uint16_t Attr)
Definition DWARFLinker.cpp:103
static void constructSeqOffsettoOrigRowMapping(CompileUnit &Unit, const DWARFDebugLine::LineTable <, DenseMap< uint64_t, unsigned > &SeqOffToOrigRow)
Definition DWARFLinker.cpp:479
static void patchStmtList(DIE &Die, DIEInteger Offset)
Definition DWARFLinker.cpp:2316
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
Definition DWARFLinker.cpp:1865
int64_t LinkedOffsetFixupVal
Definition DWARFLinker.cpp:1866
uint64_t InputAttrStartOffset
Definition DWARFLinker.cpp:1867
uint64_t InputAttrEndOffset
Definition DWARFLinker.cpp:1868
A broken link in the keep chain.
Definition DWARFLinker.cpp:1129
DWARFDie Parent
Definition DWARFLinker.cpp:1131
BrokenLink(DWARFDie Parent, DWARFDie Child)
Definition DWARFLinker.cpp:1130
DWARFDie Child
Definition DWARFLinker.cpp:1132
This class represents an item in the work list.
Definition DWARFLinker.cpp:309
CompileUnit::DIEInfo * OtherInfo
Definition DWARFLinker.cpp:313
ContextWorklistItem(DWARFDie Die, DeclContext *Context, unsigned ParentIdx, bool InImportedModule)
Definition DWARFLinker.cpp:324
unsigned ParentIdx
Definition DWARFLinker.cpp:311
bool InImportedModule
Definition DWARFLinker.cpp:317
ContextWorklistItemType Type
Definition DWARFLinker.cpp:316
ContextWorklistItem(DWARFDie Die, ContextWorklistItemType T, CompileUnit::DIEInfo *OtherInfo=nullptr)
Definition DWARFLinker.cpp:319
DWARFDie Die
Definition DWARFLinker.cpp:310
DeclContext * Context
Definition DWARFLinker.cpp:314
Container for dump options that control which debug information will be dumped.
DIDumpOptions noImplicitRecursion() const
Return the options with RecurseDepth set to 0 unless explicitly required.
unsigned ChildRecurseDepth
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Standard .debug_line state machine structure.
Represents a series of contiguous machine instructions.
uint64_t StmtSeqOffset
The offset into the line table where this sequence begins.
SmallVector< Encoding > Op
Encoding for Op operands.
Hold the input and output of the debug info size in bytes.
Definition DWARFLinker.cpp:47
uint64_t Input
Definition DWARFLinker.cpp:48
uint64_t Output
Definition DWARFLinker.cpp:49
A helper struct to help keep track of the association between the input and output rows during line t...
Definition DWARFLinker.cpp:2274
DWARFDebugLine::Row Row
Definition DWARFLinker.cpp:2275
size_t OriginalRowIndex
Definition DWARFLinker.cpp:2276
bool isStartSeqInOutput
Definition DWARFLinker.cpp:2277
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?