xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.h (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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 /// List of tracked debug tables.
38 enum class DebugSectionKind : uint8_t {
39   DebugInfo = 0,
40   DebugLine,
41   DebugFrame,
42   DebugRange,
43   DebugRngLists,
44   DebugLoc,
45   DebugLocLists,
46   DebugARanges,
47   DebugAbbrev,
48   DebugMacinfo,
49   DebugMacro,
50   DebugAddr,
51   DebugStr,
52   DebugLineStr,
53   DebugStrOffsets,
54   DebugPubNames,
55   DebugPubTypes,
56   DebugNames,
57   AppleNames,
58   AppleNamespaces,
59   AppleObjC,
60   AppleTypes,
61   NumberOfEnumEntries // must be last
62 };
63 constexpr static size_t SectionKindsNum =
64     static_cast<size_t>(DebugSectionKind::NumberOfEnumEntries);
65 
66 static constexpr StringLiteral SectionNames[SectionKindsNum] = {
67     "debug_info",     "debug_line",     "debug_frame",       "debug_ranges",
68     "debug_rnglists", "debug_loc",      "debug_loclists",    "debug_aranges",
69     "debug_abbrev",   "debug_macinfo",  "debug_macro",       "debug_addr",
70     "debug_str",      "debug_line_str", "debug_str_offsets", "debug_pubnames",
71     "debug_pubtypes", "debug_names",    "apple_names",       "apple_namespac",
72     "apple_objc",     "apple_types"};
73 
74 static constexpr const StringLiteral &
75 getSectionName(DebugSectionKind SectionKind) {
76   return SectionNames[static_cast<uint8_t>(SectionKind)];
77 }
78 
79 /// Recognise the table name and match it with the DebugSectionKind.
80 std::optional<DebugSectionKind> parseDebugTableName(StringRef Name);
81 
82 /// There are fields(sizes, offsets) which should be updated after
83 /// sections are generated. To remember offsets and related data
84 /// the descendants of SectionPatch structure should be used.
85 
86 struct SectionPatch {
87   uint64_t PatchOffset = 0;
88 };
89 
90 /// This structure is used to update strings offsets into .debug_str.
91 struct DebugStrPatch : SectionPatch {
92   const StringEntry *String = nullptr;
93 };
94 
95 /// This structure is used to update strings offsets into .debug_line_str.
96 struct DebugLineStrPatch : SectionPatch {
97   const StringEntry *String = nullptr;
98 };
99 
100 /// This structure is used to update range list offset into
101 /// .debug_ranges/.debug_rnglists.
102 struct DebugRangePatch : SectionPatch {
103   /// Indicates patch which points to immediate compile unit's attribute.
104   bool IsCompileUnitRanges = false;
105 };
106 
107 /// This structure is used to update location list offset into
108 /// .debug_loc/.debug_loclists.
109 struct DebugLocPatch : SectionPatch {
110   int64_t AddrAdjustmentValue = 0;
111 };
112 
113 /// This structure is used to update offset with start of another section.
114 struct SectionDescriptor;
115 struct DebugOffsetPatch : SectionPatch {
116   DebugOffsetPatch(uint64_t PatchOffset, SectionDescriptor *SectionPtr,
117                    bool AddLocalValue = false)
118       : SectionPatch({PatchOffset}), SectionPtr(SectionPtr, AddLocalValue) {}
119 
120   PointerIntPair<SectionDescriptor *, 1> SectionPtr;
121 };
122 
123 /// This structure is used to update reference to the DIE.
124 struct DebugDieRefPatch : SectionPatch {
125   DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU,
126                    uint32_t RefIdx);
127 
128   PointerIntPair<CompileUnit *, 1> RefCU;
129   uint64_t RefDieIdxOrClonedOffset = 0;
130 };
131 
132 /// This structure is used to update reference to the DIE of ULEB128 form.
133 struct DebugULEB128DieRefPatch : SectionPatch {
134   DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
135                           CompileUnit *RefCU, uint32_t RefIdx);
136 
137   PointerIntPair<CompileUnit *, 1> RefCU;
138   uint64_t RefDieIdxOrClonedOffset = 0;
139 };
140 
141 /// This structure is used to update reference to the type DIE.
142 struct DebugDieTypeRefPatch : SectionPatch {
143   DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName);
144 
145   TypeEntry *RefTypeName = nullptr;
146 };
147 
148 /// This structure is used to update reference to the type DIE.
149 struct DebugType2TypeDieRefPatch : SectionPatch {
150   DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
151                             TypeEntry *RefTypeName);
152 
153   DIE *Die = nullptr;
154   TypeEntry *TypeName = nullptr;
155   TypeEntry *RefTypeName = nullptr;
156 };
157 
158 struct DebugTypeStrPatch : SectionPatch {
159   DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
160                     StringEntry *String);
161 
162   DIE *Die = nullptr;
163   TypeEntry *TypeName = nullptr;
164   StringEntry *String = nullptr;
165 };
166 
167 struct DebugTypeLineStrPatch : SectionPatch {
168   DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
169                         StringEntry *String);
170 
171   DIE *Die = nullptr;
172   TypeEntry *TypeName = nullptr;
173   StringEntry *String = nullptr;
174 };
175 
176 struct DebugTypeDeclFilePatch {
177   DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory,
178                          StringEntry *FilePath);
179 
180   DIE *Die = nullptr;
181   TypeEntry *TypeName = nullptr;
182   StringEntry *Directory = nullptr;
183   StringEntry *FilePath = nullptr;
184   uint32_t FileID = 0;
185 };
186 
187 /// Type for section data.
188 using OutSectionDataTy = SmallString<0>;
189 
190 /// Type for list of pointers to patches offsets.
191 using OffsetsPtrVector = SmallVector<uint64_t *>;
192 
193 class OutputSections;
194 
195 /// This structure is used to keep data of the concrete section.
196 /// Like data bits, list of patches, format.
197 struct SectionDescriptor {
198   friend OutputSections;
199 
200   SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData,
201                     dwarf::FormParams Format, llvm::endianness Endianess)
202       : OS(Contents), ListDebugStrPatch(&GlobalData.getAllocator()),
203         ListDebugLineStrPatch(&GlobalData.getAllocator()),
204         ListDebugRangePatch(&GlobalData.getAllocator()),
205         ListDebugLocPatch(&GlobalData.getAllocator()),
206         ListDebugDieRefPatch(&GlobalData.getAllocator()),
207         ListDebugULEB128DieRefPatch(&GlobalData.getAllocator()),
208         ListDebugOffsetPatch(&GlobalData.getAllocator()),
209         ListDebugDieTypeRefPatch(&GlobalData.getAllocator()),
210         ListDebugType2TypeDieRefPatch(&GlobalData.getAllocator()),
211         ListDebugTypeStrPatch(&GlobalData.getAllocator()),
212         ListDebugTypeLineStrPatch(&GlobalData.getAllocator()),
213         ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()),
214         GlobalData(GlobalData), SectionKind(SectionKind), Format(Format),
215         Endianess(Endianess) {}
216 
217   /// Erase whole section contents(data bits, list of patches).
218   void clearAllSectionData();
219 
220   /// Erase only section output data bits.
221   void clearSectionContent();
222 
223   /// When objects(f.e. compile units) are glued into the single file,
224   /// the debug sections corresponding to the concrete object are assigned
225   /// with offsets inside the whole file. This field keeps offset
226   /// to the debug section, corresponding to this object.
227   uint64_t StartOffset = 0;
228 
229   /// Stream which stores data to the Contents.
230   raw_svector_ostream OS;
231 
232   /// Section patches.
233 #define ADD_PATCHES_LIST(T)                                                    \
234   T &notePatch(const T &Patch) { return List##T.add(Patch); }                  \
235   ArrayList<T> List##T;
236 
237   ADD_PATCHES_LIST(DebugStrPatch)
238   ADD_PATCHES_LIST(DebugLineStrPatch)
239   ADD_PATCHES_LIST(DebugRangePatch)
240   ADD_PATCHES_LIST(DebugLocPatch)
241   ADD_PATCHES_LIST(DebugDieRefPatch)
242   ADD_PATCHES_LIST(DebugULEB128DieRefPatch)
243   ADD_PATCHES_LIST(DebugOffsetPatch)
244   ADD_PATCHES_LIST(DebugDieTypeRefPatch)
245   ADD_PATCHES_LIST(DebugType2TypeDieRefPatch)
246   ADD_PATCHES_LIST(DebugTypeStrPatch)
247   ADD_PATCHES_LIST(DebugTypeLineStrPatch)
248   ADD_PATCHES_LIST(DebugTypeDeclFilePatch)
249 
250   /// While creating patches, offsets to attributes may be partially
251   /// unknown(because size of abbreviation number is unknown). In such case we
252   /// remember patch itself and pointer to patch application offset to add size
253   /// of abbreviation number later.
254   template <typename T>
255   void notePatchWithOffsetUpdate(const T &Patch,
256                                  OffsetsPtrVector &PatchesOffsetsList) {
257     PatchesOffsetsList.emplace_back(&notePatch(Patch).PatchOffset);
258   }
259 
260   /// Some sections are emitted using AsmPrinter. In that case "Contents"
261   /// member of SectionDescriptor contains elf file. This method searches
262   /// for section data inside elf file and remember offset to it.
263   void setSizesForSectionCreatedByAsmPrinter();
264 
265   /// Returns section content.
266   StringRef getContents() {
267     if (SectionOffsetInsideAsmPrinterOutputStart == 0)
268       return StringRef(Contents.data(), Contents.size());
269 
270     return Contents.slice(SectionOffsetInsideAsmPrinterOutputStart,
271                           SectionOffsetInsideAsmPrinterOutputEnd);
272   }
273 
274   /// Emit unit length into the current section contents.
275   void emitUnitLength(uint64_t Length) {
276     maybeEmitDwarf64Mark();
277     emitIntVal(Length, getFormParams().getDwarfOffsetByteSize());
278   }
279 
280   /// Emit DWARF64 mark into the current section contents.
281   void maybeEmitDwarf64Mark() {
282     if (getFormParams().Format != dwarf::DWARF64)
283       return;
284     emitIntVal(dwarf::DW_LENGTH_DWARF64, 4);
285   }
286 
287   /// Emit specified offset value into the current section contents.
288   void emitOffset(uint64_t Val) {
289     emitIntVal(Val, getFormParams().getDwarfOffsetByteSize());
290   }
291 
292   /// Emit specified integer value into the current section contents.
293   void emitIntVal(uint64_t Val, unsigned Size);
294 
295   void emitString(dwarf::Form StringForm, const char *StringVal);
296 
297   void emitBinaryData(llvm::StringRef Data);
298 
299   /// Emit specified inplace string value into the current section contents.
300   void emitInplaceString(StringRef String) {
301     OS << GlobalData.translateString(String);
302     emitIntVal(0, 1);
303   }
304 
305   /// Emit string placeholder into the current section contents.
306   void emitStringPlaceholder() {
307     // emit bad offset which should be updated later.
308     emitOffset(0xBADDEF);
309   }
310 
311   /// Write specified \p Value of \p AttrForm to the \p PatchOffset.
312   void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val);
313 
314   /// Returns section kind.
315   DebugSectionKind getKind() { return SectionKind; }
316 
317   /// Returns section name.
318   const StringLiteral &getName() const { return getSectionName(SectionKind); }
319 
320   /// Returns endianess used by section.
321   llvm::endianness getEndianess() const { return Endianess; }
322 
323   /// Returns FormParams used by section.
324   dwarf::FormParams getFormParams() const { return Format; }
325 
326   /// Returns integer value of \p Size located by specified \p PatchOffset.
327   uint64_t getIntVal(uint64_t PatchOffset, unsigned Size);
328 
329 protected:
330   /// Writes integer value \p Val of \p Size by specified \p PatchOffset.
331   void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size);
332 
333   /// Writes integer value \p Val of ULEB128 format by specified \p PatchOffset.
334   void applyULEB128(uint64_t PatchOffset, uint64_t Val);
335 
336   /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
337   void applySLEB128(uint64_t PatchOffset, uint64_t Val);
338 
339   /// Sets output format.
340   void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianess) {
341     this->Format = Format;
342     this->Endianess = Endianess;
343   }
344 
345   LinkingGlobalData &GlobalData;
346 
347   /// The section kind.
348   DebugSectionKind SectionKind = DebugSectionKind::NumberOfEnumEntries;
349 
350   /// Section data bits.
351   OutSectionDataTy Contents;
352 
353   /// Some sections are generated using AsmPrinter. The real section data
354   /// located inside elf file in that case. Following fields points to the
355   /// real section content inside elf file.
356   size_t SectionOffsetInsideAsmPrinterOutputStart = 0;
357   size_t SectionOffsetInsideAsmPrinterOutputEnd = 0;
358 
359   /// Output format.
360   dwarf::FormParams Format = {4, 4, dwarf::DWARF32};
361   llvm::endianness Endianess = llvm::endianness::little;
362 };
363 
364 /// This class keeps contents and offsets to the debug sections. Any objects
365 /// which is supposed to be emitted into the debug sections should use this
366 /// class to track debug sections offsets and keep sections data.
367 class OutputSections {
368 public:
369   OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {}
370 
371   /// Sets output format for all keeping sections.
372   void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness) {
373     this->Format = Format;
374     this->Endianness = Endianness;
375   }
376 
377   /// Returns descriptor for the specified section of \p SectionKind.
378   /// The descriptor should already be created. The llvm_unreachable
379   /// would be raised if it is not.
380   const SectionDescriptor &
381   getSectionDescriptor(DebugSectionKind SectionKind) const {
382     SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);
383 
384     if (It == SectionDescriptors.end())
385       llvm_unreachable(
386           formatv("Section {0} does not exist", getSectionName(SectionKind))
387               .str()
388               .c_str());
389 
390     return It->second;
391   }
392 
393   /// Returns descriptor for the specified section of \p SectionKind.
394   /// The descriptor should already be created. The llvm_unreachable
395   /// would be raised if it is not.
396   SectionDescriptor &getSectionDescriptor(DebugSectionKind SectionKind) {
397     SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
398 
399     if (It == SectionDescriptors.end())
400       llvm_unreachable(
401           formatv("Section {0} does not exist", getSectionName(SectionKind))
402               .str()
403               .c_str());
404 
405     return It->second;
406   }
407 
408   /// Returns descriptor for the specified section of \p SectionKind.
409   /// Returns std::nullopt if section descriptor is not created yet.
410   std::optional<const SectionDescriptor *>
411   tryGetSectionDescriptor(DebugSectionKind SectionKind) const {
412     SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);
413 
414     if (It == SectionDescriptors.end())
415       return std::nullopt;
416 
417     return &It->second;
418   }
419 
420   /// Returns descriptor for the specified section of \p SectionKind.
421   /// Returns std::nullopt if section descriptor is not created yet.
422   std::optional<SectionDescriptor *>
423   tryGetSectionDescriptor(DebugSectionKind SectionKind) {
424     SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
425 
426     if (It == SectionDescriptors.end())
427       return std::nullopt;
428 
429     return &It->second;
430   }
431 
432   /// Returns descriptor for the specified section of \p SectionKind.
433   /// If descriptor does not exist then creates it.
434   SectionDescriptor &
435   getOrCreateSectionDescriptor(DebugSectionKind SectionKind) {
436     return SectionDescriptors
437         .try_emplace(SectionKind, SectionKind, GlobalData, Format, Endianness)
438         .first->second;
439   }
440 
441   /// Erases data of all sections.
442   void eraseSections() {
443     for (auto &Section : SectionDescriptors)
444       Section.second.clearAllSectionData();
445   }
446 
447   /// Enumerate all sections and call \p Handler for each.
448   void forEach(function_ref<void(SectionDescriptor &)> Handler) {
449     for (auto &Section : SectionDescriptors)
450       Handler(Section.second);
451   }
452 
453   /// Enumerate all sections, for each section set current offset
454   /// (kept by \p SectionSizesAccumulator), update current offset with section
455   /// length.
456   void assignSectionsOffsetAndAccumulateSize(
457       std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) {
458     for (auto &Section : SectionDescriptors) {
459       Section.second.StartOffset = SectionSizesAccumulator[static_cast<uint8_t>(
460           Section.second.getKind())];
461       SectionSizesAccumulator[static_cast<uint8_t>(Section.second.getKind())] +=
462           Section.second.getContents().size();
463     }
464   }
465 
466   /// Enumerate all sections, for each section apply all section patches.
467   void applyPatches(SectionDescriptor &Section,
468                     StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
469                     StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
470                     TypeUnit *TypeUnitPtr);
471 
472   /// Endiannes for the sections.
473   llvm::endianness getEndianness() const { return Endianness; }
474 
475   /// Return DWARF version.
476   uint16_t getVersion() const { return Format.Version; }
477 
478   /// Return size of header of debug_info table.
479   uint16_t getDebugInfoHeaderSize() const {
480     return Format.Version >= 5 ? 12 : 11;
481   }
482 
483   /// Return size of header of debug_ table.
484   uint16_t getDebugAddrHeaderSize() const {
485     assert(Format.Version >= 5);
486     return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
487   }
488 
489   /// Return size of header of debug_str_offsets table.
490   uint16_t getDebugStrOffsetsHeaderSize() const {
491     assert(Format.Version >= 5);
492     return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
493   }
494 
495   /// Return size of address.
496   const dwarf::FormParams &getFormParams() const { return Format; }
497 
498 protected:
499   LinkingGlobalData &GlobalData;
500 
501   /// Format for sections.
502   dwarf::FormParams Format = {4, 4, dwarf::DWARF32};
503 
504   /// Endiannes for sections.
505   llvm::endianness Endianness = llvm::endianness::native;
506 
507   /// All keeping sections.
508   using SectionsSetTy = std::map<DebugSectionKind, SectionDescriptor>;
509   SectionsSetTy SectionDescriptors;
510 };
511 
512 } // end of namespace parallel
513 } // end of namespace dwarf_linker
514 } // end of namespace llvm
515 
516 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
517