1//===- OutputSections.h -----------------------------------------*- C++ -*-===//
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#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
10#define LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
11
12#include "ArrayList.h"
13#include "StringEntryToDwarfStringPoolEntryMap.h"
14#include "llvm/ADT/SmallString.h"
15#include "llvm/ADT/StringRef.h"
16#include "llvm/BinaryFormat/Dwarf.h"
17#include "llvm/CodeGen/DwarfStringPoolEntry.h"
18#include "llvm/DWARFLinker/StringPool.h"
19#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
20#include "llvm/DebugInfo/DWARF/DWARFObject.h"
21#include "llvm/Object/ObjectFile.h"
22#include "llvm/Support/Endian.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/FormatVariadic.h"
25#include "llvm/Support/LEB128.h"
26#include "llvm/Support/MemoryBufferRef.h"
27#include "llvm/Support/raw_ostream.h"
28#include <array>
29#include <cstdint>
30
31namespace llvm {
32namespace dwarf_linker {
33namespace parallel {
34
35class TypeUnit;
36
37/// There are fields(sizes, offsets) which should be updated after
38/// sections are generated. To remember offsets and related data
39/// the descendants of SectionPatch structure should be used.
40
41struct SectionPatch {
42 uint64_t PatchOffset = 0;
43};
44
45/// This structure is used to update strings offsets into .debug_str.
46struct DebugStrPatch : SectionPatch {
47 const StringEntry *String = nullptr;
48};
49
50/// This structure is used to update strings offsets into .debug_line_str.
51struct DebugLineStrPatch : SectionPatch {
52 const StringEntry *String = nullptr;
53};
54
55/// This structure is used to update range list offset into
56/// .debug_ranges/.debug_rnglists.
57struct DebugRangePatch : SectionPatch {
58 /// Indicates patch which points to immediate compile unit's attribute.
59 bool IsCompileUnitRanges = false;
60};
61
62/// This structure is used to update location list offset into
63/// .debug_loc/.debug_loclists.
64struct DebugLocPatch : SectionPatch {
65 int64_t AddrAdjustmentValue = 0;
66};
67
68/// This structure is used to update offset with start of another section.
69struct SectionDescriptor;
70struct DebugOffsetPatch : SectionPatch {
71 DebugOffsetPatch(uint64_t PatchOffset, SectionDescriptor *SectionPtr,
72 bool AddLocalValue = false)
73 : SectionPatch({.PatchOffset: PatchOffset}), SectionPtr(SectionPtr, AddLocalValue) {}
74
75 PointerIntPair<SectionDescriptor *, 1> SectionPtr;
76};
77
78/// This structure is used to update reference to the DIE.
79struct DebugDieRefPatch : SectionPatch {
80 DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU,
81 uint32_t RefIdx);
82
83 PointerIntPair<CompileUnit *, 1> RefCU;
84 uint64_t RefDieIdxOrClonedOffset = 0;
85};
86
87/// This structure is used to update reference to the DIE of ULEB128 form.
88struct DebugULEB128DieRefPatch : SectionPatch {
89 DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
90 CompileUnit *RefCU, uint32_t RefIdx);
91
92 PointerIntPair<CompileUnit *, 1> RefCU;
93 uint64_t RefDieIdxOrClonedOffset = 0;
94};
95
96/// This structure is used to update reference to the type DIE.
97struct DebugDieTypeRefPatch : SectionPatch {
98 DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName);
99
100 TypeEntry *RefTypeName = nullptr;
101};
102
103/// This structure is used to update reference to the type DIE.
104struct DebugType2TypeDieRefPatch : SectionPatch {
105 DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
106 TypeEntry *RefTypeName);
107
108 DIE *Die = nullptr;
109 TypeEntry *TypeName = nullptr;
110 TypeEntry *RefTypeName = nullptr;
111};
112
113struct DebugTypeStrPatch : SectionPatch {
114 DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
115 StringEntry *String);
116
117 DIE *Die = nullptr;
118 TypeEntry *TypeName = nullptr;
119 StringEntry *String = nullptr;
120};
121
122struct DebugTypeLineStrPatch : SectionPatch {
123 DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
124 StringEntry *String);
125
126 DIE *Die = nullptr;
127 TypeEntry *TypeName = nullptr;
128 StringEntry *String = nullptr;
129};
130
131struct DebugTypeDeclFilePatch {
132 DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory,
133 StringEntry *FilePath);
134
135 DIE *Die = nullptr;
136 TypeEntry *TypeName = nullptr;
137 StringEntry *Directory = nullptr;
138 StringEntry *FilePath = nullptr;
139 uint32_t FileID = 0;
140};
141
142/// Type for section data.
143using OutSectionDataTy = SmallString<0>;
144
145/// Type for list of pointers to patches offsets.
146using OffsetsPtrVector = SmallVector<uint64_t *>;
147
148class OutputSections;
149
150/// This structure is used to keep data of the concrete section.
151/// Like data bits, list of patches, format.
152struct SectionDescriptor : SectionDescriptorBase {
153 friend OutputSections;
154
155 SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData,
156 dwarf::FormParams Format, llvm::endianness Endianess)
157 : SectionDescriptorBase(SectionKind, Format, Endianess), OS(Contents),
158 ListDebugStrPatch(&GlobalData.getAllocator()),
159 ListDebugLineStrPatch(&GlobalData.getAllocator()),
160 ListDebugRangePatch(&GlobalData.getAllocator()),
161 ListDebugLocPatch(&GlobalData.getAllocator()),
162 ListDebugDieRefPatch(&GlobalData.getAllocator()),
163 ListDebugULEB128DieRefPatch(&GlobalData.getAllocator()),
164 ListDebugOffsetPatch(&GlobalData.getAllocator()),
165 ListDebugDieTypeRefPatch(&GlobalData.getAllocator()),
166 ListDebugType2TypeDieRefPatch(&GlobalData.getAllocator()),
167 ListDebugTypeStrPatch(&GlobalData.getAllocator()),
168 ListDebugTypeLineStrPatch(&GlobalData.getAllocator()),
169 ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()),
170 GlobalData(GlobalData) {}
171
172 /// Erase whole section content(data bits, list of patches).
173 void clearAllSectionData();
174
175 /// Erase only section output data bits.
176 void clearSectionContent();
177
178 /// When objects(f.e. compile units) are glued into the single file,
179 /// the debug sections corresponding to the concrete object are assigned
180 /// with offsets inside the whole file. This field keeps offset
181 /// to the debug section, corresponding to this object.
182 uint64_t StartOffset = 0;
183
184protected:
185 /// Section data bits.
186 OutSectionDataTy Contents;
187
188public:
189 /// Stream which stores data to the Contents.
190 raw_svector_ostream OS;
191
192 /// Section patches.
193#define ADD_PATCHES_LIST(T) \
194 T &notePatch(const T &Patch) { return List##T.add(Patch); } \
195 ArrayList<T> List##T;
196
197 ADD_PATCHES_LIST(DebugStrPatch)
198 ADD_PATCHES_LIST(DebugLineStrPatch)
199 ADD_PATCHES_LIST(DebugRangePatch)
200 ADD_PATCHES_LIST(DebugLocPatch)
201 ADD_PATCHES_LIST(DebugDieRefPatch)
202 ADD_PATCHES_LIST(DebugULEB128DieRefPatch)
203 ADD_PATCHES_LIST(DebugOffsetPatch)
204 ADD_PATCHES_LIST(DebugDieTypeRefPatch)
205 ADD_PATCHES_LIST(DebugType2TypeDieRefPatch)
206 ADD_PATCHES_LIST(DebugTypeStrPatch)
207 ADD_PATCHES_LIST(DebugTypeLineStrPatch)
208 ADD_PATCHES_LIST(DebugTypeDeclFilePatch)
209
210 /// While creating patches, offsets to attributes may be partially
211 /// unknown(because size of abbreviation number is unknown). In such case we
212 /// remember patch itself and pointer to patch application offset to add size
213 /// of abbreviation number later.
214 template <typename T>
215 void notePatchWithOffsetUpdate(const T &Patch,
216 OffsetsPtrVector &PatchesOffsetsList) {
217 PatchesOffsetsList.emplace_back(&notePatch(Patch).PatchOffset);
218 }
219
220 /// Some sections are emitted using AsmPrinter. In that case "Contents"
221 /// member of SectionDescriptor contains elf file. This method searches
222 /// for section data inside elf file and remember offset to it.
223 void setSizesForSectionCreatedByAsmPrinter();
224
225 /// Returns section content.
226 StringRef getContents() override {
227 if (SectionOffsetInsideAsmPrinterOutputStart == 0)
228 return Contents;
229
230 return Contents.slice(Start: SectionOffsetInsideAsmPrinterOutputStart,
231 End: SectionOffsetInsideAsmPrinterOutputEnd);
232 }
233
234 /// Emit unit length into the current section contents.
235 void emitUnitLength(uint64_t Length) {
236 maybeEmitDwarf64Mark();
237 emitIntVal(Val: Length, Size: getFormParams().getDwarfOffsetByteSize());
238 }
239
240 /// Emit DWARF64 mark into the current section contents.
241 void maybeEmitDwarf64Mark() {
242 if (getFormParams().Format != dwarf::DWARF64)
243 return;
244 emitIntVal(Val: dwarf::DW_LENGTH_DWARF64, Size: 4);
245 }
246
247 /// Emit specified offset value into the current section contents.
248 void emitOffset(uint64_t Val) {
249 emitIntVal(Val, Size: getFormParams().getDwarfOffsetByteSize());
250 }
251
252 /// Emit specified integer value into the current section contents.
253 void emitIntVal(uint64_t Val, unsigned Size);
254
255 void emitString(dwarf::Form StringForm, const char *StringVal);
256
257 void emitBinaryData(llvm::StringRef Data);
258
259 /// Emit specified inplace string value into the current section contents.
260 void emitInplaceString(StringRef String) {
261 OS << String;
262 emitIntVal(Val: 0, Size: 1);
263 }
264
265 /// Emit string placeholder into the current section contents.
266 void emitStringPlaceholder() {
267 // emit bad offset which should be updated later.
268 emitOffset(Val: 0xBADDEF);
269 }
270
271 /// Write specified \p Value of \p AttrForm to the \p PatchOffset.
272 void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val);
273
274 /// Returns integer value of \p Size located by specified \p PatchOffset.
275 uint64_t getIntVal(uint64_t PatchOffset, unsigned Size);
276
277protected:
278 /// Writes integer value \p Val of \p Size by specified \p PatchOffset.
279 void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size);
280
281 /// Writes integer value \p Val of ULEB128 format by specified \p PatchOffset.
282 void applyULEB128(uint64_t PatchOffset, uint64_t Val);
283
284 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
285 void applySLEB128(uint64_t PatchOffset, uint64_t Val);
286
287 /// Sets output format.
288 void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianess) {
289 this->Format = Format;
290 this->Endianess = Endianess;
291 }
292
293 LinkingGlobalData &GlobalData;
294
295 /// Some sections are generated using AsmPrinter. The real section data
296 /// located inside elf file in that case. Following fields points to the
297 /// real section content inside elf file.
298 size_t SectionOffsetInsideAsmPrinterOutputStart = 0;
299 size_t SectionOffsetInsideAsmPrinterOutputEnd = 0;
300};
301
302/// This class keeps contents and offsets to the debug sections. Any objects
303/// which is supposed to be emitted into the debug sections should use this
304/// class to track debug sections offsets and keep sections data.
305class OutputSections {
306public:
307 OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {}
308
309 /// Sets output format for all keeping sections.
310 void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness) {
311 this->Format = Format;
312 this->Endianness = Endianness;
313 }
314
315 /// Returns descriptor for the specified section of \p SectionKind.
316 /// The descriptor should already be created. The llvm_unreachable
317 /// would be raised if it is not.
318 const SectionDescriptor &
319 getSectionDescriptor(DebugSectionKind SectionKind) const {
320 SectionsSetTy::const_iterator It = SectionDescriptors.find(x: SectionKind);
321
322 if (It == SectionDescriptors.end())
323 llvm_unreachable(
324 formatv("Section {0} does not exist", getSectionName(SectionKind))
325 .str()
326 .c_str());
327
328 return *It->second;
329 }
330
331 /// Returns descriptor for the specified section of \p SectionKind.
332 /// The descriptor should already be created. The llvm_unreachable
333 /// would be raised if it is not.
334 SectionDescriptor &getSectionDescriptor(DebugSectionKind SectionKind) {
335 SectionsSetTy::iterator It = SectionDescriptors.find(x: SectionKind);
336
337 if (It == SectionDescriptors.end())
338 llvm_unreachable(
339 formatv("Section {0} does not exist", getSectionName(SectionKind))
340 .str()
341 .c_str());
342
343 assert(It->second.get() != nullptr);
344
345 return *It->second;
346 }
347
348 /// Returns descriptor for the specified section of \p SectionKind.
349 /// Returns std::nullopt if section descriptor is not created yet.
350 std::optional<const SectionDescriptor *>
351 tryGetSectionDescriptor(DebugSectionKind SectionKind) const {
352 SectionsSetTy::const_iterator It = SectionDescriptors.find(x: SectionKind);
353
354 if (It == SectionDescriptors.end())
355 return std::nullopt;
356
357 return It->second.get();
358 }
359
360 /// Returns descriptor for the specified section of \p SectionKind.
361 /// Returns std::nullopt if section descriptor is not created yet.
362 std::optional<SectionDescriptor *>
363 tryGetSectionDescriptor(DebugSectionKind SectionKind) {
364 SectionsSetTy::iterator It = SectionDescriptors.find(x: SectionKind);
365
366 if (It == SectionDescriptors.end())
367 return std::nullopt;
368
369 return It->second.get();
370 }
371
372 /// Returns descriptor for the specified section of \p SectionKind.
373 /// If descriptor does not exist then creates it.
374 SectionDescriptor &
375 getOrCreateSectionDescriptor(DebugSectionKind SectionKind) {
376 auto [It, Inserted] = SectionDescriptors.try_emplace(k: SectionKind);
377
378 if (Inserted)
379 It->second = std::make_shared<SectionDescriptor>(args&: SectionKind, args&: GlobalData,
380 args&: Format, args&: Endianness);
381
382 return *It->second;
383 }
384
385 /// Erases data of all sections.
386 void eraseSections() {
387 for (auto &Section : SectionDescriptors)
388 Section.second->clearAllSectionData();
389 }
390
391 /// Enumerate all sections and call \p Handler for each.
392 void forEach(function_ref<void(SectionDescriptor &)> Handler) {
393 for (auto &Section : SectionDescriptors) {
394 assert(Section.second.get() != nullptr);
395 Handler(*(Section.second));
396 }
397 }
398
399 /// Enumerate all sections and call \p Handler for each.
400 void forEach(
401 function_ref<void(std::shared_ptr<SectionDescriptor> Section)> Handler) {
402 for (auto &Section : SectionDescriptors)
403 Handler(Section.second);
404 }
405
406 /// Enumerate all sections, for each section set current offset
407 /// (kept by \p SectionSizesAccumulator), update current offset with section
408 /// length.
409 void assignSectionsOffsetAndAccumulateSize(
410 std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) {
411 for (auto &Section : SectionDescriptors) {
412 Section.second->StartOffset =
413 SectionSizesAccumulator[static_cast<uint8_t>(
414 Section.second->getKind())];
415 SectionSizesAccumulator[static_cast<uint8_t>(
416 Section.second->getKind())] += Section.second->getContents().size();
417 }
418 }
419
420 /// Enumerate all sections, for each section apply all section patches.
421 void applyPatches(SectionDescriptor &Section,
422 StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
423 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
424 TypeUnit *TypeUnitPtr);
425
426 /// Endiannes for the sections.
427 llvm::endianness getEndianness() const { return Endianness; }
428
429 /// Return DWARF version.
430 uint16_t getVersion() const { return Format.Version; }
431
432 /// Return size of header of debug_info table.
433 uint16_t getDebugInfoHeaderSize() const {
434 return Format.Version >= 5 ? 12 : 11;
435 }
436
437 /// Return size of header of debug_ table.
438 uint16_t getDebugAddrHeaderSize() const {
439 assert(Format.Version >= 5);
440 return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
441 }
442
443 /// Return size of header of debug_str_offsets table.
444 uint16_t getDebugStrOffsetsHeaderSize() const {
445 assert(Format.Version >= 5);
446 return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
447 }
448
449 /// Return size of address.
450 const dwarf::FormParams &getFormParams() const { return Format; }
451
452protected:
453 LinkingGlobalData &GlobalData;
454
455 /// Format for sections.
456 dwarf::FormParams Format = {.Version: 4, .AddrSize: 4, .Format: dwarf::DWARF32};
457
458 /// Endiannes for sections.
459 llvm::endianness Endianness = llvm::endianness::native;
460
461 /// All keeping sections.
462 using SectionsSetTy =
463 std::map<DebugSectionKind, std::shared_ptr<SectionDescriptor>>;
464 SectionsSetTy SectionDescriptors;
465};
466
467} // end of namespace parallel
468} // end of namespace dwarf_linker
469} // end of namespace llvm
470
471#endif // LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
472