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