LLVM: lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
22#include
23
24using namespace llvm;
25using namespace dwarf_linker;
26using namespace dwarf_linker::parallel;
27
32 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
33 getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),
34 AcceleratorRecords(&GlobalData.getAllocator()) {
38}
39
44 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
45 OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
47 AcceleratorRecords(&GlobalData.getAllocator()) {
50
52 if (!CUDie)
53 return;
54
55 if (std::optional Val = CUDie.find(dwarf::DW_AT_language)) {
58 Language = LangVal;
59 }
60
62 NoODR = false;
63
66 else
69}
70
72 LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());
73}
74
76
78 return;
79
80
81
82
83
84
86 Info.unsetFlagsWhichSetDuringLiveAnalysis();
87
88 LowPc = std::nullopt;
89 HighPc = 0;
92 Dependencies.reset(nullptr);
93
96 return;
97 }
98
99 AcceleratorRecords.erase();
103 DebugAddrIndexMap.clear();
104
108 Name = nullptr;
110
112}
113
116 if (!InputUnitDIE)
117 return false;
118
119
120 DieInfoArray.resize(getOrigUnit().getNumDIEs());
122 if (!NoODR)
123 TypeEntries.resize(getOrigUnit().getNumDIEs());
124 return true;
125}
126
127void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
128 bool IsODRUnavailableFunctionScope) {
130
135 bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;
136
137 if (DieInfo.getIsInMouduleScope())
138 ChildInfo.setIsInMouduleScope();
139
140 if (DieInfo.getIsInFunctionScope())
141 ChildInfo.setIsInFunctionScope();
142
143 if (DieInfo.getIsInAnonNamespaceScope())
144 ChildInfo.setIsInAnonNamespaceScope();
145
146 switch (CurChild->getTag()) {
147 case dwarf::DW_TAG_module:
148 ChildInfo.setIsInMouduleScope();
149 if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
153 break;
154 case dwarf::DW_TAG_subprogram:
155 ChildInfo.setIsInFunctionScope();
156 if (!ChildIsODRUnavailableFunctionScope &&
157 !ChildInfo.getIsInMouduleScope()) {
158 if (find(CurChild,
159 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))
160 ChildIsODRUnavailableFunctionScope = true;
161 }
162 break;
163 case dwarf::DW_TAG_namespace: {
165
166 if (find(CurChild, dwarf::DW_AT_extension))
168
169 if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))
170 ChildInfo.setIsInAnonNamespaceScope();
171 } break;
172 default:
173 break;
174 }
175
177 ChildInfo.setTrackLiveness();
178
179 if ((!ChildInfo.getIsInAnonNamespaceScope() &&
180 !ChildIsODRUnavailableFunctionScope && !NoODR))
181 ChildInfo.setODRAvailable();
182
183 if (CurChild->hasChildren())
184 analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);
185 }
186}
187
190 if (LineTablePtr) {
192
193
195 if (It == ResolvedFullPaths.end()) {
196 std::string OrigFileName;
198 FileIdx, getOrigUnit().getCompilationDir(),
199 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
200 OrigFileName);
201 (void)FoundFileName;
202 assert(FoundFileName && "Must get file name from line table");
203
204
205
208
209
210
212 ResolvedParentPaths.find(ParentPath);
213 if (ParentIt == ResolvedParentPaths.end()) {
216 ParentIt =
217 ResolvedParentPaths
218 .insert({ParentPath, GlobalStrings.insert(RealPath).first})
219 .first;
220 }
221
222
225
226 It = ResolvedFullPaths
227 .insert(std::make_pair(
228 FileIdx, GlobalStrings.insert(ResolvedPath).first))
229 .first;
230 }
231
232 return It->second;
233 }
234 }
235
236 return nullptr;
237}
238
242 ResolvedParentPaths.clear();
247 Dependencies.reset(nullptr);
249}
250
251
252
254 if (!Language || Language != dwarf::DW_LANG_Swift)
255 return;
256
258 return;
259
262 if (!Path.ends_with(".swiftinterface"))
263 return;
264
270 return;
271
272
274 if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))
275 return;
277 return;
278 if (std::optional Val = find(DieEntry, dwarf::DW_AT_name)) {
282 return;
283 }
284
286
290 ResolvedPath,
293 if (!Entry.empty() && Entry != ResolvedPath) {
295 warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +
296 ": " + Entry + " and " + Path + ".",
297 &Die);
298 }
299 Entry = std::string(ResolvedPath);
300 }
301}
302
306
309}
310
319 continue;
320
321 assert(ChildInfo.getODRAvailable());
323 {this, CurChild},
324 ChildrenIndexAssigner.getChildIndex(*this, CurChild)))
325 return Err;
326
327 if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))
328 return Err;
329 }
330
332}
333
335 if (std::optional<SectionDescriptor *> DebugInfoSection =
337
338 (*DebugInfoSection)
339 ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
340
344 });
345
346 (*DebugInfoSection)
347 ->ListDebugULEB128DieRefPatch.forEach(
349
353 });
354 }
355
356 if (std::optional<SectionDescriptor *> DebugLocSection =
358 (*DebugLocSection)
359 ->ListDebugULEB128DieRefPatch.forEach(
361
365 });
366 }
367
368 if (std::optional<SectionDescriptor *> DebugLocListsSection =
370 (*DebugLocListsSection)
371 ->ListDebugULEB128DieRefPatch.forEach(
373
377 });
378 }
379}
380
387 RefCU = this;
390 RefCU = getUnitFromOffset(*Offset);
391 RefDIEOffset = *Offset;
392 } else {
393 return std::nullopt;
394 }
395
396 if (RefCU == this) {
397
400 } else if (RefCU && CanResolveInterCUReferences) {
401
402
403
405 if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)
407
408 if (std::optional<uint32_t> RefDieIdx =
411 } else {
413 }
414 return std::nullopt;
415}
416
420 if (std::optional AttrVal = find(DieEntry, Attr))
422
423 return std::nullopt;
424}
425
427 int64_t PcOffset) {
428 std::lock_guardstd::mutex Guard(RangesMutex);
429
430 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
431 if (LowPc)
432 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
433 else
434 LowPc = FuncLowPc + PcOffset;
435 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
436}
437
439 std::lock_guardstd::mutex Guard(LabelsMutex);
440 Labels.insert({LabelLowPc, PcOffset});
441}
442
444 if (getGlobalData().getOptions().UpdateIndexTablesOnly)
446
450 }
451
454}
455
456void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {
459
460 if (!DebugInfoSection.ListDebugLocPatch.empty()) {
464
465 uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);
466
467 DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
468
469
470 uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(
475
476 if (!OriginalLocations) {
477 warn(OriginalLocations.takeError());
478 return;
479 }
480
481 LinkedLocationExpressionsVector LinkedLocationExpressions;
483 LinkedLocationExpressionsWithOffsetPatches LinkedExpression;
484
485 if (CurExpression.Range) {
486
487 LinkedExpression.Expression.Range = {
490 }
491
494
498 LinkedExpression.Expression.Expr,
500 LinkedExpression.Patches);
501
502 LinkedLocationExpressions.push_back({LinkedExpression});
503 }
504
505
506 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
507 OutLocationSection.OS.tell());
508 emitLocListFragment(LinkedLocationExpressions, OutLocationSection);
509 });
510
511 if (OffsetAfterUnitLength > 0) {
512 assert(OffsetAfterUnitLength -
514 OffsetAfterUnitLength);
515 OutLocationSection.apply(
516 OffsetAfterUnitLength -
518 dwarf::DW_FORM_sec_offset,
519 OutLocationSection.OS.tell() - OffsetAfterUnitLength);
520 }
521 }
522}
523
524
527 return 0;
528
529
531 uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();
532
533
535
536
538
539
541
542
544
545 return OffsetAfterUnitLength;
546}
547
548
549uint64_t CompileUnit::emitLocListFragment(
550 const LinkedLocationExpressionsVector &LinkedLocationExpression,
552 uint64_t OffsetBeforeLocationExpression = 0;
553
556 if (std::optional<uint64_t> LowPC = getLowPc())
557 BaseAddress = *LowPC;
558
559 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
560 LinkedLocationExpression) {
561 if (LocExpression.Expression.Range) {
563 LocExpression.Expression.Range->LowPC - BaseAddress,
566 LocExpression.Expression.Range->HighPC - BaseAddress,
568 }
569
570 OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);
571 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
572 for (uint64_t *OffsetPtr : LocExpression.Patches)
573 *OffsetPtr += OffsetBeforeLocationExpression;
574
575 OutLocationSection.OS
576 << StringRef((const char *)LocExpression.Expression.Expr.data(),
577 LocExpression.Expression.Expr.size());
578 }
579
580
585 return OffsetBeforeLocationExpression;
586 }
587
588 std::optional<uint64_t> BaseAddress;
589 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
590 LinkedLocationExpression) {
591 if (LocExpression.Expression.Range) {
592
593
594 if (!BaseAddress) {
595 BaseAddress = LocExpression.Expression.Range->LowPC;
596
597
598 OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);
600 OutLocationSection.OS);
601 }
602
603
604 OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);
605
606
607 encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,
608 OutLocationSection.OS);
609
610
611 encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,
612 OutLocationSection.OS);
613 } else
614
615 OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);
616
617 encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);
618 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
619 for (uint64_t *OffsetPtr : LocExpression.Patches)
620 *OffsetPtr += OffsetBeforeLocationExpression;
621
623 (const char *)LocExpression.Expression.Expr.data(),
624 LocExpression.Expression.Expr.size());
625 }
626
627
628 OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);
629 return OffsetBeforeLocationExpression;
630}
631
632Error CompileUnit::emitDebugAddrSection() {
635
638
639 if (DebugAddrIndexMap.empty())
641
644
645
646
647
649 uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();
650
651
653
654
656
657
659
660
663
664
665 OutAddrSection.apply(
666 OffsetAfterSectionLength -
668 dwarf::DW_FORM_sec_offset,
669 OutAddrSection.OS.tell() - OffsetAfterSectionLength);
670
672}
673
675 if (getGlobalData().getOptions().UpdateIndexTablesOnly)
677
678
681 LinkedFunctionRanges.insert(
683
684 emitAranges(LinkedFunctionRanges);
685
689 }
690
693}
694
695void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
701
702 if (!DebugInfoSection.ListDebugRangePatch.empty()) {
703 std::optional CachedRange;
704 uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);
705
707 DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
709 CompileUnitRangePtr = &Patch;
710 } else {
711
712
713 AddressRanges LinkedRanges;
714 uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(
715 Patch.PatchOffset,
716 DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
717 if (Expected InputRanges =
718 getOrigUnit().findRnglistFromOffset(
719 InputDebugRangesSectionOffset)) {
720
721 for (const auto &Range : *InputRanges) {
722 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
723 CachedRange =
724 getFunctionRanges().getRangeThatContains(Range.LowPC);
725
726
727 if (!CachedRange) {
728 warn("inconsistent range data.");
729 continue;
730 }
731
732
733 LinkedRanges.insert({Range.LowPC + CachedRange->Value,
734 Range.HighPC + CachedRange->Value});
735 }
736 } else {
737 llvm::consumeError(InputRanges.takeError());
738 warn("invalid range list ignored.");
739 }
740
741
742 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
743 OutRangeSection.OS.tell());
744 emitRangeListFragment(LinkedRanges, OutRangeSection);
745 }
746 });
747
748 if (CompileUnitRangePtr != nullptr) {
749
750
752 dwarf::DW_FORM_sec_offset,
753 OutRangeSection.OS.tell());
754 emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);
755 }
756
757 if (OffsetAfterUnitLength > 0) {
758 assert(OffsetAfterUnitLength -
760 OffsetAfterUnitLength);
761 OutRangeSection.apply(
762 OffsetAfterUnitLength -
764 dwarf::DW_FORM_sec_offset,
765 OutRangeSection.OS.tell() - OffsetAfterUnitLength);
766 }
767 }
768}
769
772 return 0;
773
774
776 uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();
777
778
780
781
783
784
786
787
789
790 return OffsetAfterUnitLength;
791}
792
793void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,
796
798 if (std::optional<uint64_t> LowPC = getLowPc())
799 BaseAddress = *LowPC;
800
806 }
807
808
811 return;
812 }
813
814 std::optional<uint64_t> BaseAddress;
816 if (!BaseAddress) {
817 BaseAddress = Range.start();
818
819
820 OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);
822 }
823
824
825 OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);
826
827
829
830
832 }
833
834
835 OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);
836}
837
838void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {
839 if (LinkedFunctionRanges.empty())
840 return;
841
846
847
849 sizeof(int32_t) +
850 sizeof(int16_t) +
851 sizeof(int32_t) +
852 sizeof(int8_t) +
853 sizeof(int8_t);
854
857
858 OutArangesSection.emitOffset(0xBADDEF);
859 uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();
860
862 OutArangesSection.notePatch(
864 OutArangesSection.emitOffset(0xBADDEF);
866 1);
867 OutArangesSection.emitIntVal(0, 1);
868
870 OutArangesSection.emitIntVal(0, 1);
871
872
878 }
879
880
883
884 uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();
885
886
887 OutArangesSection.apply(
888 OffsetAfterArangesLengthField -
890 dwarf::DW_FORM_sec_offset,
891 OffsetAfterArangesEnd - OffsetAfterArangesLengthField);
892}
893
897
900
901
902 if (std::optional<uint64_t> MacroAttr =
906 emitMacroTableImpl(Table, *MacroAttr, true);
907 }
908 }
909
910
911 if (std::optional<uint64_t> MacroAttr =
915 emitMacroTableImpl(Table, *MacroAttr, false);
916 }
917 }
918
920}
921
922void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
924 bool hasDWARFv5Header) {
926 hasDWARFv5Header
929
930 bool DefAttributeIsReported = false;
931 bool UndefAttributeIsReported = false;
932 bool ImportAttributeIsReported = false;
933
934 for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
935 if (OffsetToMacroTable == List.Offset) {
936
937 if (hasDWARFv5Header) {
938
939 OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));
940
942
943
944 if (Flags &
945 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
946 Flags &=
947 ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
948 warn("opcode_operands_table is not supported yet.");
949 }
950
951
952 std::optional<uint64_t> StmtListOffset;
953 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
954
956 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
957 StmtListOffset = V.getDIEInteger().getValue();
958 break;
959 }
960 }
961
962 if (!StmtListOffset) {
963 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
964 warn("couldn`t find line table for macro table.");
965 }
966 }
967
968
969 OutSection.emitIntVal(Flags, sizeof(Flags));
970
971
972 if (StmtListOffset) {
976
977
978 OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());
979 }
980 }
981
982
983 for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
984 if (MacroEntry.Type == 0) {
986 continue;
987 }
988
989 uint8_t MacroType = MacroEntry.Type;
990 switch (MacroType) {
991 default: {
992 bool HasVendorSpecificExtension =
993 (!hasDWARFv5Header &&
997
998 if (HasVendorSpecificExtension) {
999
1000 OutSection.emitIntVal(MacroType, 1);
1001
1002
1004
1005
1006 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);
1007 } else
1008 warn("unknown macro type. skip.");
1009 } break;
1010
1011
1012
1013
1014
1015
1016 case dwarf::DW_MACRO_define:
1017 case dwarf::DW_MACRO_undef: {
1018
1019 OutSection.emitIntVal(MacroType, 1);
1020
1021
1023
1024
1025 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);
1026 } break;
1027 case dwarf::DW_MACRO_define_strp:
1028 case dwarf::DW_MACRO_undef_strp:
1029 case dwarf::DW_MACRO_define_strx:
1030 case dwarf::DW_MACRO_undef_strx: {
1031
1032
1033 switch (MacroType) {
1034 case dwarf::DW_MACRO_define_strx: {
1035 MacroType = dwarf::DW_MACRO_define_strp;
1036 if (!DefAttributeIsReported) {
1037 warn("DW_MACRO_define_strx unsupported yet. Convert to "
1038 "DW_MACRO_define_strp.");
1039 DefAttributeIsReported = true;
1040 }
1041 } break;
1042 case dwarf::DW_MACRO_undef_strx: {
1043 MacroType = dwarf::DW_MACRO_undef_strp;
1044 if (!UndefAttributeIsReported) {
1045 warn("DW_MACRO_undef_strx unsupported yet. Convert to "
1046 "DW_MACRO_undef_strp.");
1047 UndefAttributeIsReported = true;
1048 }
1049 } break;
1050 default:
1051
1052 break;
1053 }
1054
1055
1056 OutSection.emitIntVal(MacroType, 1);
1057
1058
1060
1061
1062 OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);
1063 break;
1064 }
1065 case dwarf::DW_MACRO_start_file: {
1066
1067 OutSection.emitIntVal(MacroType, 1);
1068
1070
1072 } break;
1073 case dwarf::DW_MACRO_end_file: {
1074
1075 OutSection.emitIntVal(MacroType, 1);
1076 } break;
1077 case dwarf::DW_MACRO_import:
1078 case dwarf::DW_MACRO_import_sup: {
1079 if (!ImportAttributeIsReported) {
1080 warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "
1081 "yet. remove.");
1082 ImportAttributeIsReported = true;
1083 }
1084 } break;
1085 }
1086 }
1087
1088 return;
1089 }
1090 }
1091}
1092
1096 std::optional<int64_t> VarAddressAdjustment,
1099
1102
1104 for (auto &Op : InputExpression) {
1106
1107
1108 if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1109 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1110 Desc.Op[0] != Encoding::Size1))
1111 warn("unsupported DW_OP encoding.");
1112
1113 if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||
1114 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
1115 Desc.Op[0] == Encoding::Size1)) {
1116
1119 assert(ULEBsize <= 16);
1120
1121
1127 } else {
1130 }
1133 unsigned RealSize = 0;
1134
1135
1136
1137 if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
1138 RefOffset += OrigUnit.getOffset();
1140 if (std::optional<uint32_t> Idx =
1142 RefDieIdx = *Idx;
1143
1144
1145
1147
1148 RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);
1149
1150 Section.notePatchWithOffsetUpdate(
1152 RefDieIdx),
1153 PatchesOffsets);
1154 } else
1156
1157 if (RealSize > ULEBsize) {
1158
1160 warn("base type ref doesn't fit.");
1161 }
1162 assert(RealSize == ULEBsize && "padding failed");
1164 OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());
1165 } else if (().getOptions().UpdateIndexTablesOnly &&
1166 Op.getCode() == dwarf::DW_OP_addrx) {
1167 if (std::optionalobject::SectionedAddress SA =
1169
1170
1171
1172
1173 OutputExpression.push_back(dwarf::DW_OP_addr);
1174 uint64_t LinkedAddress = SA->Address + VarAddressAdjustment.value_or(0);
1178 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1179 OrigAddressByteSize);
1180 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
1181 } else
1182 warn("cann't read DW_OP_addrx operand.");
1183 } else if (().getOptions().UpdateIndexTablesOnly &&
1184 Op.getCode() == dwarf::DW_OP_constx) {
1185 if (std::optionalobject::SectionedAddress SA =
1187
1188
1189
1190
1191 std::optional<uint8_t> OutOperandKind;
1192 switch (OrigAddressByteSize) {
1193 case 2:
1194 OutOperandKind = dwarf::DW_OP_const2u;
1195 break;
1196 case 4:
1197 OutOperandKind = dwarf::DW_OP_const4u;
1198 break;
1199 case 8:
1200 OutOperandKind = dwarf::DW_OP_const8u;
1201 break;
1202 default:
1204 formatv(("unsupported address size: {0}."), OrigAddressByteSize));
1205 break;
1206 }
1207
1208 if (OutOperandKind) {
1209 OutputExpression.push_back(*OutOperandKind);
1211 SA->Address + VarAddressAdjustment.value_or(0);
1215 reinterpret_cast<const uint8_t *>(&LinkedAddress),
1216 OrigAddressByteSize);
1217 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
1218 }
1219 } else
1220 warn("cann't read DW_OP_constx operand.");
1221 } else {
1222
1225 OutputExpression.append(Bytes.begin(), Bytes.end());
1226 }
1228 }
1229}
1230
1232 std::optional<std::reference_wrapper> TargetTriple,
1233 TypeUnit *ArtificialTypeUnit) {
1235
1237 if (!OrigUnitDIE.isValid())
1239
1241 if (ArtificialTypeUnit)
1243
1244
1245 std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(
1247 std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);
1249
1250 if (!TargetTriple.has_value() || (OutCUDie.first == nullptr))
1252
1254 return Err;
1255
1257 return Err;
1258
1261 return Err;
1262
1263
1264
1265
1266
1268 return Err;
1269
1271 return Err;
1272
1273 if (Error Err = emitDebugAddrSection())
1274 return Err;
1275
1276
1280
1282 return Err;
1283
1285}
1286
1289 uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,
1290 std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,
1291 TypeUnit *ArtificialTypeUnit) {
1294
1295 bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();
1296 bool NeedToCloneTypeDIE =
1297 (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&
1298 Info.needToPlaceInTypeTable();
1299 std::pair<DIE *, TypeEntry *> ClonedDIE;
1300
1302
1303 if (NeedToClonePlainDIE)
1304
1305
1306 ClonedDIE.first = createPlainDIEandCloneAttributes(
1307 InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,
1308 VarAddressAdjustment);
1309 if (NeedToCloneTypeDIE) {
1310
1311
1312 assert(ArtificialTypeUnit != nullptr);
1315
1316 ClonedDIE.second = createTypeDIEandCloneAttributes(
1317 InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,
1318 ArtificialTypeUnit);
1319 }
1321 ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;
1322
1323 bool HasPlainChildrenToClone =
1324 (ClonedDIE.first && Info.getKeepPlainChildren());
1325
1326 bool HasTypeChildrenToClone =
1327 ((ClonedDIE.second ||
1328 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&
1329 Info.getKeepTypeChildren());
1330
1331
1332 if (HasPlainChildrenToClone || HasTypeChildrenToClone) {
1337 std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(
1338 CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,
1339 VarAddressAdjustment, Allocator, ArtificialTypeUnit);
1340
1341 if (ClonedChild.first) {
1342 OutOffset =
1343 ClonedChild.first->getOffset() + ClonedChild.first->getSize();
1344 PlainDIEGenerator.addChild(ClonedChild.first);
1345 }
1346 }
1347 assert(ClonedDIE.first == nullptr ||
1348 HasPlainChildrenToClone == ClonedDIE.first->hasChildren());
1349
1350
1351 if (HasPlainChildrenToClone)
1352 OutOffset += sizeof(int8_t);
1353 }
1354
1355
1356 if (ClonedDIE.first != nullptr)
1357 ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());
1358
1359 return ClonedDIE;
1360}
1361
1362DIE *CompileUnit::createPlainDIEandCloneAttributes(
1364 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
1365 std::optional<int64_t> &VarAddressAdjustment) {
1368 DIE *ClonedDIE = nullptr;
1369 bool HasLocationExpressionAddress = false;
1370 if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {
1371
1372 FuncAddressAdjustment =
1374 getDIE(InputDieEntry), false);
1375 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {
1376
1377 std::optional<uint64_t> lowPC =
1379 if (lowPC) {
1381 if (It != Labels.end())
1382 FuncAddressAdjustment = It->second;
1383 }
1384 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {
1385
1386 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
1388 getDIE(InputDieEntry), false);
1389
1390 HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;
1391 if (LocExprAddrAndRelocAdjustment.first &&
1392 LocExprAddrAndRelocAdjustment.second)
1393 VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;
1394 }
1395
1396 ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);
1397
1398
1399
1401
1402
1403 DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,
1404 PlainDIEGenerator, FuncAddressAdjustment,
1405 VarAddressAdjustment,
1406 HasLocationExpressionAddress);
1407 AttributesCloner.clone();
1408
1409
1411 AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,
1412 nullptr);
1413
1414 OutOffset =
1415 AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());
1416
1417 return ClonedDIE;
1418}
1419
1420
1421DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,
1423 dwarf::Tag DieTag, bool IsDeclaration,
1424 bool IsParentDeclaration) {
1425 DIE *DefinitionDie = TypeDescriptor->Die;
1426
1427 if (DefinitionDie)
1428 return nullptr;
1429
1432
1433 if (IsDeclaration && !DeclarationDie) {
1434
1435 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1436 if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
1437 NewDie))
1438 return NewDie;
1439 } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
1440
1441
1443 OldParentIsDeclaration, false)) {
1444 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1446 return NewDie;
1447 }
1448 } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
1449
1450
1451 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1452 if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
1453 NewDie))
1454 return NewDie;
1455 } else if (!IsDeclaration && !IsParentDeclaration) {
1456
1457 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
1458 if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {
1460 return NewDie;
1461 }
1462 }
1463
1464 return nullptr;
1465}
1466
1467TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
1470 assert(ArtificialTypeUnit != nullptr);
1472
1474 assert(Entry != nullptr);
1475 assert(ClonedParentTypeDIE != nullptr);
1478 Entry, ClonedParentTypeDIE);
1480
1481 bool IsDeclaration =
1483
1484 bool ParentIsDeclaration = false;
1485 if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())
1486 ParentIsDeclaration =
1488
1489 DIE *OutDIE =
1490 allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),
1491 IsDeclaration, ParentIsDeclaration);
1492
1493 if (OutDIE != nullptr) {
1494 assert(ArtificialTypeUnit != nullptr);
1496
1497 DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,
1498 InputDieEntry, TypeDIEGenerator,
1499 std::nullopt, std::nullopt, false);
1500 AttributesCloner.clone();
1501
1502
1504 ArtificialTypeUnit);
1505 AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,
1506 Entry);
1507
1508
1509
1510 OutDIE->setSize(AttributesCloner.getOutOffset() + 1);
1511 }
1512
1514}
1515
1519 if (InputLineTable == nullptr) {
1521 warn("cann't load line table.");
1523 }
1524
1526
1527
1530
1531
1532 if (getGlobalData().getOptions().UpdateIndexTablesOnly) {
1533 OutLineTable.Rows = InputLineTable->Rows;
1534
1535
1536 if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)
1537 OutLineTable.Rows.clear();
1538
1540 } else {
1541
1542 std::vectorDWARFDebugLine::Row NewRows;
1543 NewRows.reserve(InputLineTable->Rows.size());
1544
1545
1546
1547 std::vectorDWARFDebugLine::Row Seq;
1548
1550 std::optional CurrRange;
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1564
1565
1566
1567
1568
1569 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {
1570
1571
1573 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
1574 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
1575 if (StopAddress != -1ULL && !Seq.empty()) {
1576
1577
1578 auto NextLine = Seq.back();
1579 NextLine.Address.Address = StopAddress;
1580 NextLine.EndSequence = 1;
1581 NextLine.PrologueEnd = 0;
1582 NextLine.BasicBlock = 0;
1583 NextLine.EpilogueBegin = 0;
1584 Seq.push_back(NextLine);
1585 insertLineSequence(Seq, NewRows);
1586 }
1587
1588 if (!CurrRange)
1589 continue;
1590 }
1591
1592
1593 if (Row.EndSequence && Seq.empty())
1594 continue;
1595
1596
1597 Row.Address.Address += CurrRange->Value;
1598 Seq.emplace_back(Row);
1599
1600 if (Row.EndSequence)
1601 insertLineSequence(Seq, NewRows);
1602 }
1603
1604 OutLineTable.Rows = std::move(NewRows);
1605 }
1606
1607 return emitDebugLine(TargetTriple, OutLineTable);
1608}
1609
1610void CompileUnit::insertLineSequence(std::vectorDWARFDebugLine::Row &Seq,
1611 std::vectorDWARFDebugLine::Row &Rows) {
1612 if (Seq.empty())
1613 return;
1614
1615 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
1617 Seq.clear();
1618 return;
1619 }
1620
1624
1625
1626
1627
1628
1629 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
1630 InsertPoint->EndSequence) {
1631 *InsertPoint = Seq.front();
1632 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
1633 } else {
1634 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
1635 }
1636
1637 Seq.clear();
1638}
1639
1640#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1647 break;
1650 break;
1653 break;
1656 break;
1657 }
1658
1659 llvm::errs() << " Keep: " << getKeep();
1660 llvm::errs() << " KeepPlainChildren: " << getKeepPlainChildren();
1661 llvm::errs() << " KeepTypeChildren: " << getKeepTypeChildren();
1662 llvm::errs() << " IsInMouduleScope: " << getIsInMouduleScope();
1663 llvm::errs() << " IsInFunctionScope: " << getIsInFunctionScope();
1664 llvm::errs() << " IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();
1665 llvm::errs() << " ODRAvailable: " << getODRAvailable();
1666 llvm::errs() << " TrackLiveness: " << getTrackLiveness();
1668}
1669#endif
1670
1671std::optional<std::pair<StringRef, StringRef>>
1676 FileIdx = *Val;
1677 else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())
1678 FileIdx = *Val;
1679 else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())
1680 FileIdx = *Val;
1681 else
1682 return std::nullopt;
1683
1685}
1686
1687std::optional<std::pair<StringRef, StringRef>>
1691 return std::make_pair(StringRef(FileData->second.first),
1692 StringRef(FileData->second.second));
1693
1696 if (LineTable->hasFileAtIndex(FileIdx)) {
1697
1699 LineTable->Prologue.getFileNameEntry(FileIdx);
1700
1702 if () {
1704 return std::nullopt;
1705 }
1706
1707 std::string FileName = *Name;
1711 .insert(std::make_pair(
1712 FileIdx,
1713 std::make_pair(std::string(""), std::move(FileName))))
1714 .first;
1715 return std::make_pair(StringRef(FileData->second.first),
1716 StringRef(FileData->second.second));
1717 }
1718
1721
1723
1724
1725 if ((Entry.DirIdx != 0) &&
1726 Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {
1728 LineTable->Prologue.IncludeDirectories[Entry.DirIdx]
1729 .getAsCString();
1730 if (DirName)
1731 IncludeDir = *DirName;
1732 else {
1734 return std::nullopt;
1735 }
1736 }
1737 } else {
1738 if (0 < Entry.DirIdx &&
1739 Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {
1741 LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]
1742 .getAsCString();
1743 if (DirName)
1744 IncludeDir = *DirName;
1745 else {
1747 return std::nullopt;
1748 }
1749 }
1750 }
1751
1753
1756 }
1757
1759
1763 std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
1764 std::move(FileName))))
1765 .first;
1766 return std::make_pair(StringRef(FileData->second.first),
1767 StringRef(FileData->second.second));
1768 }
1769 }
1770
1771 return std::nullopt;
1772}
1773
1774#define MAX_REFERENCIES_DEPTH 1000
1777 std::optional RefDiePair;
1778 int refDepth = 0;
1779 do {
1781 CUDiePair.DieEntry, dwarf::DW_AT_extension,
1783 if (!RefDiePair || !RefDiePair->DieEntry)
1784 return CUDiePair;
1785
1786 CUDiePair = *RefDiePair;
1788
1789 return CUDiePair;
1790}
1791
1793 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())
1795
1796 return std::nullopt;
1797}
1798
1800 : Ptr(U) {
1801 assert(U != nullptr);
1802}
1803
1805 assert(U != nullptr);
1806}
1807
1810 return getAsCompileUnit();
1811 else
1812 return getAsTypeUnit();
1813}
1814
1816 return isa<CompileUnit *>(Ptr);
1817}
1818
1820 return isa<TypeUnit *>(Ptr);
1821}
1822
1824 return cast<CompileUnit *>(Ptr);
1825}
1826
1828 return cast<TypeUnit *>(Ptr);
1829}
1830
1832 bool InterCUProcessingStarted, std::atomic &HasNewInterconnectedCUs) {
1833 if (!Dependencies)
1835
1836 return Dependencies->resolveDependenciesAndMarkLiveness(
1837 InterCUProcessingStarted, HasNewInterconnectedCUs);
1838}
1839
1841 assert(Dependencies.get());
1842
1843 return Dependencies->updateDependenciesCompleteness();
1844}
1845
1847 assert(Dependencies.get());
1848
1849 Dependencies->verifyKeepChain();
1850}
1851
1854 dwarf::DW_AT_type, dwarf::DW_AT_specification,
1855 dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};
1856
1857 return ODRAttributes;
1858}
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Mark the given Function as meaning that it cannot be changed in any way mark any values that are used as this function s parameters or by its return values(according to Uses) live as well. void DeadArgumentEliminationPass
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define MAX_REFERENCIES_DEPTH
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A class that represents an address range.
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),...
Allocate memory in an ever growing pool, as if by bump-pointer.
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.
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
const DWARFDebugInfoEntry * getDebugInfoEntry() const
const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.
This class represents an Operation in the Expression.
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
StringRef getData() const
std::optional< uint64_t > getAsSectionOffset() const
std::optional< int64_t > getAsSignedConstant() const
std::optional< uint64_t > getAsRelativeReference() const
getAsFoo functions below return the extracted value as Foo if only DWARFFormValue has form class is s...
std::optional< uint64_t > getAsDebugInfoReference() const
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()
std::optional< uint32_t > getDIEIndexForOffset(uint64_t Offset)
Return the DIE index for a given offset Offset inside the unit's DIE vector.
Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)
bool isLittleEndian() const
std::optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
uint64_t getOffset() const
iterator find(const_arg_type_t< KeyT > Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > 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.
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
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
uint64_t getValueIndex(T Value)
const SmallVector< T > & getValues() const
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName)
This class helps to store information for accelerator entries.
TypeUnit * getAsTypeUnit()
Returns TypeUnit if applicable.
DwarfUnit * operator->()
Accessor for common functionality.
CompileUnit * getAsCompileUnit()
Returns CompileUnit if applicable.
OutputUnitVariantPtr(CompileUnit *U)
Stores all information related to a compile unit, be it in its original instance of the object file o...
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).
void cloneDieAttrExpression(const DWARFExpression &InputExpression, SmallVectorImpl< uint8_t > &OutputExpression, SectionDescriptor &Section, std::optional< int64_t > VarAddressAdjustment, OffsetsPtrVector &PatchesOffsets)
Clone attribute location axpression.
void maybeResetToLoadedStage()
Reset compile units data(results of liveness analysis, clonning) if current stage greater than Stage:...
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.
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)
void cleanupDataAfterClonning()
Cleanup unneeded resources after compile unit is cloned.
Error assignTypeNames(TypePool &TypePoolRef)
Search for type entries and assign names.
@ Both
Corresponding DIE goes to type table and to plain dwarf.
@ TypeTable
Corresponding DIE goes to the type table only.
@ PlainDwarf
Corresponding DIE goes to the plain dwarf only.
Error cloneAndEmitLineTable(const Triple &TargetTriple)
Error cloneAndEmitRanges()
Clone and emit ranges.
void updateDieRefPatchesWithClonedOffsets()
After cloning stage the output DIEs offsets are deallocated.
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.
bool updateDependenciesCompleteness()
Check dependend DIEs for incompatible placement.
bool loadInputDIEs()
Load DIEs of input compilation unit.
const RangesTy & getFunctionRanges() const
Returns function ranges of this unit.
Error cloneAndEmitDebugMacro()
Clone and emit debug macros(.debug_macinfo/.debug_macro).
Error cloneAndEmit(std::optional< std::reference_wrapper< const Triple > > TargetTriple, TypeUnit *ArtificialTypeUnit)
Clone and emit this compilation unit.
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)
void verifyDependencies()
Check DIEs to have a consistent marking(keep marking, placement marking).
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.
std::optional< UnitEntryPairTy > resolveDIEReference(const DWARFFormValue &RefValue, ResolveInterCUReferencesMode CanResolveInterCUReferences)
Resolve the DIE attribute reference that has been extracted in RefValue.
void loadLineTable()
Loads unit line table.
StringEntry * getFileName(unsigned FileIdx, StringPool &GlobalStrings)
Returns name of the file for the FileIdx from the unit`s line table.
This class creates clones of input DIE attributes.
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...
Base class for all Dwarf units(Compile unit/Type table unit).
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.
const std::string & getClangModuleName() const
Return Clang module name;.
void setOutUnitDIE(DIE *UnitDie)
Set output unit DIE.
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.
const DWARFLinkerOptions & getOptions() const
Returns linking options.
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.
uint64_t getDieOutOffset(uint32_t 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.
bool isODRLanguage(uint16_t Language)
ArrayRef< dwarf::Attribute > getODRAttributes()
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.
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.
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
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 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.
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...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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)
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool hasFileAtIndex(uint64_t FileIndex) const
bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const
Extracts filename by its index in filename table in prologue.
dwarf::FormParams FormParams
Version, address size (starting in v5), and DWARF32/64 format; these parameters affect interpretation...
Standard .debug_line state machine structure.
Description of the encoding of one expression Op.
SmallVector< Encoding > Op
Encoding for Op operands.
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
DWARFLinkerBase::SwiftInterfacesMapTy * ParseableSwiftInterfaces
A list of all .swiftinterface files referenced by the debug info, mapping Module name to path on disk...
SmallVector< DWARFLinkerBase::AccelTableKind, 1 > AccelTables
The accelerator table kinds.
bool NoODR
Do not unique types according to ODR.
bool UpdateIndexTablesOnly
Update index tables.
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 emitString(dwarf::Form StringForm, const char *StringVal)
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.
std::optional< UnitEntryPairTy > getParent()
UnitEntryPairTy getNamespaceOrigin()
const DWARFDebugInfoEntry * DieEntry