LLVM 22.0.0git
OutputSections.h
Go to the documentation of this file.
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"
15#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/Endian.h"
23#include "llvm/Support/Error.h"
25#include "llvm/Support/LEB128.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
43};
44
45/// This structure is used to update strings offsets into .debug_str.
47 const StringEntry *String = nullptr;
48};
49
50/// This structure is used to update strings offsets into .debug_line_str.
52 const StringEntry *String = nullptr;
53};
54
55/// This structure is used to update range list offset into
56/// .debug_ranges/.debug_rnglists.
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.
66};
67
68/// This structure is used to update offset with start of another section.
72 bool AddLocalValue = false)
73 : SectionPatch({PatchOffset}), SectionPtr(SectionPtr, AddLocalValue) {}
74
76};
77
78/// This structure is used to update reference to the DIE.
81 uint32_t RefIdx);
82
85};
86
87/// This structure is used to update reference to the DIE of ULEB128 form.
90 CompileUnit *RefCU, uint32_t RefIdx);
91
94};
95
96/// This structure is used to update reference to the type DIE.
99
101};
102
103/// This structure is used to update reference to the type DIE.
107
108 DIE *Die = nullptr;
109 TypeEntry *TypeName = nullptr;
111};
112
116
117 DIE *Die = nullptr;
118 TypeEntry *TypeName = nullptr;
119 StringEntry *String = nullptr;
120};
121
125
126 DIE *Die = nullptr;
127 TypeEntry *TypeName = nullptr;
128 StringEntry *String = nullptr;
129};
130
134
135 DIE *Die = nullptr;
136 TypeEntry *TypeName = nullptr;
140};
141
142/// Type for section data.
144
145/// Type for list of pointers to patches offsets.
147
148class OutputSections;
149
150/// This structure is used to keep data of the concrete section.
151/// Like data bits, list of patches, format.
154
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()),
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.
183
184protected:
185 /// Section data bits.
187
188public:
189 /// Stream which stores data to the Contents.
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.
224
225 /// Returns section content.
228 return Contents;
229
232 }
233
234 /// Emit unit length into the current section contents.
237 emitIntVal(Length, getFormParams().getDwarfOffsetByteSize());
238 }
239
240 /// Emit DWARF64 mark into the current section contents.
243 return;
245 }
246
247 /// Emit specified offset value into the current section contents.
249 emitIntVal(Val, 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
258
259 /// Emit specified inplace string value into the current section contents.
261 OS << String;
262 emitIntVal(0, 1);
263 }
264
265 /// Emit string placeholder into the current section contents.
267 // emit bad offset which should be updated later.
268 emitOffset(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.
289 this->Format = Format;
290 this->Endianess = Endianess;
291 }
292
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.
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.
306public:
308
309 /// Sets output format for all keeping sections.
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 &
320 SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);
321
322 if (It == SectionDescriptors.end())
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.
335 SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
336
337 if (It == SectionDescriptors.end())
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 *>
352 SectionsSetTy::const_iterator It = SectionDescriptors.find(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 *>
364 SectionsSetTy::iterator It = SectionDescriptors.find(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.
376 auto [It, Inserted] = SectionDescriptors.try_emplace(SectionKind);
377
378 if (Inserted)
379 It->second = std::make_shared<SectionDescriptor>(SectionKind, GlobalData,
381
382 return *It->second;
383 }
384
385 /// Erases data of all sections.
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.
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.
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,
423 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
424 TypeUnit *TypeUnitPtr);
425
426 /// Endiannes for the sections.
428
429 /// Return DWARF version.
430 uint16_t getVersion() const { return Format.Version; }
431
432 /// Return size of header of debug_info table.
434 return Format.Version >= 5 ? 12 : 11;
435 }
436
437 /// Return size of header of debug_ table.
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.
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:
454
455 /// Format for sections.
457
458 /// Endiannes for sections.
460
461 /// All keeping sections.
463 std::map<DebugSectionKind, std::shared_ptr<SectionDescriptor>>;
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
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains constants used for implementing Dwarf debug support.
uint64_t Size
#define ADD_PATCHES_LIST(T)
Section patches.
This file defines the SmallString class.
A structured debug information entry.
Definition: DIE.h:828
PointerIntPair - This class implements a pair of a pointer and small integer.
SectionKind - This is a simple POD value that classifies the properties of a section.
Definition: SectionKind.h:22
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: SmallString.h:247
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
Stores all information related to a compile unit, be it in its original instance of the object file o...
This class keeps data and services common for the whole linking process.
This class keeps contents and offsets to the debug sections.
std::optional< SectionDescriptor * > tryGetSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
void applyPatches(SectionDescriptor &Section, StringEntryToDwarfStringPoolEntryMap &DebugStrStrings, StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings, TypeUnit *TypeUnitPtr)
Enumerate all sections, for each section apply all section patches.
uint16_t getDebugStrOffsetsHeaderSize() const
Return size of header of debug_str_offsets table.
OutputSections(LinkingGlobalData &GlobalData)
llvm::endianness Endianness
Endiannes for sections.
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.
uint16_t getDebugAddrHeaderSize() const
Return size of header of debug_ table.
std::map< DebugSectionKind, std::shared_ptr< SectionDescriptor > > SectionsSetTy
All keeping sections.
void forEach(function_ref< void(std::shared_ptr< SectionDescriptor > Section)> Handler)
Enumerate all sections and call Handler for each.
void forEach(function_ref< void(SectionDescriptor &)> Handler)
Enumerate all sections and call Handler for each.
llvm::endianness getEndianness() const
Endiannes for the sections.
SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
void assignSectionsOffsetAndAccumulateSize(std::array< uint64_t, SectionKindsNum > &SectionSizesAccumulator)
Enumerate all sections, for each section set current offset (kept by SectionSizesAccumulator),...
const SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
This class creates a DwarfStringPoolEntry for the corresponding StringEntry.
Type Unit is used to represent an artificial compilation unit which keeps all type information.
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:692
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static constexpr const StringLiteral & getSectionName(DebugSectionKind SectionKind)
Return the name of the section.
DebugSectionKind
List of tracked debug tables.
@ DWARF64
Definition: Dwarf.h:92
@ DWARF32
Definition: Dwarf.h:92
@ DW_LENGTH_DWARF64
Indicator of 64-bit DWARF format.
Definition: Dwarf.h:56
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Length
Definition: DWP.cpp:477
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
endianness
Definition: bit.h:71
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
Definition: Dwarf.h:1093
DwarfFormat Format
Definition: Dwarf.h:1096
This structure is used to update reference to the DIE.
PointerIntPair< CompileUnit *, 1 > RefCU
This structure is used to update reference to the type DIE.
This structure is used to update strings offsets into .debug_line_str.
This structure is used to update location list offset into .debug_loc/.debug_loclists.
DebugOffsetPatch(uint64_t PatchOffset, SectionDescriptor *SectionPtr, bool AddLocalValue=false)
PointerIntPair< SectionDescriptor *, 1 > SectionPtr
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 strings offsets into .debug_str.
This structure is used to update reference to the type DIE.
This structure is used to update reference to the DIE of ULEB128 form.
This structure keeps data of the concrete section.
Definition: DWARFLinker.h:94
dwarf::FormParams getFormParams() const
Returns FormParams used by section.
Definition: DWARFLinker.h:108
This structure is used to keep data of the concrete section.
raw_svector_ostream OS
Stream which stores data to the Contents.
void setSizesForSectionCreatedByAsmPrinter()
Some sections are emitted using AsmPrinter.
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.
OutSectionDataTy Contents
Section data bits.
void emitString(dwarf::Form StringForm, const char *StringVal)
void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size)
Writes integer value Val of Size by specified PatchOffset.
void emitIntVal(uint64_t Val, unsigned Size)
Emit specified integer value into the current section contents.
void applySLEB128(uint64_t PatchOffset, uint64_t Val)
Writes integer value Val of SLEB128 format by specified PatchOffset.
void applyULEB128(uint64_t PatchOffset, uint64_t Val)
Writes integer value Val of ULEB128 format by specified PatchOffset.
void maybeEmitDwarf64Mark()
Emit DWARF64 mark into the current section contents.
void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)
Write specified Value of AttrForm to the PatchOffset.
void emitInplaceString(StringRef String)
Emit specified inplace string value into the current section contents.
uint64_t getIntVal(uint64_t PatchOffset, unsigned Size)
Returns integer value of Size located by specified PatchOffset.
void clearSectionContent()
Erase only section output data bits.
StringRef getContents() override
Returns section content.
void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianess)
Sets output format.
size_t SectionOffsetInsideAsmPrinterOutputStart
Some sections are generated using AsmPrinter.
void clearAllSectionData()
Erase whole section content(data bits, list of patches).
SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData, dwarf::FormParams Format, llvm::endianness Endianess)
void emitStringPlaceholder()
Emit string placeholder into the current section contents.
void notePatchWithOffsetUpdate(const T &Patch, OffsetsPtrVector &PatchesOffsetsList)
While creating patches, offsets to attributes may be partially unknown(because size of abbreviation n...
There are fields(sizes, offsets) which should be updated after sections are generated.