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