LLVM: lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
21#include
22
23using namespace llvm;
26
33 AcceleratorRecords(&GlobalData.getAllocator()) {
37}
38
44 OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
46 AcceleratorRecords(&GlobalData.getAllocator()) {
49
50 DWARFDie CUDie = OrigUnit.getUnitDIE();
51 if (!CUDie)
52 return;
53
54 if (std::optional Val = CUDie.find(dwarf::DW_AT_language)) {
57 Language = LangVal;
58 }
59
60 if (.getOptions().NoODR && Language.has_value())
61 NoODR = false;
62
65 else
68}
69
71 LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());
72}
73
75
77 return;
78
79
80
81
82
83
84 for (DIEInfo &Info : DieInfoArray)
85 Info.unsetFlagsWhichSetDuringLiveAnalysis();
86
87 LowPc = std::nullopt;
88 HighPc = 0;
89 Labels.clear();
90 Ranges.clear();
91 Dependencies.reset(nullptr);
92
95 return;
96 }
97
98 AcceleratorRecords.erase();
102 DebugAddrIndexMap.clear();
103
107
109}
110
113 if (!InputUnitDIE)
114 return false;
115
116
117 DieInfoArray.resize(getOrigUnit().getNumDIEs());
118 OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);
119 if (!NoODR)
120 TypeEntries.resize(getOrigUnit().getNumDIEs());
121 return true;
122}
123
124void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
125 bool IsODRUnavailableFunctionScope) {
127
132 bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;
133
134 if (DieInfo.getIsInMouduleScope())
135 ChildInfo.setIsInMouduleScope();
136
137 if (DieInfo.getIsInFunctionScope())
138 ChildInfo.setIsInFunctionScope();
139
140 if (DieInfo.getIsInAnonNamespaceScope())
141 ChildInfo.setIsInAnonNamespaceScope();
142
143 switch (CurChild->getTag()) {
144 case dwarf::DW_TAG_module:
145 ChildInfo.setIsInMouduleScope();
146 if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
150 break;
151 case dwarf::DW_TAG_subprogram:
152 ChildInfo.setIsInFunctionScope();
153 if (!ChildIsODRUnavailableFunctionScope &&
154 !ChildInfo.getIsInMouduleScope()) {
155 if (find(CurChild,
156 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))
157 ChildIsODRUnavailableFunctionScope = true;
158 }
159 break;
160 case dwarf::DW_TAG_namespace: {
162
163 if (find(CurChild, dwarf::DW_AT_extension))
165
166 if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))
167 ChildInfo.setIsInAnonNamespaceScope();
168 } break;
169 default:
170 break;
171 }
172
174 ChildInfo.setTrackLiveness();
175
176 if ((!ChildInfo.getIsInAnonNamespaceScope() &&
177 !ChildIsODRUnavailableFunctionScope && !NoODR))
178 ChildInfo.setODRAvailable();
179
180 if (CurChild->hasChildren())
181 analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);
182 }
183}
184
187 if (LineTablePtr) {
188 if (LineTablePtr->hasFileAtIndex(FileIdx)) {
189
190
192 if (It == ResolvedFullPaths.end()) {
193 std::string OrigFileName;
194 bool FoundFileName = LineTablePtr->getFileNameByIndex(
195 FileIdx, getOrigUnit().getCompilationDir(),
197 OrigFileName);
198 (void)FoundFileName;
199 assert(FoundFileName && "Must get file name from line table");
200
201
202
205
206
207
209 ResolvedParentPaths.find(ParentPath);
210 if (ParentIt == ResolvedParentPaths.end()) {
213 ParentIt =
214 ResolvedParentPaths
215 .insert({ParentPath, GlobalStrings.insert(RealPath).first})
216 .first;
217 }
218
219
222
223 It = ResolvedFullPaths
224 .insert(std::make_pair(
225 FileIdx, GlobalStrings.insert(ResolvedPath).first))
226 .first;
227 }
228
229 return It->second;
230 }
231 }
232
233 return nullptr;
234}
235
238 ResolvedFullPaths.shrink_and_clear();
239 ResolvedParentPaths.clear();
244 Dependencies.reset(nullptr);
246}
247
248
249
251 if (!Language || Language != dwarf::DW_LANG_Swift)
252 return;
253
254 if (.getOptions().ParseableSwiftInterfaces)
255 return;
256
259 if (!Path.ends_with(".swiftinterface"))
260 return;
261
267 return;
268
269
271 if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))
272 return;
274 return;
275 if (std::optional Val = find(DieEntry, dwarf::DW_AT_name)) {
279 return;
280 }
281
282 auto &Entry = (*GlobalData.getOptions().ParseableSwiftInterfaces)[*Name];
283
287 ResolvedPath,
290 if (!Entry.empty() && Entry != ResolvedPath) {
292 warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +
293 ": " + Entry + " and " + Path + ".",
294 &Die);
295 }
296 Entry = std::string(ResolvedPath);
297 }
298}
299
307
316 continue;
317
318 assert(ChildInfo.getODRAvailable());
320 {this, CurChild},
321 ChildrenIndexAssigner.getChildIndex(*this, CurChild)))
322 return Err;
323
324 if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))
325 return Err;
326 }
327
329}
330
332 if (std::optional<SectionDescriptor *> DebugInfoSection =
334
335 (*DebugInfoSection)
336 ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
337
339 Patch.RefCU.getPointer()->getDieOutOffset(
341 });
342
343 (*DebugInfoSection)
344 ->ListDebugULEB128DieRefPatch.forEach(
346
348 Patch.RefCU.getPointer()->getDieOutOffset(
350 });
351 }
352
353 if (std::optional<SectionDescriptor *> DebugLocSection =
355 (*DebugLocSection)
356 ->ListDebugULEB128DieRefPatch.forEach(
358
360 Patch.RefCU.getPointer()->getDieOutOffset(
362 });
363 }
364
365 if (std::optional<SectionDescriptor *> DebugLocListsSection =
367 (*DebugLocListsSection)
368 ->ListDebugULEB128DieRefPatch.forEach(
370
372 Patch.RefCU.getPointer()->getDieOutOffset(
374 });
375 }
376}
377
384 RefCU = this;
387 RefCU = getUnitFromOffset(*Offset);
388 RefDIEOffset = *Offset;
389 } else {
390 return std::nullopt;
391 }
392
393 if (RefCU == this) {
394
397 } else if (RefCU && CanResolveInterCUReferences) {
398
399
400
402 if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)
404
405 if (std::optional<uint32_t> RefDieIdx =
408 } else {
410 }
411 return std::nullopt;
412}
413
417 if (std::optional AttrVal = find(DieEntry, Attr))
419
420 return std::nullopt;
421}
422
424 int64_t PcOffset) {
425 std::lock_guardstd::mutex Guard(RangesMutex);
426
427 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
428 if (LowPc)
429 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
430 else
431 LowPc = FuncLowPc + PcOffset;
432 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
433}
434
436 std::lock_guardstd::mutex Guard(LabelsMutex);
437 Labels.insert({LabelLowPc, PcOffset});
438}
439
441 if (getGlobalData().getOptions().UpdateIndexTablesOnly)
443
447 }
448
451}
452
453void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {
456
457 if (!DebugInfoSection.ListDebugLocPatch.empty()) {
461
462 uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);
463
464 DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
465
466
467 uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(
472
473 if (!OriginalLocations) {
475 return;
476 }
477
478 LinkedLocationExpressionsVector LinkedLocationExpressions;
480 LinkedLocationExpressionsWithOffsetPatches LinkedExpression;
481
482 if (CurExpression.Range) {
483
484 LinkedExpression.Expression.Range = {
487 }
488
491
495 LinkedExpression.Expression.Expr,
497 LinkedExpression.Patches);
498
499 LinkedLocationExpressions.push_back({LinkedExpression});
500 }
501
502
503 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
504 OutLocationSection.OS.tell());
505 emitLocListFragment(LinkedLocationExpressions, OutLocationSection);
506 });
507
508 if (OffsetAfterUnitLength > 0) {
509 assert(OffsetAfterUnitLength -
511 OffsetAfterUnitLength);
512 OutLocationSection.apply(
513 OffsetAfterUnitLength -
515 dwarf::DW_FORM_sec_offset,
516 OutLocationSection.OS.tell() - OffsetAfterUnitLength);
517 }
518 }
519}
520
521
522uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) {
524 return 0;
525
526
528 uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();
529
530
532
533
535
536
538
539
541
542 return OffsetAfterUnitLength;
543}
544
545
546uint64_t CompileUnit::emitLocListFragment(
547 const LinkedLocationExpressionsVector &LinkedLocationExpression,
549 uint64_t OffsetBeforeLocationExpression = 0;
550
552 uint64_t BaseAddress = 0;
553 if (std::optional<uint64_t> LowPC = getLowPc())
554 BaseAddress = *LowPC;
555
556 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
557 LinkedLocationExpression) {
558 if (LocExpression.Expression.Range) {
560 LocExpression.Expression.Range->LowPC - BaseAddress,
563 LocExpression.Expression.Range->HighPC - BaseAddress,
565 }
566
567 OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);
568 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
569 for (uint64_t *OffsetPtr : LocExpression.Patches)
570 *OffsetPtr += OffsetBeforeLocationExpression;
571
572 OutLocationSection.OS
573 << StringRef((const char *)LocExpression.Expression.Expr.data(),
574 LocExpression.Expression.Expr.size());
575 }
576
577
582 return OffsetBeforeLocationExpression;
583 }
584
585 std::optional<uint64_t> BaseAddress;
586 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
587 LinkedLocationExpression) {
588 if (LocExpression.Expression.Range) {
589
590
591 if (!BaseAddress) {
592 BaseAddress = LocExpression.Expression.Range->LowPC;
593
594
595 OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);
596 encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress),
597 OutLocationSection.OS);
598 }
599
600
601 OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);
602
603
604 encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,
605 OutLocationSection.OS);
606
607
608 encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,
609 OutLocationSection.OS);
610 } else
611
612 OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);
613
614 encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);
615 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
616 for (uint64_t *OffsetPtr : LocExpression.Patches)
617 *OffsetPtr += OffsetBeforeLocationExpression;
618
619 OutLocationSection.OS << StringRef(
620 (const char *)LocExpression.Expression.Expr.data(),
621 LocExpression.Expression.Expr.size());
622 }
623
624
625 OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);
626 return OffsetBeforeLocationExpression;
627}
628
629Error CompileUnit::emitDebugAddrSection() {
630 if (GlobalData.getOptions().UpdateIndexTablesOnly)
632
635
636 if (DebugAddrIndexMap.empty())
638
639 SectionDescriptor &OutAddrSection =
641
642
643
644
646 uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();
647
648
650
651
653
654
656
657
658 for (uint64_t AddrValue : DebugAddrIndexMap.getValues())
660
661
662 OutAddrSection.apply(
663 OffsetAfterSectionLength -
665 dwarf::DW_FORM_sec_offset,
666 OutAddrSection.OS.tell() - OffsetAfterSectionLength);
667
669}
670
672 if (getGlobalData().getOptions().UpdateIndexTablesOnly)
674
675
678 LinkedFunctionRanges.insert(
680
681 emitAranges(LinkedFunctionRanges);
682
686 }
687
690}
691
692void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
698
699 if (!DebugInfoSection.ListDebugRangePatch.empty()) {
700 std::optional CachedRange;
701 uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);
702
704 DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
706 CompileUnitRangePtr = &Patch;
707 } else {
708
709
711 uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(
716 InputDebugRangesSectionOffset)) {
717
718 for (const auto &Range : *InputRanges) {
719 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
720 CachedRange =
722
723
724 if (!CachedRange) {
725 warn("inconsistent range data.");
726 continue;
727 }
728
729
730 LinkedRanges.insert({Range.LowPC + CachedRange->Value,
731 Range.HighPC + CachedRange->Value});
732 }
733 } else {
735 warn("invalid range list ignored.");
736 }
737
738
739 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
740 OutRangeSection.OS.tell());
741 emitRangeListFragment(LinkedRanges, OutRangeSection);
742 }
743 });
744
745 if (CompileUnitRangePtr != nullptr) {
746
747
749 dwarf::DW_FORM_sec_offset,
750 OutRangeSection.OS.tell());
751 emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);
752 }
753
754 if (OffsetAfterUnitLength > 0) {
755 assert(OffsetAfterUnitLength -
757 OffsetAfterUnitLength);
758 OutRangeSection.apply(
759 OffsetAfterUnitLength -
761 dwarf::DW_FORM_sec_offset,
762 OutRangeSection.OS.tell() - OffsetAfterUnitLength);
763 }
764 }
765}
766
767uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) {
769 return 0;
770
771
773 uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();
774
775
777
778
780
781
783
784
786
787 return OffsetAfterUnitLength;
788}
789
790void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,
793
794 uint64_t BaseAddress = 0;
795 if (std::optional<uint64_t> LowPC = getLowPc())
796 BaseAddress = *LowPC;
797
798 for (const AddressRange &Range : LinkedRanges) {
803 }
804
805
808 return;
809 }
810
811 std::optional<uint64_t> BaseAddress;
812 for (const AddressRange &Range : LinkedRanges) {
813 if (!BaseAddress) {
814 BaseAddress = Range.start();
815
816
817 OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);
819 }
820
821
822 OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);
823
824
826
827
829 }
830
831
832 OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);
833}
834
835void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {
836 if (LinkedFunctionRanges.empty())
837 return;
838
839 SectionDescriptor &DebugInfoSection =
841 SectionDescriptor &OutArangesSection =
843
844
846 sizeof(int32_t) +
847 sizeof(int16_t) +
848 sizeof(int32_t) +
849 sizeof(int8_t) +
850 sizeof(int8_t);
851
854
855 OutArangesSection.emitOffset(0xBADDEF);
856 uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();
857
859 OutArangesSection.notePatch(
860 DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection});
861 OutArangesSection.emitOffset(0xBADDEF);
863 1);
864 OutArangesSection.emitIntVal(0, 1);
865
866 for (size_t Idx = 0; Idx < Padding; Idx++)
867 OutArangesSection.emitIntVal(0, 1);
868
869
870 for (const AddressRange &Range : LinkedFunctionRanges) {
875 }
876
877
880
881 uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();
882
883
884 OutArangesSection.apply(
885 OffsetAfterArangesLengthField -
887 dwarf::DW_FORM_sec_offset,
888 OffsetAfterArangesEnd - OffsetAfterArangesLengthField);
889}
890
894
896 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
897
898
899 if (std::optional<uint64_t> MacroAttr =
903 emitMacroTableImpl(Table, *MacroAttr, true);
904 }
905 }
906
907
908 if (std::optional<uint64_t> MacroAttr =
912 emitMacroTableImpl(Table, *MacroAttr, false);
913 }
914 }
915
917}
918
919void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
921 bool hasDWARFv5Header) {
923 hasDWARFv5Header
926
927 bool DefAttributeIsReported = false;
928 bool UndefAttributeIsReported = false;
929 bool ImportAttributeIsReported = false;
930
931 for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
932 if (OffsetToMacroTable == List.Offset) {
933
934 if (hasDWARFv5Header) {
935
936 OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));
937
938 uint8_t Flags = List.Header.Flags;
939
940
941 if (Flags &
942 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
943 Flags &=
944 ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
945 warn("opcode_operands_table is not supported yet.");
946 }
947
948
949 std::optional<uint64_t> StmtListOffset;
950 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
951
952 for (auto &V : getOutUnitDIE()->values()) {
953 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
954 StmtListOffset = V.getDIEInteger().getValue();
955 break;
956 }
957 }
958
959 if (!StmtListOffset) {
960 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
961 warn("couldn`t find line table for macro table.");
962 }
963 }
964
965
966 OutSection.emitIntVal(Flags, sizeof(Flags));
967
968
969 if (StmtListOffset) {
970 OutSection.notePatch(DebugOffsetPatch{
971 OutSection.OS.tell(),
972 &getOrCreateSectionDescriptor(DebugSectionKind::DebugLine)});
973
974
975 OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());
976 }
977 }
978
979
980 for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
981 if (MacroEntry.Type == 0) {
982 encodeULEB128(MacroEntry.Type, OutSection.OS);
983 continue;
984 }
985
986 uint8_t MacroType = MacroEntry.Type;
987 switch (MacroType) {
988 default: {
989 bool HasVendorSpecificExtension =
990 (!hasDWARFv5Header &&
991 MacroType == dwarf::DW_MACINFO_vendor_ext) ||
992 (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
993 MacroType <= dwarf::DW_MACRO_hi_user));
994
995 if (HasVendorSpecificExtension) {
996
997 OutSection.emitIntVal(MacroType, 1);
998
999
1000 encodeULEB128(MacroEntry.ExtConstant, OutSection.OS);
1001
1002
1003 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);
1004 } else
1005 warn("unknown macro type. skip.");
1006 } break;
1007
1008
1009
1010
1011
1012
1013 case dwarf::DW_MACRO_define:
1014 case dwarf::DW_MACRO_undef: {
1015
1016 OutSection.emitIntVal(MacroType, 1);
1017
1018
1019 encodeULEB128(MacroEntry.Line, OutSection.OS);
1020
1021
1022 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);
1023 } break;
1024 case dwarf::DW_MACRO_define_strp:
1025 case dwarf::DW_MACRO_undef_strp:
1026 case dwarf::DW_MACRO_define_strx:
1027 case dwarf::DW_MACRO_undef_strx: {
1028
1029
1030 switch (MacroType) {
1031 case dwarf::DW_MACRO_define_strx: {
1032 MacroType = dwarf::DW_MACRO_define_strp;
1033 if (!DefAttributeIsReported) {
1034 warn("DW_MACRO_define_strx unsupported yet. Convert to "
1035 "DW_MACRO_define_strp.");
1036 DefAttributeIsReported = true;
1037 }
1038 } break;
1039 case dwarf::DW_MACRO_undef_strx: {
1040 MacroType = dwarf::DW_MACRO_undef_strp;
1041 if (!UndefAttributeIsReported) {
1042 warn("DW_MACRO_undef_strx unsupported yet. Convert to "
1043 "DW_MACRO_undef_strp.");
1044 UndefAttributeIsReported = true;
1045 }
1046 } break;
1047 default:
1048
1049 break;
1050 }
1051
1052
1053 OutSection.emitIntVal(MacroType, 1);
1054
1055
1056 encodeULEB128(MacroEntry.Line, OutSection.OS);
1057
1058
1059 OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);
1060 break;
1061 }
1062 case dwarf::DW_MACRO_start_file: {
1063
1064 OutSection.emitIntVal(MacroType, 1);
1065
1066 encodeULEB128(MacroEntry.Line, OutSection.OS);
1067
1068 encodeULEB128(MacroEntry.File, OutSection.OS);
1069 } break;
1070 case dwarf::DW_MACRO_end_file: {
1071
1072 OutSection.emitIntVal(MacroType, 1);
1073 } break;
1074 case dwarf::DW_MACRO_import:
1075 case dwarf::DW_MACRO_import_sup: {
1076 if (!ImportAttributeIsReported) {
1077 warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "
1078 "yet. remove.");
1079 ImportAttributeIsReported = true;
1080 }
1081 } break;
1082 }
1083 }
1084
1085 return;
1086 }
1087 }
1088}
1089
1093 std::optional<int64_t> VarAddressAdjustment,
1096
1098 uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize();
1099
1101 for (auto &Op : InputExpression) {
1102 auto Desc = Op.getDescription();
1103
1104
1105 if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1106 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1107 Desc.Op[0] != Encoding::Size1))
1108 warn("unsupported DW_OP encoding.");
1109
1110 if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1111 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1112 Desc.Op[0] == Encoding::Size1)) {
1113
1114 assert(OpOffset < Op.getEndOffset());
1115 uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
1116 assert(ULEBsize <= 16);
1117
1118
1119 assert(.getSubCode() && "SubOps not yet supported");
1120 OutputExpression.push_back(Op.getCode());
1122 if (Desc.Op.size() == 1) {
1123 RefOffset = Op.getRawOperand(0);
1124 } else {
1125 OutputExpression.push_back(Op.getRawOperand(0));
1126 RefOffset = Op.getRawOperand(1);
1127 }
1130 unsigned RealSize = 0;
1131
1132
1133
1134 if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
1135 RefOffset += OrigUnit.getOffset();
1137 if (std::optional<uint32_t> Idx =
1138 OrigUnit.getDIEIndexForOffset(RefOffset))
1139 RefDieIdx = *Idx;
1140
1141
1142
1144
1145 RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);
1146
1147 Section.notePatchWithOffsetUpdate(
1149 RefDieIdx),
1150 PatchesOffsets);
1151 } else
1153
1154 if (RealSize > ULEBsize) {
1155
1157 warn("base type ref doesn't fit.");
1158 }
1159 assert(RealSize == ULEBsize && "padding failed");
1161 OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());
1162 } else if (().getOptions().UpdateIndexTablesOnly &&
1163 Op.getCode() == dwarf::DW_OP_addrx) {
1164 if (std::optionalobject::SectionedAddress SA =
1165 OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
1166
1167
1168
1169
1170 OutputExpression.push_back(dwarf::DW_OP_addr);
1171 uint64_t LinkedAddress = SA->Address + VarAddressAdjustment.value_or(0);
1175 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1176 OrigAddressByteSize);
1177 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
1178 } else
1179 warn("cann't read DW_OP_addrx operand.");
1180 } else if (().getOptions().UpdateIndexTablesOnly &&
1181 Op.getCode() == dwarf::DW_OP_constx) {
1182 if (std::optionalobject::SectionedAddress SA =
1183 OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
1184
1185
1186
1187
1188 std::optional<uint8_t> OutOperandKind;
1189 switch (OrigAddressByteSize) {
1190 case 2:
1191 OutOperandKind = dwarf::DW_OP_const2u;
1192 break;
1193 case 4:
1194 OutOperandKind = dwarf::DW_OP_const4u;
1195 break;
1196 case 8:
1197 OutOperandKind = dwarf::DW_OP_const8u;
1198 break;
1199 default:
1201 formatv(("unsupported address size: {0}."), OrigAddressByteSize));
1202 break;
1203 }
1204
1205 if (OutOperandKind) {
1206 OutputExpression.push_back(*OutOperandKind);
1208 SA->Address + VarAddressAdjustment.value_or(0);
1212 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1213 OrigAddressByteSize);
1214 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
1215 }
1216 } else
1217 warn("cann't read DW_OP_constx operand.");
1218 } else {
1219
1221 InputExpression.getData().slice(OpOffset, Op.getEndOffset());
1222 OutputExpression.append(Bytes.begin(), Bytes.end());
1223 }
1224 OpOffset = Op.getEndOffset();
1225 }
1226}
1227
1229 std::optional<std::reference_wrapper> TargetTriple,
1230 TypeUnit *ArtificialTypeUnit) {
1232
1234 if (!OrigUnitDIE.isValid())
1236
1238 if (ArtificialTypeUnit)
1240
1241
1242 std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(
1244 std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);
1246
1247 if (!TargetTriple.has_value() || (OutCUDie.first == nullptr))
1249
1251 return Err;
1252
1254 return Err;
1255
1258 return Err;
1259
1260
1261
1262
1263
1265 return Err;
1266
1268 return Err;
1269
1270 if (Error Err = emitDebugAddrSection())
1271 return Err;
1272
1273
1277
1279 return Err;
1280
1282}
1283
1286 uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,
1287 std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,
1288 TypeUnit *ArtificialTypeUnit) {
1291
1292 bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();
1293 bool NeedToCloneTypeDIE =
1294 (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&
1295 Info.needToPlaceInTypeTable();
1296 std::pair<DIE *, TypeEntry *> ClonedDIE;
1297
1298 DIEGenerator PlainDIEGenerator(Allocator, *this);
1299
1300 if (NeedToClonePlainDIE)
1301
1302
1303 ClonedDIE.first = createPlainDIEandCloneAttributes(
1304 InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,
1305 VarAddressAdjustment);
1306 if (NeedToCloneTypeDIE) {
1307
1308
1309 assert(ArtificialTypeUnit != nullptr);
1312
1313 ClonedDIE.second = createTypeDIEandCloneAttributes(
1314 InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,
1315 ArtificialTypeUnit);
1316 }
1318 ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;
1319
1320 bool HasPlainChildrenToClone =
1321 (ClonedDIE.first && Info.getKeepPlainChildren());
1322
1323 bool HasTypeChildrenToClone =
1324 ((ClonedDIE.second ||
1325 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&
1326 Info.getKeepTypeChildren());
1327
1328
1329 if (HasPlainChildrenToClone || HasTypeChildrenToClone) {
1334 std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(
1335 CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,
1336 VarAddressAdjustment, Allocator, ArtificialTypeUnit);
1337
1338 if (ClonedChild.first) {
1339 OutOffset =
1340 ClonedChild.first->getOffset() + ClonedChild.first->getSize();
1341 PlainDIEGenerator.addChild(ClonedChild.first);
1342 }
1343 }
1344 assert(ClonedDIE.first == nullptr ||
1345 HasPlainChildrenToClone == ClonedDIE.first->hasChildren());
1346
1347
1348 if (HasPlainChildrenToClone)
1349 OutOffset += sizeof(int8_t);
1350 }
1351
1352
1353 if (ClonedDIE.first != nullptr)
1354 ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());
1355
1356 return ClonedDIE;
1357}
1358
1359DIE *CompileUnit::createPlainDIEandCloneAttributes(
1361 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
1362 std::optional<int64_t> &VarAddressAdjustment) {
1365 DIE *ClonedDIE = nullptr;
1366 bool HasLocationExpressionAddress = false;
1367 if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {
1368
1369 FuncAddressAdjustment =
1371 getDIE(InputDieEntry), false);
1372 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {
1373
1374 std::optional<uint64_t> lowPC =
1376 if (lowPC) {
1378 if (It != Labels.end())
1379 FuncAddressAdjustment = It->second;
1380 }
1381 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {
1382
1383 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
1385 getDIE(InputDieEntry), false);
1386
1387 HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;
1388 if (LocExprAddrAndRelocAdjustment.first &&
1389 LocExprAddrAndRelocAdjustment.second)
1390 VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;
1391 }
1392
1393 ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);
1394
1395
1396
1398
1399
1400 DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,
1401 PlainDIEGenerator, FuncAddressAdjustment,
1402 VarAddressAdjustment,
1403 HasLocationExpressionAddress);
1404 AttributesCloner.clone();
1405
1406
1407 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);
1408 AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,
1409 nullptr);
1410
1411 OutOffset =
1412 AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());
1413
1414 return ClonedDIE;
1415}
1416
1417
1418DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,
1420 dwarf::Tag DieTag, bool IsDeclaration,
1421 bool IsParentDeclaration) {
1422 DIE *DefinitionDie = TypeDescriptor->Die;
1423
1424 if (DefinitionDie)
1425 return nullptr;
1426
1427 DIE *DeclarationDie = TypeDescriptor->DeclarationDie;
1429
1430 if (IsDeclaration && !DeclarationDie) {
1431
1432 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1433 if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,
1434 NewDie))
1435 return NewDie;
1436 } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
1437
1438
1440 OldParentIsDeclaration, false)) {
1441 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1443 return NewDie;
1444 }
1445 } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
1446
1447
1448 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1449 if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,
1450 NewDie))
1451 return NewDie;
1452 } else if (!IsDeclaration && !IsParentDeclaration) {
1453
1454 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1455 if (TypeDescriptor->Die.compare_exchange_strong(DefinitionDie, NewDie)) {
1457 return NewDie;
1458 }
1459 }
1460
1461 return nullptr;
1462}
1463
1464TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
1465 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
1467 assert(ArtificialTypeUnit != nullptr);
1468 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
1469
1471 assert(Entry != nullptr);
1472 assert(ClonedParentTypeDIE != nullptr);
1473 TypeEntryBody *EntryBody =
1475 Entry, ClonedParentTypeDIE);
1477
1478 bool IsDeclaration =
1480
1481 bool ParentIsDeclaration = false;
1482 if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())
1483 ParentIsDeclaration =
1485
1486 DIE *OutDIE =
1487 allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),
1488 IsDeclaration, ParentIsDeclaration);
1489
1490 if (OutDIE != nullptr) {
1491 assert(ArtificialTypeUnit != nullptr);
1493
1494 DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,
1495 InputDieEntry, TypeDIEGenerator,
1496 std::nullopt, std::nullopt, false);
1497 AttributesCloner.clone();
1498
1499
1500 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,
1501 ArtificialTypeUnit);
1502 AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,
1503 Entry);
1504
1505
1506
1507 OutDIE->setSize(AttributesCloner.getOutOffset() + 1);
1508 }
1509
1511}
1512
1516 if (InputLineTable == nullptr) {
1518 warn("cann't load line table.");
1520 }
1521
1523
1524
1527
1528
1529 if (getGlobalData().getOptions().UpdateIndexTablesOnly) {
1530 OutLineTable.Rows = InputLineTable->Rows;
1531
1532
1533 if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)
1534 OutLineTable.Rows.clear();
1535
1537 } else {
1538
1539 std::vectorDWARFDebugLine::Row NewRows;
1540 NewRows.reserve(InputLineTable->Rows.size());
1541
1542
1543
1544 std::vectorDWARFDebugLine::Row Seq;
1545
1547 std::optional CurrRange;
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1561
1562
1563
1564
1565
1566 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {
1567
1568
1570 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
1571 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
1572 if (StopAddress != -1ULL && !Seq.empty()) {
1573
1574
1575 auto NextLine = Seq.back();
1576 NextLine.Address.Address = StopAddress;
1577 NextLine.EndSequence = 1;
1578 NextLine.PrologueEnd = 0;
1579 NextLine.BasicBlock = 0;
1580 NextLine.EpilogueBegin = 0;
1581 Seq.push_back(NextLine);
1582 insertLineSequence(Seq, NewRows);
1583 }
1584
1585 if (!CurrRange)
1586 continue;
1587 }
1588
1589
1590 if (Row.EndSequence && Seq.empty())
1591 continue;
1592
1593
1594 Row.Address.Address += CurrRange->Value;
1595 Seq.emplace_back(Row);
1596
1597 if (Row.EndSequence)
1598 insertLineSequence(Seq, NewRows);
1599 }
1600
1601 OutLineTable.Rows = std::move(NewRows);
1602 }
1603
1604 return emitDebugLine(TargetTriple, OutLineTable);
1605}
1606
1607void CompileUnit::insertLineSequence(std::vectorDWARFDebugLine::Row &Seq,
1608 std::vectorDWARFDebugLine::Row &Rows) {
1609 if (Seq.empty())
1610 return;
1611
1612 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
1614 Seq.clear();
1615 return;
1616 }
1617
1621
1622
1623
1624
1625
1626 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
1627 InsertPoint->EndSequence) {
1628 *InsertPoint = Seq.front();
1629 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
1630 } else {
1631 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
1632 }
1633
1634 Seq.clear();
1635}
1636
1637#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1644 break;
1647 break;
1650 break;
1651 case Both:
1653 break;
1654 }
1655
1656 llvm::errs() << " Keep: " << getKeep();
1657 llvm::errs() << " KeepPlainChildren: " << getKeepPlainChildren();
1658 llvm::errs() << " KeepTypeChildren: " << getKeepTypeChildren();
1659 llvm::errs() << " IsInMouduleScope: " << getIsInMouduleScope();
1660 llvm::errs() << " IsInFunctionScope: " << getIsInFunctionScope();
1661 llvm::errs() << " IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();
1662 llvm::errs() << " ODRAvailable: " << getODRAvailable();
1663 llvm::errs() << " TrackLiveness: " << getTrackLiveness();
1665}
1666#endif
1667
1668std::optional<std::pair<StringRef, StringRef>>
1673 FileIdx = *Val;
1674 else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())
1675 FileIdx = *Val;
1676 else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())
1677 FileIdx = *Val;
1678 else
1679 return std::nullopt;
1680
1682}
1683
1684std::optional<std::pair<StringRef, StringRef>>
1686 FileNamesCache::iterator FileData = FileNames.find(FileIdx);
1687 if (FileData != FileNames.end())
1688 return std::make_pair(StringRef(FileData->second.first),
1689 StringRef(FileData->second.second));
1690
1693 if (LineTable->hasFileAtIndex(FileIdx)) {
1694
1696 LineTable->Prologue.getFileNameEntry(FileIdx);
1697
1699 if () {
1701 return std::nullopt;
1702 }
1703
1704 std::string FileName = *Name;
1706 FileNamesCache::iterator FileData =
1708 .insert(std::make_pair(
1709 FileIdx,
1710 std::make_pair(std::string(""), std::move(FileName))))
1711 .first;
1712 return std::make_pair(StringRef(FileData->second.first),
1713 StringRef(FileData->second.second));
1714 }
1715
1718
1720
1721
1722 if ((Entry.DirIdx != 0) &&
1723 Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {
1725 LineTable->Prologue.IncludeDirectories[Entry.DirIdx]
1726 .getAsCString();
1727 if (DirName)
1728 IncludeDir = *DirName;
1729 else {
1731 return std::nullopt;
1732 }
1733 }
1734 } else {
1735 if (0 < Entry.DirIdx &&
1736 Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {
1738 LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]
1739 .getAsCString();
1740 if (DirName)
1741 IncludeDir = *DirName;
1742 else {
1744 return std::nullopt;
1745 }
1746 }
1747 }
1748
1750
1753 }
1754
1756
1757 FileNamesCache::iterator FileData =
1759 .insert(
1760 std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
1761 std::move(FileName))))
1762 .first;
1763 return std::make_pair(StringRef(FileData->second.first),
1764 StringRef(FileData->second.second));
1765 }
1766 }
1767
1768 return std::nullopt;
1769}
1770
1771#define MAX_REFERENCIES_DEPTH 1000
1774 std::optional RefDiePair;
1775 int refDepth = 0;
1776 do {
1778 CUDiePair.DieEntry, dwarf::DW_AT_extension,
1780 if (!RefDiePair || !RefDiePair->DieEntry)
1781 return CUDiePair;
1782
1783 CUDiePair = *RefDiePair;
1785
1786 return CUDiePair;
1787}
1788
1790 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())
1792
1793 return std::nullopt;
1794}
1795
1797 : Ptr(U) {
1798 assert(U != nullptr);
1799}
1800
1802 assert(U != nullptr);
1803}
1804
1811
1815
1819
1823
1827
1829 bool InterCUProcessingStarted, std::atomic &HasNewInterconnectedCUs) {
1830 if (!Dependencies)
1832
1833 return Dependencies->resolveDependenciesAndMarkLiveness(
1834 InterCUProcessingStarted, HasNewInterconnectedCUs);
1835}
1836
1838 assert(Dependencies.get());
1839
1840 return Dependencies->updateDependenciesCompleteness();
1841}
1842
1844 assert(Dependencies.get());
1845
1846 Dependencies->verifyKeepChain();
1847}
1848
1851 dwarf::DW_AT_type, dwarf::DW_AT_specification,
1852 dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};
1853
1854 return ODRAttributes;
1855}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define MAX_REFERENCIES_DEPTH
Definition DWARFLinkerCompileUnit.cpp:1771
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
std::optional< T > getRangeThatContains(uint64_t Addr) const
void insert(AddressRange Range, int64_t Value)
The AddressRanges class helps normalize address range collections.
Collection::const_iterator insert(AddressRange Range)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
std::pair< KeyDataTy *, bool > insert(const KeyTy &NewValue)
Insert new value NewValue or return already existing entry.
A structured debug information entry.
DWARFDebugInfoEntry - A DIE with only the minimum required data.
dwarf::Tag getTag() const
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
const DWARFDebugInfoEntry * getDebugInfoEntry() const
LLVM_ABI const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.
Encoding
Size and signedness of expression operations' operands.
StringRef getData() const
LLVM_ABI std::optional< uint64_t > getAsSectionOffset() const
LLVM_ABI std::optional< int64_t > getAsSignedConstant() const
LLVM_ABI std::optional< uint64_t > getAsRelativeReference() const
getAsFoo functions below return the extracted value as Foo if only DWARFFormValue has form class is s...
LLVM_ABI std::optional< uint64_t > getAsDebugInfoReference() const
LLVM_ABI std::optional< uint64_t > getAsUnsignedConstant() const
const DWARFUnit * getUnit() const
const dwarf::FormParams & getFormParams() const
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
uint8_t getAddressByteSize() const
const char * getCompilationDir()
Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)
bool isLittleEndian() const
uint64_t getOffset() const
iterator find(const_arg_type_t< KeyT > Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMapIterBase< ValueTy, false > iterator
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This class represents DWARF information for source file and it's address map.
std::unique_ptr< AddressesMap > Addresses
Helpful address information(list of valid address ranges, relocations).
std::unique_ptr< DWARFContext > Dwarf
Source DWARF information.
@ Pub
.debug_pubnames, .debug_pubtypes
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName)
TypeUnit * getAsTypeUnit()
Returns TypeUnit if applicable.
Definition DWARFLinkerCompileUnit.cpp:1824
bool isTypeUnit()
Definition DWARFLinkerCompileUnit.cpp:1816
DwarfUnit * operator->()
Accessor for common functionality.
Definition DWARFLinkerCompileUnit.cpp:1805
PointerUnion< CompileUnit *, TypeUnit * > Ptr
CompileUnit * getAsCompileUnit()
Returns CompileUnit if applicable.
Definition DWARFLinkerCompileUnit.cpp:1820
OutputUnitVariantPtr(CompileUnit *U)
Definition DWARFLinkerCompileUnit.cpp:1796
bool isCompileUnit()
Definition DWARFLinkerCompileUnit.cpp:1812
void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset)
Add the low_pc of a label that is relocated by applying offset PCOffset.
Error cloneAndEmitDebugLocations()
Clone and emit debug locations(.debug_loc/.debug_loclists).
Definition DWARFLinkerCompileUnit.cpp:440
void cloneDieAttrExpression(const DWARFExpression &InputExpression, SmallVectorImpl< uint8_t > &OutputExpression, SectionDescriptor &Section, std::optional< int64_t > VarAddressAdjustment, OffsetsPtrVector &PatchesOffsets)
Clone attribute location axpression.
Definition DWARFLinkerCompileUnit.cpp:1090
void maybeResetToLoadedStage()
Reset compile units data(results of liveness analysis, clonning) if current stage greater than Stage:...
Definition DWARFLinkerCompileUnit.cpp:74
void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset)
Add a function range [LowPC, HighPC) that is relocated by applying offset PCOffset.
void analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
Definition DWARFLinkerCompileUnit.cpp:250
std::pair< DIE *, TypeEntry * > cloneDIE(const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset, std::optional< int64_t > FuncAddressAdjustment, std::optional< int64_t > VarAddressAdjustment, BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit)
Definition DWARFLinkerCompileUnit.cpp:1284
void cleanupDataAfterClonning()
Cleanup unneeded resources after compile unit is cloned.
Definition DWARFLinkerCompileUnit.cpp:236
Error assignTypeNames(TypePool &TypePoolRef)
Search for type entries and assign names.
Definition DWARFLinkerCompileUnit.cpp:300
@ TypeTable
Corresponding DIE goes to the type table only.
@ PlainDwarf
Corresponding DIE goes to the plain dwarf only.
Error cloneAndEmitLineTable(const Triple &TargetTriple)
Definition DWARFLinkerCompileUnit.cpp:1513
Error cloneAndEmitRanges()
Clone and emit ranges.
Definition DWARFLinkerCompileUnit.cpp:671
void updateDieRefPatchesWithClonedOffsets()
After cloning stage the output DIEs offsets are deallocated.
Definition DWARFLinkerCompileUnit.cpp:331
uint64_t getDebugAddrIndex(uint64_t Addr)
Returns index(inside .debug_addr) of an address.
const DWARFFile & getContaingFile() const
Returns DWARFFile containing this compile unit.
bool resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Search for subprograms and variables referencing live code and discover dependend DIEs.
Definition DWARFLinkerCompileUnit.cpp:1828
bool updateDependenciesCompleteness()
Check dependend DIEs for incompatible placement.
Definition DWARFLinkerCompileUnit.cpp:1837
bool loadInputDIEs()
Load DIEs of input compilation unit.
Definition DWARFLinkerCompileUnit.cpp:111
const RangesTy & getFunctionRanges() const
Returns function ranges of this unit.
Error cloneAndEmitDebugMacro()
Clone and emit debug macros(.debug_macinfo/.debug_macro).
Definition DWARFLinkerCompileUnit.cpp:891
Error cloneAndEmit(std::optional< std::reference_wrapper< const Triple > > TargetTriple, TypeUnit *ArtificialTypeUnit)
Clone and emit this compilation unit.
Definition DWARFLinkerCompileUnit.cpp:1228
void setStage(Stage Stage)
Set stage of overall processing.
Stage getStage() const
Returns stage of overall processing.
CompileUnit(LinkingGlobalData &GlobalData, unsigned ID, StringRef ClangModuleName, DWARFFile &File, OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format, llvm::endianness Endianess)
Definition DWARFLinkerCompileUnit.cpp:27
void verifyDependencies()
Check DIEs to have a consistent marking(keep marking, placement marking).
Definition DWARFLinkerCompileUnit.cpp:1843
Stage
The stages of new compile unit processing.
@ Cloned
Output DWARF is generated.
@ CreatedNotLoaded
Created, linked with input DWARF file.
@ Loaded
Input DWARF is loaded.
std::optional< uint64_t > getLowPc() const
Returns value of DW_AT_low_pc attribute.
std::optional< std::pair< StringRef, StringRef > > getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue)
Returns directory and file from the line table by index.
Definition DWARFLinkerCompileUnit.cpp:1669
std::optional< UnitEntryPairTy > resolveDIEReference(const DWARFFormValue &RefValue, ResolveInterCUReferencesMode CanResolveInterCUReferences)
Resolve the DIE attribute reference that has been extracted in RefValue.
Definition DWARFLinkerCompileUnit.cpp:378
void loadLineTable()
Loads unit line table.
Definition DWARFLinkerCompileUnit.cpp:70
StringEntry * getFileName(unsigned FileIdx, StringPool &GlobalStrings)
Returns name of the file for the FileIdx from the unit`s line table.
Definition DWARFLinkerCompileUnit.cpp:185
This class is a helper to create output DIE tree.
void addChild(DIE *Child)
Adds a specified Child to the current DIE.
DIE * createDIE(dwarf::Tag DieTag, uint32_t OutOffset)
Creates a DIE of specified tag DieTag and OutOffset.
This class discovers DIEs dependencies: marks "live" DIEs, marks DIE locations (whether DIE should be...
std::string UnitName
The name of this unit.
LinkingGlobalData & getGlobalData()
Return global data.
std::vector< std::unique_ptr< DIEAbbrev > > Abbreviations
Storage for the unique Abbreviations.
DIE * OutUnitDIE
Output unit DIE.
std::string SysRoot
The DW_AT_LLVM_sysroot of this unit.
bool isClangModule() const
Return true if this compile unit is from Clang module.
unsigned ID
Unique ID for the unit.
const std::string & getClangModuleName() const
Return Clang module name;.
void setOutUnitDIE(DIE *UnitDie)
Set output unit DIE.
DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID, StringRef ClangModuleName)
std::string ClangModuleName
If this is a Clang module, this holds the module's name.
FoldingSet< DIEAbbrev > AbbreviationsSet
FoldingSet that uniques the abbreviations.
StringRef getSysRoot()
Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
DIE * getOutUnitDIE()
Returns output unit DIE.
This class keeps data and services common for the whole linking process.
This class helps to assign indexes for DIE children.
LinkingGlobalData & GlobalData
dwarf::FormParams Format
Format for sections.
const dwarf::FormParams & getFormParams() const
Return size of address.
void eraseSections()
Erases data of all sections.
std::optional< const SectionDescriptor * > tryGetSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness)
Sets output format for all keeping sections.
uint16_t getVersion() const
Return DWARF version.
uint16_t getDebugInfoHeaderSize() const
Return size of header of debug_info table.
llvm::endianness getEndianness() const
Endiannes for the sections.
SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
const SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
The helper class to build type name based on DIE properties.
Error assignName(UnitEntryPairTy InputUnitEntryPair, std::optional< std::pair< size_t, size_t > > ChildIndex)
Create synthetic name for the specified DIE InputUnitEntryPair and assign created name to the DIE typ...
Keeps cloned data for the type DIE.
std::atomic< bool > ParentIsDeclaration
std::atomic< DIE * > DeclarationDie
std::atomic< DIE * > Die
TypeEntryBody keeps partially cloned DIEs corresponding to this type.
TypePool keeps type descriptors which contain partially cloned DIE correspinding to each type.
BumpPtrAllocator & getThreadLocalAllocator()
Return thread local allocator used by pool.
TypeEntryBody * getOrCreateTypeEntryBody(TypeEntry *Entry, TypeEntry *ParentEntry)
Create or return existing type entry body for the specified Entry.
TypeEntry * getRoot() const
Return root for all type entries.
Type Unit is used to represent an artificial compilation unit which keeps all type information.
TypePool & getTypePool()
Returns global type pool.
uint64_t tell() const
tell - Return the current offset with the file.
void rememberDieOutOffset(uint32_t Idx, uint64_t Offset)
Idx index of the DIE.
TypeEntry * getDieTypeEntry(uint32_t Idx)
Idx index of the DIE.
DIEInfo & getDIEInfo(unsigned Idx)
Idx index of the DIE.
const DWARFDebugInfoEntry * getSiblingEntry(const DWARFDebugInfoEntry *Die) const
const DWARFDebugInfoEntry * getFirstChildEntry(const DWARFDebugInfoEntry *Die) const
std::optional< uint32_t > getDIEIndexForOffset(uint64_t Offset)
DWARFDie getDIE(const DWARFDebugInfoEntry *Die)
const DWARFDebugInfoEntry * getDebugInfoEntry(unsigned Index) const
DWARFUnit & getOrigUnit() const
Returns paired compile unit from input DWARF.
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const
std::optional< DWARFFormValue > find(uint32_t DieIdx, ArrayRef< dwarf::Attribute > Attrs) const
Error emitDebugInfo(const Triple &TargetTriple)
Emit .debug_info section for unit DIEs.
Error emitDebugStringOffsetSection()
Emit the .debug_str_offsets section for current unit.
void emitPubAccelerators()
Emit .debug_pubnames and .debug_pubtypes for Unit.
void warn(const Twine &Warning, const DWARFDie *DIE=nullptr)
Error emitAbbreviations()
Error emitDebugLine(const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable)
Emit .debug_line section.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
bool isODRLanguage(uint16_t Language)
function_ref< CompileUnit *(uint64_t Offset)> OffsetToUnitTy
SmallVector< uint64_t * > OffsetsPtrVector
Type for list of pointers to patches offsets.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
ArrayRef< dwarf::Attribute > getODRAttributes()
Definition DWARFLinkerCompileUnit.cpp:1849
ResolveInterCUReferencesMode
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
DebugSectionKind
List of tracked debug tables.
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
bool isInToolchainDir(StringRef Path)
Make a best effort to determine whether Path is inside a toolchain.
bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path)
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.
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.
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
@ DW_ARANGES_VERSION
Section version number for .debug_aranges.
LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
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 void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void fill(R &&Range, T &&Value)
Provide wrappers to std::fill which take ranges instead of having to pass begin/end explicitly.
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.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
@ Dwarf
DWARF v5 .debug_names.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
bool isCompileUnit(const std::unique_ptr< DWARFUnit > &U)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
void consumeError(Error Err)
Consume a Error without doing anything.
dwarf::FormParams FormParams
Version, address size (starting in v5), and DWARF32/64 format; these parameters affect interpretation...
Standard .debug_line state machine structure.
Represents a single DWARF expression, whose value is location-dependent.
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
uint8_t getDwarfOffsetByteSize() const
The size of a reference is determined by the DWARF 32/64-bit format.
Information gathered about source DIEs.
LLVM_DUMP_METHOD void dump()
bool needToPlaceInTypeTable() const
DieOutputPlacement getPlacement() const
This structure is used to update reference to the DIE.
uint64_t RefDieIdxOrClonedOffset
PointerIntPair< CompileUnit *, 1 > RefCU
This structure is used to update location list offset into .debug_loc/.debug_loclists.
int64_t AddrAdjustmentValue
This structure is used to update range list offset into .debug_ranges/.debug_rnglists.
bool IsCompileUnitRanges
Indicates patch which points to immediate compile unit's attribute.
This structure is used to update reference to the DIE of ULEB128 form.
uint64_t RefDieIdxOrClonedOffset
PointerIntPair< CompileUnit *, 1 > RefCU
dwarf::FormParams getFormParams() const
Returns FormParams used by section.
This structure is used to keep data of the concrete section.
raw_svector_ostream OS
Stream which stores data to the Contents.
void emitUnitLength(uint64_t Length)
Emit unit length into the current section contents.
void emitOffset(uint64_t Val)
Emit specified offset value into the current section contents.
void emitIntVal(uint64_t Val, unsigned Size)
Emit specified integer value into the current section contents.
void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)
Write specified Value of AttrForm to the PatchOffset.
uint64_t getIntVal(uint64_t PatchOffset, unsigned Size)
Returns integer value of Size located by specified PatchOffset.
This is a helper structure which keeps a debug info entry with it's containing compilation unit.
UnitEntryPairTy()=default
std::optional< UnitEntryPairTy > getParent()
Definition DWARFLinkerCompileUnit.cpp:1789
UnitEntryPairTy getNamespaceOrigin()
Definition DWARFLinkerCompileUnit.cpp:1772
const DWARFDebugInfoEntry * DieEntry