xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
SectionDescriptorSectionDescriptor155   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)
ADD_PATCHES_LISTSectionDescriptor193   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.
getContentsSectionDescriptor221   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.
emitUnitLengthSectionDescriptor230   void emitUnitLength(uint64_t Length) {
231     maybeEmitDwarf64Mark();
232     emitIntVal(Length, getFormParams().getDwarfOffsetByteSize());
233   }
234 
235   /// Emit DWARF64 mark into the current section contents.
maybeEmitDwarf64MarkSectionDescriptor236   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.
emitOffsetSectionDescriptor243   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.
emitInplaceStringSectionDescriptor255   void emitInplaceString(StringRef String) {
256     OS << String;
257     emitIntVal(0, 1);
258   }
259 
260   /// Emit string placeholder into the current section contents.
emitStringPlaceholderSectionDescriptor261   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.
setOutputFormatSectionDescriptor283   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:
OutputSections(LinkingGlobalData & GlobalData)305   OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {}
306 
307   /// Sets output format for all keeping sections.
setOutputFormat(dwarf::FormParams Format,llvm::endianness Endianness)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 &
getSectionDescriptor(DebugSectionKind SectionKind)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.
getSectionDescriptor(DebugSectionKind SectionKind)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 *>
tryGetSectionDescriptor(DebugSectionKind SectionKind)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 *>
tryGetSectionDescriptor(DebugSectionKind SectionKind)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 &
getOrCreateSectionDescriptor(DebugSectionKind SectionKind)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.
eraseSections()389   void eraseSections() {
390     for (auto &Section : SectionDescriptors)
391       Section.second->clearAllSectionData();
392   }
393 
394   /// Enumerate all sections and call \p Handler for each.
forEach(function_ref<void (SectionDescriptor &)> Handler)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.
forEach(function_ref<void (std::shared_ptr<SectionDescriptor> Section)> Handler)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.
assignSectionsOffsetAndAccumulateSize(std::array<uint64_t,SectionKindsNum> & SectionSizesAccumulator)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.
getEndianness()430   llvm::endianness getEndianness() const { return Endianness; }
431 
432   /// Return DWARF version.
getVersion()433   uint16_t getVersion() const { return Format.Version; }
434 
435   /// Return size of header of debug_info table.
getDebugInfoHeaderSize()436   uint16_t getDebugInfoHeaderSize() const {
437     return Format.Version >= 5 ? 12 : 11;
438   }
439 
440   /// Return size of header of debug_ table.
getDebugAddrHeaderSize()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.
getDebugStrOffsetsHeaderSize()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.
getFormParams()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