1 //===- OutputSections.h -----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
10 #define LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
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"
32 namespace dwarf_linker
{
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.
42 uint64_t PatchOffset
= 0;
45 /// This structure is used to update strings offsets into .debug_str.
46 struct DebugStrPatch
: SectionPatch
{
47 const StringEntry
*String
= nullptr;
50 /// This structure is used to update strings offsets into .debug_line_str.
51 struct DebugLineStrPatch
: SectionPatch
{
52 const StringEntry
*String
= nullptr;
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;
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;
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
) {}
75 PointerIntPair
<SectionDescriptor
*, 1> SectionPtr
;
78 /// This structure is used to update reference to the DIE.
79 struct DebugDieRefPatch
: SectionPatch
{
80 DebugDieRefPatch(uint64_t PatchOffset
, CompileUnit
*SrcCU
, CompileUnit
*RefCU
,
83 PointerIntPair
<CompileUnit
*, 1> RefCU
;
84 uint64_t RefDieIdxOrClonedOffset
= 0;
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
);
92 PointerIntPair
<CompileUnit
*, 1> RefCU
;
93 uint64_t RefDieIdxOrClonedOffset
= 0;
96 /// This structure is used to update reference to the type DIE.
97 struct DebugDieTypeRefPatch
: SectionPatch
{
98 DebugDieTypeRefPatch(uint64_t PatchOffset
, TypeEntry
*RefTypeName
);
100 TypeEntry
*RefTypeName
= nullptr;
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
);
109 TypeEntry
*TypeName
= nullptr;
110 TypeEntry
*RefTypeName
= nullptr;
113 struct DebugTypeStrPatch
: SectionPatch
{
114 DebugTypeStrPatch(uint64_t PatchOffset
, DIE
*Die
, TypeEntry
*TypeName
,
115 StringEntry
*String
);
118 TypeEntry
*TypeName
= nullptr;
119 StringEntry
*String
= nullptr;
122 struct DebugTypeLineStrPatch
: SectionPatch
{
123 DebugTypeLineStrPatch(uint64_t PatchOffset
, DIE
*Die
, TypeEntry
*TypeName
,
124 StringEntry
*String
);
127 TypeEntry
*TypeName
= nullptr;
128 StringEntry
*String
= nullptr;
131 struct DebugTypeDeclFilePatch
{
132 DebugTypeDeclFilePatch(DIE
*Die
, TypeEntry
*TypeName
, StringEntry
*Directory
,
133 StringEntry
*FilePath
);
136 TypeEntry
*TypeName
= nullptr;
137 StringEntry
*Directory
= nullptr;
138 StringEntry
*FilePath
= nullptr;
142 /// Type for section data.
143 using OutSectionDataTy
= SmallString
<0>;
145 /// Type for list of pointers to patches offsets.
146 using OffsetsPtrVector
= SmallVector
<uint64_t *>;
148 class OutputSections
;
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
;
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
) {}
172 /// Erase whole section content(data bits, list of patches).
173 void clearAllSectionData();
175 /// Erase only section output data bits.
176 void clearSectionContent();
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;
184 /// Stream which stores data to the Contents.
185 raw_svector_ostream OS
;
188 #define ADD_PATCHES_LIST(T) \
189 T ¬ePatch(const T &Patch) { return List##T.add(Patch); } \
190 ArrayList<T> List##T;
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
)
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(¬ePatch(Patch
).PatchOffset
);
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();
220 /// Returns section content.
221 StringRef
getContents() override
{
222 if (SectionOffsetInsideAsmPrinterOutputStart
== 0)
225 return Contents
.slice(SectionOffsetInsideAsmPrinterOutputStart
,
226 SectionOffsetInsideAsmPrinterOutputEnd
);
229 /// Emit unit length into the current section contents.
230 void emitUnitLength(uint64_t Length
) {
231 maybeEmitDwarf64Mark();
232 emitIntVal(Length
, getFormParams().getDwarfOffsetByteSize());
235 /// Emit DWARF64 mark into the current section contents.
236 void maybeEmitDwarf64Mark() {
237 if (getFormParams().Format
!= dwarf::DWARF64
)
239 emitIntVal(dwarf::DW_LENGTH_DWARF64
, 4);
242 /// Emit specified offset value into the current section contents.
243 void emitOffset(uint64_t Val
) {
244 emitIntVal(Val
, getFormParams().getDwarfOffsetByteSize());
247 /// Emit specified integer value into the current section contents.
248 void emitIntVal(uint64_t Val
, unsigned Size
);
250 void emitString(dwarf::Form StringForm
, const char *StringVal
);
252 void emitBinaryData(llvm::StringRef Data
);
254 /// Emit specified inplace string value into the current section contents.
255 void emitInplaceString(StringRef String
) {
260 /// Emit string placeholder into the current section contents.
261 void emitStringPlaceholder() {
262 // emit bad offset which should be updated later.
263 emitOffset(0xBADDEF);
266 /// Write specified \p Value of \p AttrForm to the \p PatchOffset.
267 void apply(uint64_t PatchOffset
, dwarf::Form AttrForm
, uint64_t Val
);
269 /// Returns integer value of \p Size located by specified \p PatchOffset.
270 uint64_t getIntVal(uint64_t PatchOffset
, unsigned Size
);
273 /// Writes integer value \p Val of \p Size by specified \p PatchOffset.
274 void applyIntVal(uint64_t PatchOffset
, uint64_t Val
, unsigned Size
);
276 /// Writes integer value \p Val of ULEB128 format by specified \p PatchOffset.
277 void applyULEB128(uint64_t PatchOffset
, uint64_t Val
);
279 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
280 void applySLEB128(uint64_t PatchOffset
, uint64_t Val
);
282 /// Sets output format.
283 void setOutputFormat(dwarf::FormParams Format
, llvm::endianness Endianess
) {
284 this->Format
= Format
;
285 this->Endianess
= Endianess
;
288 LinkingGlobalData
&GlobalData
;
290 /// Section data bits.
291 OutSectionDataTy Contents
;
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;
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
{
305 OutputSections(LinkingGlobalData
&GlobalData
) : GlobalData(GlobalData
) {}
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
;
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
);
320 if (It
== SectionDescriptors
.end())
322 formatv("Section {0} does not exist", getSectionName(SectionKind
))
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
);
335 if (It
== SectionDescriptors
.end())
337 formatv("Section {0} does not exist", getSectionName(SectionKind
))
341 assert(It
->second
.get() != nullptr);
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
);
352 if (It
== SectionDescriptors
.end())
355 return It
->second
.get();
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
);
364 if (It
== SectionDescriptors
.end())
367 return It
->second
.get();
370 /// Returns descriptor for the specified section of \p SectionKind.
371 /// If descriptor does not exist then creates it.
373 getOrCreateSectionDescriptor(DebugSectionKind SectionKind
) {
374 SectionsSetTy::iterator It
= SectionDescriptors
.find(SectionKind
);
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
);
388 /// Erases data of all sections.
389 void eraseSections() {
390 for (auto &Section
: SectionDescriptors
)
391 Section
.second
->clearAllSectionData();
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
));
402 /// Enumerate all sections and call \p Handler for each.
404 function_ref
<void(std::shared_ptr
<SectionDescriptor
> Section
)> Handler
) {
405 for (auto &Section
: SectionDescriptors
)
406 Handler(Section
.second
);
409 /// Enumerate all sections, for each section set current offset
410 /// (kept by \p SectionSizesAccumulator), update current offset with section
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();
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
);
429 /// Endiannes for the sections.
430 llvm::endianness
getEndianness() const { return Endianness
; }
432 /// Return DWARF version.
433 uint16_t getVersion() const { return Format
.Version
; }
435 /// Return size of header of debug_info table.
436 uint16_t getDebugInfoHeaderSize() const {
437 return Format
.Version
>= 5 ? 12 : 11;
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;
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;
452 /// Return size of address.
453 const dwarf::FormParams
&getFormParams() const { return Format
; }
456 LinkingGlobalData
&GlobalData
;
458 /// Format for sections.
459 dwarf::FormParams Format
= {4, 4, dwarf::DWARF32
};
461 /// Endiannes for sections.
462 llvm::endianness Endianness
= llvm::endianness::native
;
464 /// All keeping sections.
465 using SectionsSetTy
=
466 std::map
<DebugSectionKind
, std::shared_ptr
<SectionDescriptor
>>;
467 SectionsSetTy SectionDescriptors
;
470 } // end of namespace parallel
471 } // end of namespace dwarf_linker
472 } // end of namespace llvm
474 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H