1//===- DWARFLinkerUnit.cpp ------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DWARFLinkerUnit.h"
10#include "DWARFEmitterImpl.h"
11#include "DebugLineSectionEmitter.h"
12
13using namespace llvm;
14using namespace dwarf_linker;
15using namespace dwarf_linker::parallel;
16
17void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
18 // Check the set for priors.
19 FoldingSetNodeID ID;
20 Abbrev.Profile(ID);
21 void *InsertToken;
22
23 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos&: InsertToken);
24 // If it's newly added.
25 if (InSet) {
26 // Assign existing abbreviation number.
27 Abbrev.setNumber(InSet->getNumber());
28 } else {
29 // Add to abbreviation list.
30 Abbreviations.push_back(
31 x: std::make_unique<DIEAbbrev>(args: Abbrev.getTag(), args: Abbrev.hasChildren()));
32 for (const auto &Attr : Abbrev.getData())
33 Abbreviations.back()->AddAttribute(AbbrevData: Attr);
34 AbbreviationsSet.InsertNode(N: Abbreviations.back().get(), InsertPos: InsertToken);
35 // Assign the unique abbreviation number.
36 Abbrev.setNumber(Abbreviations.size());
37 Abbreviations.back()->setNumber(Abbreviations.size());
38 }
39}
40
41Error DwarfUnit::emitAbbreviations() {
42 const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();
43 if (Abbrevs.empty())
44 return Error::success();
45
46 SectionDescriptor &AbbrevSection =
47 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugAbbrev);
48
49 // For each abbreviation.
50 for (const auto &Abbrev : Abbrevs)
51 emitDwarfAbbrevEntry(Abbrev: *Abbrev, AbbrevSection);
52
53 // Mark end of abbreviations.
54 encodeULEB128(Value: 0, OS&: AbbrevSection.OS);
55
56 return Error::success();
57}
58
59void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
60 SectionDescriptor &AbbrevSection) {
61 // Emit the abbreviations code (base 1 index.)
62 encodeULEB128(Value: Abbrev.getNumber(), OS&: AbbrevSection.OS);
63
64 // Emit the abbreviations data.
65 // Emit its Dwarf tag type.
66 encodeULEB128(Value: Abbrev.getTag(), OS&: AbbrevSection.OS);
67
68 // Emit whether it has children DIEs.
69 encodeULEB128(Value: (unsigned)Abbrev.hasChildren(), OS&: AbbrevSection.OS);
70
71 // For each attribute description.
72 const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();
73 for (const DIEAbbrevData &AttrData : Data) {
74 // Emit attribute type.
75 encodeULEB128(Value: AttrData.getAttribute(), OS&: AbbrevSection.OS);
76
77 // Emit form type.
78 encodeULEB128(Value: AttrData.getForm(), OS&: AbbrevSection.OS);
79
80 // Emit value for DW_FORM_implicit_const.
81 if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
82 encodeSLEB128(Value: AttrData.getValue(), OS&: AbbrevSection.OS);
83 }
84
85 // Mark end of abbreviation.
86 encodeULEB128(Value: 0, OS&: AbbrevSection.OS);
87 encodeULEB128(Value: 0, OS&: AbbrevSection.OS);
88}
89
90Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {
91 DIE *OutUnitDIE = getOutUnitDIE();
92 if (OutUnitDIE == nullptr)
93 return Error::success();
94
95 // FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs
96 // directly.
97
98 SectionDescriptor &OutSection =
99 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo);
100 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS);
101 if (Error Err = Emitter.init(TheTriple: TargetTriple, Swift5ReflectionSegmentName: "__DWARF"))
102 return Err;
103
104 // Emit compile unit header.
105 Emitter.emitCompileUnitHeader(Unit&: *this);
106 size_t OffsetToAbbreviationTableOffset =
107 (getFormParams().Version >= 5) ? 8 : 6;
108 OutSection.notePatch(Patch: DebugOffsetPatch{
109 OffsetToAbbreviationTableOffset,
110 &getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugAbbrev)});
111
112 // Emit DIEs.
113 Emitter.emitDIE(Die&: *OutUnitDIE);
114 Emitter.finish();
115
116 // Set start offset ans size for .debug_info section.
117 OutSection.setSizesForSectionCreatedByAsmPrinter();
118 return Error::success();
119}
120
121Error DwarfUnit::emitDebugLine(
122 const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable,
123 ArrayRef<uint64_t> OrigRowIndices,
124 DenseMap<uint64_t, uint64_t> *RowIndexToSeqStartOffset) {
125 DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);
126
127 return DebugLineEmitter.emit(LineTable: OutLineTable, OrigRowIndices,
128 RowIndexToSeqStartOffset);
129}
130
131Error DwarfUnit::emitDebugStringOffsetSection() {
132 if (getVersion() < 5)
133 return Error::success();
134
135 if (DebugStringIndexMap.empty())
136 return Error::success();
137
138 SectionDescriptor &OutDebugStrOffsetsSection =
139 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugStrOffsets);
140
141 // Emit section header.
142
143 // Emit length.
144 OutDebugStrOffsetsSection.emitUnitLength(Length: 0xBADDEF);
145 uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();
146
147 // Emit version.
148 OutDebugStrOffsetsSection.emitIntVal(Val: 5, Size: 2);
149
150 // Emit padding.
151 OutDebugStrOffsetsSection.emitIntVal(Val: 0, Size: 2);
152
153 // Emit index to offset map.
154 for (const StringEntry *String : DebugStringIndexMap.getValues()) {
155 // Note patch for string offset value.
156 OutDebugStrOffsetsSection.notePatch(
157 Patch: DebugStrPatch{{.PatchOffset: OutDebugStrOffsetsSection.OS.tell()}, .String: String});
158
159 // Emit placeholder for offset value.
160 OutDebugStrOffsetsSection.emitOffset(Val: 0xBADDEF);
161 }
162
163 // Patch section length.
164 OutDebugStrOffsetsSection.apply(
165 PatchOffset: OffsetAfterSectionLength -
166 OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),
167 AttrForm: dwarf::DW_FORM_sec_offset,
168 Val: OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);
169
170 return Error::success();
171}
172
173/// Emit the pubnames or pubtypes section contribution for \p
174/// Unit into \p Sec. The data is provided in \p Info.
175std::optional<uint64_t>
176DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
177 const DwarfUnit::AccelInfo &Info,
178 std::optional<uint64_t> LengthOffset) {
179 if (!LengthOffset) {
180 // Emit the header.
181 OutSection.emitIntVal(Val: 0xBADDEF,
182 Size: getFormParams().getDwarfOffsetByteSize()); // Length
183 LengthOffset = OutSection.OS.tell();
184
185 OutSection.emitIntVal(Val: dwarf::DW_PUBNAMES_VERSION, Size: 2); // Version
186
187 OutSection.notePatch(Patch: DebugOffsetPatch{
188 OutSection.OS.tell(),
189 &getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo)});
190 OutSection.emitOffset(Val: 0xBADDEF); // Unit offset
191
192 OutSection.emitIntVal(Val: getUnitSize(), Size: 4); // Size
193 }
194 OutSection.emitOffset(Val: Info.OutOffset);
195
196 // Emit the string itself.
197 OutSection.emitInplaceString(String: Info.String->first());
198
199 return LengthOffset;
200}
201
202/// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
203void DwarfUnit::emitPubAccelerators() {
204 std::optional<uint64_t> NamesLengthOffset;
205 std::optional<uint64_t> TypesLengthOffset;
206
207 forEachAcceleratorRecord(Handler: [&](const DwarfUnit::AccelInfo &Info) {
208 if (Info.AvoidForPubSections)
209 return;
210
211 switch (Info.Type) {
212 case DwarfUnit::AccelType::Name: {
213 NamesLengthOffset = emitPubAcceleratorEntry(
214 OutSection&: getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugPubNames), Info,
215 LengthOffset: NamesLengthOffset);
216 } break;
217 case DwarfUnit::AccelType::Type: {
218 TypesLengthOffset = emitPubAcceleratorEntry(
219 OutSection&: getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugPubTypes), Info,
220 LengthOffset: TypesLengthOffset);
221 } break;
222 default: {
223 // Nothing to do.
224 } break;
225 }
226 });
227
228 if (NamesLengthOffset) {
229 SectionDescriptor &OutSection =
230 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugPubNames);
231 OutSection.emitIntVal(Val: 0, Size: 4); // End marker.
232
233 OutSection.apply(PatchOffset: *NamesLengthOffset -
234 OutSection.getFormParams().getDwarfOffsetByteSize(),
235 AttrForm: dwarf::DW_FORM_sec_offset,
236 Val: OutSection.OS.tell() - *NamesLengthOffset);
237 }
238
239 if (TypesLengthOffset) {
240 SectionDescriptor &OutSection =
241 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugPubTypes);
242 OutSection.emitIntVal(Val: 0, Size: 4); // End marker.
243
244 OutSection.apply(PatchOffset: *TypesLengthOffset -
245 OutSection.getFormParams().getDwarfOffsetByteSize(),
246 AttrForm: dwarf::DW_FORM_sec_offset,
247 Val: OutSection.OS.tell() - *TypesLengthOffset);
248 }
249}
250