Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.h
35292 views
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
31
namespace llvm {
32
namespace dwarf_linker {
33
namespace parallel {
34
35
class 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
41
struct SectionPatch {
42
uint64_t PatchOffset = 0;
43
};
44
45
/// This structure is used to update strings offsets into .debug_str.
46
struct DebugStrPatch : SectionPatch {
47
const StringEntry *String = nullptr;
48
};
49
50
/// This structure is used to update strings offsets into .debug_line_str.
51
struct 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.
57
struct 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.
64
struct DebugLocPatch : SectionPatch {
65
int64_t AddrAdjustmentValue = 0;
66
};
67
68
/// This structure is used to update offset with start of another section.
69
struct SectionDescriptor;
70
struct DebugOffsetPatch : SectionPatch {
71
DebugOffsetPatch(uint64_t PatchOffset, SectionDescriptor *SectionPtr,
72
bool AddLocalValue = false)
73
: SectionPatch({PatchOffset}), SectionPtr(SectionPtr, AddLocalValue) {}
74
75
PointerIntPair<SectionDescriptor *, 1> SectionPtr;
76
};
77
78
/// This structure is used to update reference to the DIE.
79
struct 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.
88
struct 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.
97
struct 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.
104
struct 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
113
struct 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
122
struct 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
131
struct 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.
143
using OutSectionDataTy = SmallString<0>;
144
145
/// Type for list of pointers to patches offsets.
146
using OffsetsPtrVector = SmallVector<uint64_t *>;
147
148
class OutputSections;
149
150
/// This structure is used to keep data of the concrete section.
151
/// Like data bits, list of patches, format.
152
struct 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
184
/// Stream which stores data to the Contents.
185
raw_svector_ostream OS;
186
187
/// Section patches.
188
#define ADD_PATCHES_LIST(T) \
189
T &notePatch(const T &Patch) { return List##T.add(Patch); } \
190
ArrayList<T> List##T;
191
192
ADD_PATCHES_LIST(DebugStrPatch)
193
ADD_PATCHES_LIST(DebugLineStrPatch)
194
ADD_PATCHES_LIST(DebugRangePatch)
195
ADD_PATCHES_LIST(DebugLocPatch)
196
ADD_PATCHES_LIST(DebugDieRefPatch)
197
ADD_PATCHES_LIST(DebugULEB128DieRefPatch)
198
ADD_PATCHES_LIST(DebugOffsetPatch)
199
ADD_PATCHES_LIST(DebugDieTypeRefPatch)
200
ADD_PATCHES_LIST(DebugType2TypeDieRefPatch)
201
ADD_PATCHES_LIST(DebugTypeStrPatch)
202
ADD_PATCHES_LIST(DebugTypeLineStrPatch)
203
ADD_PATCHES_LIST(DebugTypeDeclFilePatch)
204
205
/// While creating patches, offsets to attributes may be partially
206
/// unknown(because size of abbreviation number is unknown). In such case we
207
/// remember patch itself and pointer to patch application offset to add size
208
/// of abbreviation number later.
209
template <typename T>
210
void notePatchWithOffsetUpdate(const T &Patch,
211
OffsetsPtrVector &PatchesOffsetsList) {
212
PatchesOffsetsList.emplace_back(&notePatch(Patch).PatchOffset);
213
}
214
215
/// Some sections are emitted using AsmPrinter. In that case "Contents"
216
/// member of SectionDescriptor contains elf file. This method searches
217
/// for section data inside elf file and remember offset to it.
218
void setSizesForSectionCreatedByAsmPrinter();
219
220
/// Returns section content.
221
StringRef getContents() override {
222
if (SectionOffsetInsideAsmPrinterOutputStart == 0)
223
return Contents;
224
225
return Contents.slice(SectionOffsetInsideAsmPrinterOutputStart,
226
SectionOffsetInsideAsmPrinterOutputEnd);
227
}
228
229
/// Emit unit length into the current section contents.
230
void emitUnitLength(uint64_t Length) {
231
maybeEmitDwarf64Mark();
232
emitIntVal(Length, getFormParams().getDwarfOffsetByteSize());
233
}
234
235
/// Emit DWARF64 mark into the current section contents.
236
void maybeEmitDwarf64Mark() {
237
if (getFormParams().Format != dwarf::DWARF64)
238
return;
239
emitIntVal(dwarf::DW_LENGTH_DWARF64, 4);
240
}
241
242
/// Emit specified offset value into the current section contents.
243
void emitOffset(uint64_t Val) {
244
emitIntVal(Val, getFormParams().getDwarfOffsetByteSize());
245
}
246
247
/// Emit specified integer value into the current section contents.
248
void emitIntVal(uint64_t Val, unsigned Size);
249
250
void emitString(dwarf::Form StringForm, const char *StringVal);
251
252
void emitBinaryData(llvm::StringRef Data);
253
254
/// Emit specified inplace string value into the current section contents.
255
void emitInplaceString(StringRef String) {
256
OS << String;
257
emitIntVal(0, 1);
258
}
259
260
/// Emit string placeholder into the current section contents.
261
void emitStringPlaceholder() {
262
// emit bad offset which should be updated later.
263
emitOffset(0xBADDEF);
264
}
265
266
/// Write specified \p Value of \p AttrForm to the \p PatchOffset.
267
void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val);
268
269
/// Returns integer value of \p Size located by specified \p PatchOffset.
270
uint64_t getIntVal(uint64_t PatchOffset, unsigned Size);
271
272
protected:
273
/// Writes integer value \p Val of \p Size by specified \p PatchOffset.
274
void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size);
275
276
/// Writes integer value \p Val of ULEB128 format by specified \p PatchOffset.
277
void applyULEB128(uint64_t PatchOffset, uint64_t Val);
278
279
/// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
280
void applySLEB128(uint64_t PatchOffset, uint64_t Val);
281
282
/// Sets output format.
283
void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianess) {
284
this->Format = Format;
285
this->Endianess = Endianess;
286
}
287
288
LinkingGlobalData &GlobalData;
289
290
/// Section data bits.
291
OutSectionDataTy Contents;
292
293
/// Some sections are generated using AsmPrinter. The real section data
294
/// located inside elf file in that case. Following fields points to the
295
/// real section content inside elf file.
296
size_t SectionOffsetInsideAsmPrinterOutputStart = 0;
297
size_t SectionOffsetInsideAsmPrinterOutputEnd = 0;
298
};
299
300
/// This class keeps contents and offsets to the debug sections. Any objects
301
/// which is supposed to be emitted into the debug sections should use this
302
/// class to track debug sections offsets and keep sections data.
303
class OutputSections {
304
public:
305
OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {}
306
307
/// Sets output format for all keeping sections.
308
void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness) {
309
this->Format = Format;
310
this->Endianness = Endianness;
311
}
312
313
/// Returns descriptor for the specified section of \p SectionKind.
314
/// The descriptor should already be created. The llvm_unreachable
315
/// would be raised if it is not.
316
const SectionDescriptor &
317
getSectionDescriptor(DebugSectionKind SectionKind) const {
318
SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);
319
320
if (It == SectionDescriptors.end())
321
llvm_unreachable(
322
formatv("Section {0} does not exist", getSectionName(SectionKind))
323
.str()
324
.c_str());
325
326
return *It->second;
327
}
328
329
/// Returns descriptor for the specified section of \p SectionKind.
330
/// The descriptor should already be created. The llvm_unreachable
331
/// would be raised if it is not.
332
SectionDescriptor &getSectionDescriptor(DebugSectionKind SectionKind) {
333
SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
334
335
if (It == SectionDescriptors.end())
336
llvm_unreachable(
337
formatv("Section {0} does not exist", getSectionName(SectionKind))
338
.str()
339
.c_str());
340
341
assert(It->second.get() != nullptr);
342
343
return *It->second;
344
}
345
346
/// Returns descriptor for the specified section of \p SectionKind.
347
/// Returns std::nullopt if section descriptor is not created yet.
348
std::optional<const SectionDescriptor *>
349
tryGetSectionDescriptor(DebugSectionKind SectionKind) const {
350
SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);
351
352
if (It == SectionDescriptors.end())
353
return std::nullopt;
354
355
return It->second.get();
356
}
357
358
/// Returns descriptor for the specified section of \p SectionKind.
359
/// Returns std::nullopt if section descriptor is not created yet.
360
std::optional<SectionDescriptor *>
361
tryGetSectionDescriptor(DebugSectionKind SectionKind) {
362
SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
363
364
if (It == SectionDescriptors.end())
365
return std::nullopt;
366
367
return It->second.get();
368
}
369
370
/// Returns descriptor for the specified section of \p SectionKind.
371
/// If descriptor does not exist then creates it.
372
SectionDescriptor &
373
getOrCreateSectionDescriptor(DebugSectionKind SectionKind) {
374
SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
375
376
if (It == SectionDescriptors.end()) {
377
SectionDescriptor *Section =
378
new SectionDescriptor(SectionKind, GlobalData, Format, Endianness);
379
auto Result = SectionDescriptors.try_emplace(SectionKind, Section);
380
assert(Result.second);
381
382
It = Result.first;
383
}
384
385
return *It->second;
386
}
387
388
/// Erases data of all sections.
389
void eraseSections() {
390
for (auto &Section : SectionDescriptors)
391
Section.second->clearAllSectionData();
392
}
393
394
/// Enumerate all sections and call \p Handler for each.
395
void forEach(function_ref<void(SectionDescriptor &)> Handler) {
396
for (auto &Section : SectionDescriptors) {
397
assert(Section.second.get() != nullptr);
398
Handler(*(Section.second));
399
}
400
}
401
402
/// Enumerate all sections and call \p Handler for each.
403
void forEach(
404
function_ref<void(std::shared_ptr<SectionDescriptor> Section)> Handler) {
405
for (auto &Section : SectionDescriptors)
406
Handler(Section.second);
407
}
408
409
/// Enumerate all sections, for each section set current offset
410
/// (kept by \p SectionSizesAccumulator), update current offset with section
411
/// length.
412
void assignSectionsOffsetAndAccumulateSize(
413
std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) {
414
for (auto &Section : SectionDescriptors) {
415
Section.second->StartOffset =
416
SectionSizesAccumulator[static_cast<uint8_t>(
417
Section.second->getKind())];
418
SectionSizesAccumulator[static_cast<uint8_t>(
419
Section.second->getKind())] += Section.second->getContents().size();
420
}
421
}
422
423
/// Enumerate all sections, for each section apply all section patches.
424
void applyPatches(SectionDescriptor &Section,
425
StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
426
StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
427
TypeUnit *TypeUnitPtr);
428
429
/// Endiannes for the sections.
430
llvm::endianness getEndianness() const { return Endianness; }
431
432
/// Return DWARF version.
433
uint16_t getVersion() const { return Format.Version; }
434
435
/// Return size of header of debug_info table.
436
uint16_t getDebugInfoHeaderSize() const {
437
return Format.Version >= 5 ? 12 : 11;
438
}
439
440
/// Return size of header of debug_ table.
441
uint16_t getDebugAddrHeaderSize() const {
442
assert(Format.Version >= 5);
443
return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
444
}
445
446
/// Return size of header of debug_str_offsets table.
447
uint16_t getDebugStrOffsetsHeaderSize() const {
448
assert(Format.Version >= 5);
449
return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
450
}
451
452
/// Return size of address.
453
const dwarf::FormParams &getFormParams() const { return Format; }
454
455
protected:
456
LinkingGlobalData &GlobalData;
457
458
/// Format for sections.
459
dwarf::FormParams Format = {4, 4, dwarf::DWARF32};
460
461
/// Endiannes for sections.
462
llvm::endianness Endianness = llvm::endianness::native;
463
464
/// All keeping sections.
465
using SectionsSetTy =
466
std::map<DebugSectionKind, std::shared_ptr<SectionDescriptor>>;
467
SectionsSetTy SectionDescriptors;
468
};
469
470
} // end of namespace parallel
471
} // end of namespace dwarf_linker
472
} // end of namespace llvm
473
474
#endif // LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
475
476