Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / lib / DWARFLinker / Parallel / OutputSections.h
blobd2e4622aa764332b6036ef1485552d33fe3dd108
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 //===----------------------------------------------------------------------===//
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"
28 #include <array>
29 #include <cstdint>
31 namespace llvm {
32 namespace dwarf_linker {
33 namespace parallel {
35 class TypeUnit;
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.
41 struct SectionPatch {
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,
81 uint32_t RefIdx);
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);
108 DIE *Die = nullptr;
109 TypeEntry *TypeName = nullptr;
110 TypeEntry *RefTypeName = nullptr;
113 struct DebugTypeStrPatch : SectionPatch {
114 DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
115 StringEntry *String);
117 DIE *Die = nullptr;
118 TypeEntry *TypeName = nullptr;
119 StringEntry *String = nullptr;
122 struct DebugTypeLineStrPatch : SectionPatch {
123 DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
124 StringEntry *String);
126 DIE *Die = nullptr;
127 TypeEntry *TypeName = nullptr;
128 StringEntry *String = nullptr;
131 struct DebugTypeDeclFilePatch {
132 DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory,
133 StringEntry *FilePath);
135 DIE *Die = nullptr;
136 TypeEntry *TypeName = nullptr;
137 StringEntry *Directory = nullptr;
138 StringEntry *FilePath = nullptr;
139 uint32_t FileID = 0;
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;
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;
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(&notePatch(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)
223 return Contents;
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)
238 return;
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) {
256 OS << String;
257 emitIntVal(0, 1);
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);
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);
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 {
304 public:
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())
321 llvm_unreachable(
322 formatv("Section {0} does not exist", getSectionName(SectionKind))
323 .str()
324 .c_str());
326 return *It->second;
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())
336 llvm_unreachable(
337 formatv("Section {0} does not exist", getSectionName(SectionKind))
338 .str()
339 .c_str());
341 assert(It->second.get() != nullptr);
343 return *It->second;
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())
353 return std::nullopt;
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())
365 return std::nullopt;
367 return It->second.get();
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);
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);
382 It = Result.first;
385 return *It->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.
403 void forEach(
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
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();
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; }
455 protected:
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