xref: /freebsd-src/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
11db9f3b2SDimitry Andric //===- OutputSections.h -----------------------------------------*- C++ -*-===//
21db9f3b2SDimitry Andric //
31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61db9f3b2SDimitry Andric //
71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===//
81db9f3b2SDimitry Andric 
91db9f3b2SDimitry Andric #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
101db9f3b2SDimitry Andric #define LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
111db9f3b2SDimitry Andric 
121db9f3b2SDimitry Andric #include "ArrayList.h"
131db9f3b2SDimitry Andric #include "StringEntryToDwarfStringPoolEntryMap.h"
141db9f3b2SDimitry Andric #include "llvm/ADT/SmallString.h"
151db9f3b2SDimitry Andric #include "llvm/ADT/StringRef.h"
161db9f3b2SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
171db9f3b2SDimitry Andric #include "llvm/CodeGen/DwarfStringPoolEntry.h"
181db9f3b2SDimitry Andric #include "llvm/DWARFLinker/StringPool.h"
191db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
201db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFObject.h"
211db9f3b2SDimitry Andric #include "llvm/Object/ObjectFile.h"
221db9f3b2SDimitry Andric #include "llvm/Support/Endian.h"
231db9f3b2SDimitry Andric #include "llvm/Support/Error.h"
241db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h"
251db9f3b2SDimitry Andric #include "llvm/Support/LEB128.h"
261db9f3b2SDimitry Andric #include "llvm/Support/MemoryBufferRef.h"
271db9f3b2SDimitry Andric #include "llvm/Support/raw_ostream.h"
281db9f3b2SDimitry Andric #include <array>
291db9f3b2SDimitry Andric #include <cstdint>
301db9f3b2SDimitry Andric 
311db9f3b2SDimitry Andric namespace llvm {
321db9f3b2SDimitry Andric namespace dwarf_linker {
331db9f3b2SDimitry Andric namespace parallel {
341db9f3b2SDimitry Andric 
351db9f3b2SDimitry Andric class TypeUnit;
361db9f3b2SDimitry Andric 
371db9f3b2SDimitry Andric /// There are fields(sizes, offsets) which should be updated after
381db9f3b2SDimitry Andric /// sections are generated. To remember offsets and related data
391db9f3b2SDimitry Andric /// the descendants of SectionPatch structure should be used.
401db9f3b2SDimitry Andric 
411db9f3b2SDimitry Andric struct SectionPatch {
421db9f3b2SDimitry Andric   uint64_t PatchOffset = 0;
431db9f3b2SDimitry Andric };
441db9f3b2SDimitry Andric 
451db9f3b2SDimitry Andric /// This structure is used to update strings offsets into .debug_str.
461db9f3b2SDimitry Andric struct DebugStrPatch : SectionPatch {
471db9f3b2SDimitry Andric   const StringEntry *String = nullptr;
481db9f3b2SDimitry Andric };
491db9f3b2SDimitry Andric 
501db9f3b2SDimitry Andric /// This structure is used to update strings offsets into .debug_line_str.
511db9f3b2SDimitry Andric struct DebugLineStrPatch : SectionPatch {
521db9f3b2SDimitry Andric   const StringEntry *String = nullptr;
531db9f3b2SDimitry Andric };
541db9f3b2SDimitry Andric 
551db9f3b2SDimitry Andric /// This structure is used to update range list offset into
561db9f3b2SDimitry Andric /// .debug_ranges/.debug_rnglists.
571db9f3b2SDimitry Andric struct DebugRangePatch : SectionPatch {
581db9f3b2SDimitry Andric   /// Indicates patch which points to immediate compile unit's attribute.
591db9f3b2SDimitry Andric   bool IsCompileUnitRanges = false;
601db9f3b2SDimitry Andric };
611db9f3b2SDimitry Andric 
621db9f3b2SDimitry Andric /// This structure is used to update location list offset into
631db9f3b2SDimitry Andric /// .debug_loc/.debug_loclists.
641db9f3b2SDimitry Andric struct DebugLocPatch : SectionPatch {
651db9f3b2SDimitry Andric   int64_t AddrAdjustmentValue = 0;
661db9f3b2SDimitry Andric };
671db9f3b2SDimitry Andric 
681db9f3b2SDimitry Andric /// This structure is used to update offset with start of another section.
691db9f3b2SDimitry Andric struct SectionDescriptor;
701db9f3b2SDimitry Andric struct DebugOffsetPatch : SectionPatch {
711db9f3b2SDimitry Andric   DebugOffsetPatch(uint64_t PatchOffset, SectionDescriptor *SectionPtr,
721db9f3b2SDimitry Andric                    bool AddLocalValue = false)
731db9f3b2SDimitry Andric       : SectionPatch({PatchOffset}), SectionPtr(SectionPtr, AddLocalValue) {}
741db9f3b2SDimitry Andric 
751db9f3b2SDimitry Andric   PointerIntPair<SectionDescriptor *, 1> SectionPtr;
761db9f3b2SDimitry Andric };
771db9f3b2SDimitry Andric 
781db9f3b2SDimitry Andric /// This structure is used to update reference to the DIE.
791db9f3b2SDimitry Andric struct DebugDieRefPatch : SectionPatch {
801db9f3b2SDimitry Andric   DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU,
811db9f3b2SDimitry Andric                    uint32_t RefIdx);
821db9f3b2SDimitry Andric 
831db9f3b2SDimitry Andric   PointerIntPair<CompileUnit *, 1> RefCU;
841db9f3b2SDimitry Andric   uint64_t RefDieIdxOrClonedOffset = 0;
851db9f3b2SDimitry Andric };
861db9f3b2SDimitry Andric 
871db9f3b2SDimitry Andric /// This structure is used to update reference to the DIE of ULEB128 form.
881db9f3b2SDimitry Andric struct DebugULEB128DieRefPatch : SectionPatch {
891db9f3b2SDimitry Andric   DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
901db9f3b2SDimitry Andric                           CompileUnit *RefCU, uint32_t RefIdx);
911db9f3b2SDimitry Andric 
921db9f3b2SDimitry Andric   PointerIntPair<CompileUnit *, 1> RefCU;
931db9f3b2SDimitry Andric   uint64_t RefDieIdxOrClonedOffset = 0;
941db9f3b2SDimitry Andric };
951db9f3b2SDimitry Andric 
961db9f3b2SDimitry Andric /// This structure is used to update reference to the type DIE.
971db9f3b2SDimitry Andric struct DebugDieTypeRefPatch : SectionPatch {
981db9f3b2SDimitry Andric   DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName);
991db9f3b2SDimitry Andric 
1001db9f3b2SDimitry Andric   TypeEntry *RefTypeName = nullptr;
1011db9f3b2SDimitry Andric };
1021db9f3b2SDimitry Andric 
1031db9f3b2SDimitry Andric /// This structure is used to update reference to the type DIE.
1041db9f3b2SDimitry Andric struct DebugType2TypeDieRefPatch : SectionPatch {
1051db9f3b2SDimitry Andric   DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
1061db9f3b2SDimitry Andric                             TypeEntry *RefTypeName);
1071db9f3b2SDimitry Andric 
1081db9f3b2SDimitry Andric   DIE *Die = nullptr;
1091db9f3b2SDimitry Andric   TypeEntry *TypeName = nullptr;
1101db9f3b2SDimitry Andric   TypeEntry *RefTypeName = nullptr;
1111db9f3b2SDimitry Andric };
1121db9f3b2SDimitry Andric 
1131db9f3b2SDimitry Andric struct DebugTypeStrPatch : SectionPatch {
1141db9f3b2SDimitry Andric   DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
1151db9f3b2SDimitry Andric                     StringEntry *String);
1161db9f3b2SDimitry Andric 
1171db9f3b2SDimitry Andric   DIE *Die = nullptr;
1181db9f3b2SDimitry Andric   TypeEntry *TypeName = nullptr;
1191db9f3b2SDimitry Andric   StringEntry *String = nullptr;
1201db9f3b2SDimitry Andric };
1211db9f3b2SDimitry Andric 
1221db9f3b2SDimitry Andric struct DebugTypeLineStrPatch : SectionPatch {
1231db9f3b2SDimitry Andric   DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
1241db9f3b2SDimitry Andric                         StringEntry *String);
1251db9f3b2SDimitry Andric 
1261db9f3b2SDimitry Andric   DIE *Die = nullptr;
1271db9f3b2SDimitry Andric   TypeEntry *TypeName = nullptr;
1281db9f3b2SDimitry Andric   StringEntry *String = nullptr;
1291db9f3b2SDimitry Andric };
1301db9f3b2SDimitry Andric 
1311db9f3b2SDimitry Andric struct DebugTypeDeclFilePatch {
1321db9f3b2SDimitry Andric   DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory,
1331db9f3b2SDimitry Andric                          StringEntry *FilePath);
1341db9f3b2SDimitry Andric 
1351db9f3b2SDimitry Andric   DIE *Die = nullptr;
1361db9f3b2SDimitry Andric   TypeEntry *TypeName = nullptr;
1371db9f3b2SDimitry Andric   StringEntry *Directory = nullptr;
1381db9f3b2SDimitry Andric   StringEntry *FilePath = nullptr;
1391db9f3b2SDimitry Andric   uint32_t FileID = 0;
1401db9f3b2SDimitry Andric };
1411db9f3b2SDimitry Andric 
1421db9f3b2SDimitry Andric /// Type for section data.
1431db9f3b2SDimitry Andric using OutSectionDataTy = SmallString<0>;
1441db9f3b2SDimitry Andric 
1451db9f3b2SDimitry Andric /// Type for list of pointers to patches offsets.
1461db9f3b2SDimitry Andric using OffsetsPtrVector = SmallVector<uint64_t *>;
1471db9f3b2SDimitry Andric 
1481db9f3b2SDimitry Andric class OutputSections;
1491db9f3b2SDimitry Andric 
1501db9f3b2SDimitry Andric /// This structure is used to keep data of the concrete section.
1511db9f3b2SDimitry Andric /// Like data bits, list of patches, format.
1527a6dacacSDimitry Andric struct SectionDescriptor : SectionDescriptorBase {
1531db9f3b2SDimitry Andric   friend OutputSections;
1541db9f3b2SDimitry Andric 
1551db9f3b2SDimitry Andric   SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData,
1561db9f3b2SDimitry Andric                     dwarf::FormParams Format, llvm::endianness Endianess)
1577a6dacacSDimitry Andric       : SectionDescriptorBase(SectionKind, Format, Endianess), OS(Contents),
1587a6dacacSDimitry Andric         ListDebugStrPatch(&GlobalData.getAllocator()),
1591db9f3b2SDimitry Andric         ListDebugLineStrPatch(&GlobalData.getAllocator()),
1601db9f3b2SDimitry Andric         ListDebugRangePatch(&GlobalData.getAllocator()),
1611db9f3b2SDimitry Andric         ListDebugLocPatch(&GlobalData.getAllocator()),
1621db9f3b2SDimitry Andric         ListDebugDieRefPatch(&GlobalData.getAllocator()),
1631db9f3b2SDimitry Andric         ListDebugULEB128DieRefPatch(&GlobalData.getAllocator()),
1641db9f3b2SDimitry Andric         ListDebugOffsetPatch(&GlobalData.getAllocator()),
1651db9f3b2SDimitry Andric         ListDebugDieTypeRefPatch(&GlobalData.getAllocator()),
1661db9f3b2SDimitry Andric         ListDebugType2TypeDieRefPatch(&GlobalData.getAllocator()),
1671db9f3b2SDimitry Andric         ListDebugTypeStrPatch(&GlobalData.getAllocator()),
1681db9f3b2SDimitry Andric         ListDebugTypeLineStrPatch(&GlobalData.getAllocator()),
1691db9f3b2SDimitry Andric         ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()),
1707a6dacacSDimitry Andric         GlobalData(GlobalData) {}
1711db9f3b2SDimitry Andric 
1727a6dacacSDimitry Andric   /// Erase whole section content(data bits, list of patches).
1731db9f3b2SDimitry Andric   void clearAllSectionData();
1741db9f3b2SDimitry Andric 
1751db9f3b2SDimitry Andric   /// Erase only section output data bits.
1761db9f3b2SDimitry Andric   void clearSectionContent();
1771db9f3b2SDimitry Andric 
1781db9f3b2SDimitry Andric   /// When objects(f.e. compile units) are glued into the single file,
1791db9f3b2SDimitry Andric   /// the debug sections corresponding to the concrete object are assigned
1801db9f3b2SDimitry Andric   /// with offsets inside the whole file. This field keeps offset
1811db9f3b2SDimitry Andric   /// to the debug section, corresponding to this object.
1821db9f3b2SDimitry Andric   uint64_t StartOffset = 0;
1831db9f3b2SDimitry Andric 
1841db9f3b2SDimitry Andric   /// Stream which stores data to the Contents.
1851db9f3b2SDimitry Andric   raw_svector_ostream OS;
1861db9f3b2SDimitry Andric 
1871db9f3b2SDimitry Andric   /// Section patches.
1881db9f3b2SDimitry Andric #define ADD_PATCHES_LIST(T)                                                    \
1891db9f3b2SDimitry Andric   T &notePatch(const T &Patch) { return List##T.add(Patch); }                  \
1901db9f3b2SDimitry Andric   ArrayList<T> List##T;
1911db9f3b2SDimitry Andric 
1921db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugStrPatch)
1931db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugLineStrPatch)
1941db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugRangePatch)
1951db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugLocPatch)
1961db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugDieRefPatch)
1971db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugULEB128DieRefPatch)
1981db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugOffsetPatch)
1991db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugDieTypeRefPatch)
2001db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugType2TypeDieRefPatch)
2011db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugTypeStrPatch)
2021db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugTypeLineStrPatch)
2031db9f3b2SDimitry Andric   ADD_PATCHES_LIST(DebugTypeDeclFilePatch)
2041db9f3b2SDimitry Andric 
2051db9f3b2SDimitry Andric   /// While creating patches, offsets to attributes may be partially
2061db9f3b2SDimitry Andric   /// unknown(because size of abbreviation number is unknown). In such case we
2071db9f3b2SDimitry Andric   /// remember patch itself and pointer to patch application offset to add size
2081db9f3b2SDimitry Andric   /// of abbreviation number later.
2091db9f3b2SDimitry Andric   template <typename T>
2101db9f3b2SDimitry Andric   void notePatchWithOffsetUpdate(const T &Patch,
2111db9f3b2SDimitry Andric                                  OffsetsPtrVector &PatchesOffsetsList) {
2121db9f3b2SDimitry Andric     PatchesOffsetsList.emplace_back(&notePatch(Patch).PatchOffset);
2131db9f3b2SDimitry Andric   }
2141db9f3b2SDimitry Andric 
2151db9f3b2SDimitry Andric   /// Some sections are emitted using AsmPrinter. In that case "Contents"
2161db9f3b2SDimitry Andric   /// member of SectionDescriptor contains elf file. This method searches
2171db9f3b2SDimitry Andric   /// for section data inside elf file and remember offset to it.
2181db9f3b2SDimitry Andric   void setSizesForSectionCreatedByAsmPrinter();
2191db9f3b2SDimitry Andric 
2201db9f3b2SDimitry Andric   /// Returns section content.
2217a6dacacSDimitry Andric   StringRef getContents() override {
2221db9f3b2SDimitry Andric     if (SectionOffsetInsideAsmPrinterOutputStart == 0)
223*0fca6ea1SDimitry Andric       return Contents;
2241db9f3b2SDimitry Andric 
2251db9f3b2SDimitry Andric     return Contents.slice(SectionOffsetInsideAsmPrinterOutputStart,
2261db9f3b2SDimitry Andric                           SectionOffsetInsideAsmPrinterOutputEnd);
2271db9f3b2SDimitry Andric   }
2281db9f3b2SDimitry Andric 
2291db9f3b2SDimitry Andric   /// Emit unit length into the current section contents.
2301db9f3b2SDimitry Andric   void emitUnitLength(uint64_t Length) {
2311db9f3b2SDimitry Andric     maybeEmitDwarf64Mark();
2321db9f3b2SDimitry Andric     emitIntVal(Length, getFormParams().getDwarfOffsetByteSize());
2331db9f3b2SDimitry Andric   }
2341db9f3b2SDimitry Andric 
2351db9f3b2SDimitry Andric   /// Emit DWARF64 mark into the current section contents.
2361db9f3b2SDimitry Andric   void maybeEmitDwarf64Mark() {
2371db9f3b2SDimitry Andric     if (getFormParams().Format != dwarf::DWARF64)
2381db9f3b2SDimitry Andric       return;
2391db9f3b2SDimitry Andric     emitIntVal(dwarf::DW_LENGTH_DWARF64, 4);
2401db9f3b2SDimitry Andric   }
2411db9f3b2SDimitry Andric 
2421db9f3b2SDimitry Andric   /// Emit specified offset value into the current section contents.
2431db9f3b2SDimitry Andric   void emitOffset(uint64_t Val) {
2441db9f3b2SDimitry Andric     emitIntVal(Val, getFormParams().getDwarfOffsetByteSize());
2451db9f3b2SDimitry Andric   }
2461db9f3b2SDimitry Andric 
2471db9f3b2SDimitry Andric   /// Emit specified integer value into the current section contents.
2481db9f3b2SDimitry Andric   void emitIntVal(uint64_t Val, unsigned Size);
2491db9f3b2SDimitry Andric 
2501db9f3b2SDimitry Andric   void emitString(dwarf::Form StringForm, const char *StringVal);
2511db9f3b2SDimitry Andric 
2521db9f3b2SDimitry Andric   void emitBinaryData(llvm::StringRef Data);
2531db9f3b2SDimitry Andric 
2541db9f3b2SDimitry Andric   /// Emit specified inplace string value into the current section contents.
2551db9f3b2SDimitry Andric   void emitInplaceString(StringRef String) {
256*0fca6ea1SDimitry Andric     OS << String;
2571db9f3b2SDimitry Andric     emitIntVal(0, 1);
2581db9f3b2SDimitry Andric   }
2591db9f3b2SDimitry Andric 
2601db9f3b2SDimitry Andric   /// Emit string placeholder into the current section contents.
2611db9f3b2SDimitry Andric   void emitStringPlaceholder() {
2621db9f3b2SDimitry Andric     // emit bad offset which should be updated later.
2631db9f3b2SDimitry Andric     emitOffset(0xBADDEF);
2641db9f3b2SDimitry Andric   }
2651db9f3b2SDimitry Andric 
2661db9f3b2SDimitry Andric   /// Write specified \p Value of \p AttrForm to the \p PatchOffset.
2671db9f3b2SDimitry Andric   void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val);
2681db9f3b2SDimitry Andric 
2691db9f3b2SDimitry Andric   /// Returns integer value of \p Size located by specified \p PatchOffset.
2701db9f3b2SDimitry Andric   uint64_t getIntVal(uint64_t PatchOffset, unsigned Size);
2711db9f3b2SDimitry Andric 
2721db9f3b2SDimitry Andric protected:
2731db9f3b2SDimitry Andric   /// Writes integer value \p Val of \p Size by specified \p PatchOffset.
2741db9f3b2SDimitry Andric   void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size);
2751db9f3b2SDimitry Andric 
2761db9f3b2SDimitry Andric   /// Writes integer value \p Val of ULEB128 format by specified \p PatchOffset.
2771db9f3b2SDimitry Andric   void applyULEB128(uint64_t PatchOffset, uint64_t Val);
2781db9f3b2SDimitry Andric 
2791db9f3b2SDimitry Andric   /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
2801db9f3b2SDimitry Andric   void applySLEB128(uint64_t PatchOffset, uint64_t Val);
2811db9f3b2SDimitry Andric 
2821db9f3b2SDimitry Andric   /// Sets output format.
2831db9f3b2SDimitry Andric   void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianess) {
2841db9f3b2SDimitry Andric     this->Format = Format;
2851db9f3b2SDimitry Andric     this->Endianess = Endianess;
2861db9f3b2SDimitry Andric   }
2871db9f3b2SDimitry Andric 
2881db9f3b2SDimitry Andric   LinkingGlobalData &GlobalData;
2891db9f3b2SDimitry Andric 
2901db9f3b2SDimitry Andric   /// Section data bits.
2911db9f3b2SDimitry Andric   OutSectionDataTy Contents;
2921db9f3b2SDimitry Andric 
2931db9f3b2SDimitry Andric   /// Some sections are generated using AsmPrinter. The real section data
2941db9f3b2SDimitry Andric   /// located inside elf file in that case. Following fields points to the
2951db9f3b2SDimitry Andric   /// real section content inside elf file.
2961db9f3b2SDimitry Andric   size_t SectionOffsetInsideAsmPrinterOutputStart = 0;
2971db9f3b2SDimitry Andric   size_t SectionOffsetInsideAsmPrinterOutputEnd = 0;
2981db9f3b2SDimitry Andric };
2991db9f3b2SDimitry Andric 
3001db9f3b2SDimitry Andric /// This class keeps contents and offsets to the debug sections. Any objects
3011db9f3b2SDimitry Andric /// which is supposed to be emitted into the debug sections should use this
3021db9f3b2SDimitry Andric /// class to track debug sections offsets and keep sections data.
3031db9f3b2SDimitry Andric class OutputSections {
3041db9f3b2SDimitry Andric public:
3051db9f3b2SDimitry Andric   OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {}
3061db9f3b2SDimitry Andric 
3071db9f3b2SDimitry Andric   /// Sets output format for all keeping sections.
3081db9f3b2SDimitry Andric   void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness) {
3091db9f3b2SDimitry Andric     this->Format = Format;
3101db9f3b2SDimitry Andric     this->Endianness = Endianness;
3111db9f3b2SDimitry Andric   }
3121db9f3b2SDimitry Andric 
3131db9f3b2SDimitry Andric   /// Returns descriptor for the specified section of \p SectionKind.
3141db9f3b2SDimitry Andric   /// The descriptor should already be created. The llvm_unreachable
3151db9f3b2SDimitry Andric   /// would be raised if it is not.
3161db9f3b2SDimitry Andric   const SectionDescriptor &
3171db9f3b2SDimitry Andric   getSectionDescriptor(DebugSectionKind SectionKind) const {
3181db9f3b2SDimitry Andric     SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);
3191db9f3b2SDimitry Andric 
3201db9f3b2SDimitry Andric     if (It == SectionDescriptors.end())
3211db9f3b2SDimitry Andric       llvm_unreachable(
3221db9f3b2SDimitry Andric           formatv("Section {0} does not exist", getSectionName(SectionKind))
3231db9f3b2SDimitry Andric               .str()
3241db9f3b2SDimitry Andric               .c_str());
3251db9f3b2SDimitry Andric 
3267a6dacacSDimitry Andric     return *It->second;
3271db9f3b2SDimitry Andric   }
3281db9f3b2SDimitry Andric 
3291db9f3b2SDimitry Andric   /// Returns descriptor for the specified section of \p SectionKind.
3301db9f3b2SDimitry Andric   /// The descriptor should already be created. The llvm_unreachable
3311db9f3b2SDimitry Andric   /// would be raised if it is not.
3321db9f3b2SDimitry Andric   SectionDescriptor &getSectionDescriptor(DebugSectionKind SectionKind) {
3331db9f3b2SDimitry Andric     SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
3341db9f3b2SDimitry Andric 
3351db9f3b2SDimitry Andric     if (It == SectionDescriptors.end())
3361db9f3b2SDimitry Andric       llvm_unreachable(
3371db9f3b2SDimitry Andric           formatv("Section {0} does not exist", getSectionName(SectionKind))
3381db9f3b2SDimitry Andric               .str()
3391db9f3b2SDimitry Andric               .c_str());
3401db9f3b2SDimitry Andric 
3417a6dacacSDimitry Andric     assert(It->second.get() != nullptr);
3427a6dacacSDimitry Andric 
3437a6dacacSDimitry Andric     return *It->second;
3441db9f3b2SDimitry Andric   }
3451db9f3b2SDimitry Andric 
3461db9f3b2SDimitry Andric   /// Returns descriptor for the specified section of \p SectionKind.
3471db9f3b2SDimitry Andric   /// Returns std::nullopt if section descriptor is not created yet.
3481db9f3b2SDimitry Andric   std::optional<const SectionDescriptor *>
3491db9f3b2SDimitry Andric   tryGetSectionDescriptor(DebugSectionKind SectionKind) const {
3501db9f3b2SDimitry Andric     SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);
3511db9f3b2SDimitry Andric 
3521db9f3b2SDimitry Andric     if (It == SectionDescriptors.end())
3531db9f3b2SDimitry Andric       return std::nullopt;
3541db9f3b2SDimitry Andric 
3557a6dacacSDimitry Andric     return It->second.get();
3561db9f3b2SDimitry Andric   }
3571db9f3b2SDimitry Andric 
3581db9f3b2SDimitry Andric   /// Returns descriptor for the specified section of \p SectionKind.
3591db9f3b2SDimitry Andric   /// Returns std::nullopt if section descriptor is not created yet.
3601db9f3b2SDimitry Andric   std::optional<SectionDescriptor *>
3611db9f3b2SDimitry Andric   tryGetSectionDescriptor(DebugSectionKind SectionKind) {
3621db9f3b2SDimitry Andric     SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
3631db9f3b2SDimitry Andric 
3641db9f3b2SDimitry Andric     if (It == SectionDescriptors.end())
3651db9f3b2SDimitry Andric       return std::nullopt;
3661db9f3b2SDimitry Andric 
3677a6dacacSDimitry Andric     return It->second.get();
3681db9f3b2SDimitry Andric   }
3691db9f3b2SDimitry Andric 
3701db9f3b2SDimitry Andric   /// Returns descriptor for the specified section of \p SectionKind.
3711db9f3b2SDimitry Andric   /// If descriptor does not exist then creates it.
3721db9f3b2SDimitry Andric   SectionDescriptor &
3731db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind SectionKind) {
3747a6dacacSDimitry Andric     SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
3757a6dacacSDimitry Andric 
3767a6dacacSDimitry Andric     if (It == SectionDescriptors.end()) {
3777a6dacacSDimitry Andric       SectionDescriptor *Section =
3787a6dacacSDimitry Andric           new SectionDescriptor(SectionKind, GlobalData, Format, Endianness);
3797a6dacacSDimitry Andric       auto Result = SectionDescriptors.try_emplace(SectionKind, Section);
3807a6dacacSDimitry Andric       assert(Result.second);
3817a6dacacSDimitry Andric 
3827a6dacacSDimitry Andric       It = Result.first;
3837a6dacacSDimitry Andric     }
3847a6dacacSDimitry Andric 
3857a6dacacSDimitry Andric     return *It->second;
3861db9f3b2SDimitry Andric   }
3871db9f3b2SDimitry Andric 
3881db9f3b2SDimitry Andric   /// Erases data of all sections.
3891db9f3b2SDimitry Andric   void eraseSections() {
3901db9f3b2SDimitry Andric     for (auto &Section : SectionDescriptors)
3917a6dacacSDimitry Andric       Section.second->clearAllSectionData();
3921db9f3b2SDimitry Andric   }
3931db9f3b2SDimitry Andric 
3941db9f3b2SDimitry Andric   /// Enumerate all sections and call \p Handler for each.
3951db9f3b2SDimitry Andric   void forEach(function_ref<void(SectionDescriptor &)> Handler) {
3967a6dacacSDimitry Andric     for (auto &Section : SectionDescriptors) {
3977a6dacacSDimitry Andric       assert(Section.second.get() != nullptr);
3987a6dacacSDimitry Andric       Handler(*(Section.second));
3997a6dacacSDimitry Andric     }
4007a6dacacSDimitry Andric   }
4017a6dacacSDimitry Andric 
4027a6dacacSDimitry Andric   /// Enumerate all sections and call \p Handler for each.
4037a6dacacSDimitry Andric   void forEach(
4047a6dacacSDimitry Andric       function_ref<void(std::shared_ptr<SectionDescriptor> Section)> Handler) {
4051db9f3b2SDimitry Andric     for (auto &Section : SectionDescriptors)
4061db9f3b2SDimitry Andric       Handler(Section.second);
4071db9f3b2SDimitry Andric   }
4081db9f3b2SDimitry Andric 
4091db9f3b2SDimitry Andric   /// Enumerate all sections, for each section set current offset
4101db9f3b2SDimitry Andric   /// (kept by \p SectionSizesAccumulator), update current offset with section
4111db9f3b2SDimitry Andric   /// length.
4121db9f3b2SDimitry Andric   void assignSectionsOffsetAndAccumulateSize(
4131db9f3b2SDimitry Andric       std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) {
4141db9f3b2SDimitry Andric     for (auto &Section : SectionDescriptors) {
4157a6dacacSDimitry Andric       Section.second->StartOffset =
4167a6dacacSDimitry Andric           SectionSizesAccumulator[static_cast<uint8_t>(
4177a6dacacSDimitry Andric               Section.second->getKind())];
4187a6dacacSDimitry Andric       SectionSizesAccumulator[static_cast<uint8_t>(
4197a6dacacSDimitry Andric           Section.second->getKind())] += Section.second->getContents().size();
4201db9f3b2SDimitry Andric     }
4211db9f3b2SDimitry Andric   }
4221db9f3b2SDimitry Andric 
4231db9f3b2SDimitry Andric   /// Enumerate all sections, for each section apply all section patches.
4241db9f3b2SDimitry Andric   void applyPatches(SectionDescriptor &Section,
4251db9f3b2SDimitry Andric                     StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
4261db9f3b2SDimitry Andric                     StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
4271db9f3b2SDimitry Andric                     TypeUnit *TypeUnitPtr);
4281db9f3b2SDimitry Andric 
4291db9f3b2SDimitry Andric   /// Endiannes for the sections.
4301db9f3b2SDimitry Andric   llvm::endianness getEndianness() const { return Endianness; }
4311db9f3b2SDimitry Andric 
4321db9f3b2SDimitry Andric   /// Return DWARF version.
4331db9f3b2SDimitry Andric   uint16_t getVersion() const { return Format.Version; }
4341db9f3b2SDimitry Andric 
4351db9f3b2SDimitry Andric   /// Return size of header of debug_info table.
4361db9f3b2SDimitry Andric   uint16_t getDebugInfoHeaderSize() const {
4371db9f3b2SDimitry Andric     return Format.Version >= 5 ? 12 : 11;
4381db9f3b2SDimitry Andric   }
4391db9f3b2SDimitry Andric 
4401db9f3b2SDimitry Andric   /// Return size of header of debug_ table.
4411db9f3b2SDimitry Andric   uint16_t getDebugAddrHeaderSize() const {
4421db9f3b2SDimitry Andric     assert(Format.Version >= 5);
4431db9f3b2SDimitry Andric     return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
4441db9f3b2SDimitry Andric   }
4451db9f3b2SDimitry Andric 
4461db9f3b2SDimitry Andric   /// Return size of header of debug_str_offsets table.
4471db9f3b2SDimitry Andric   uint16_t getDebugStrOffsetsHeaderSize() const {
4481db9f3b2SDimitry Andric     assert(Format.Version >= 5);
4491db9f3b2SDimitry Andric     return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
4501db9f3b2SDimitry Andric   }
4511db9f3b2SDimitry Andric 
4521db9f3b2SDimitry Andric   /// Return size of address.
4531db9f3b2SDimitry Andric   const dwarf::FormParams &getFormParams() const { return Format; }
4541db9f3b2SDimitry Andric 
4551db9f3b2SDimitry Andric protected:
4561db9f3b2SDimitry Andric   LinkingGlobalData &GlobalData;
4571db9f3b2SDimitry Andric 
4581db9f3b2SDimitry Andric   /// Format for sections.
4591db9f3b2SDimitry Andric   dwarf::FormParams Format = {4, 4, dwarf::DWARF32};
4601db9f3b2SDimitry Andric 
4611db9f3b2SDimitry Andric   /// Endiannes for sections.
4621db9f3b2SDimitry Andric   llvm::endianness Endianness = llvm::endianness::native;
4631db9f3b2SDimitry Andric 
4641db9f3b2SDimitry Andric   /// All keeping sections.
4657a6dacacSDimitry Andric   using SectionsSetTy =
4667a6dacacSDimitry Andric       std::map<DebugSectionKind, std::shared_ptr<SectionDescriptor>>;
4671db9f3b2SDimitry Andric   SectionsSetTy SectionDescriptors;
4681db9f3b2SDimitry Andric };
4691db9f3b2SDimitry Andric 
4701db9f3b2SDimitry Andric } // end of namespace parallel
4711db9f3b2SDimitry Andric } // end of namespace dwarf_linker
4721db9f3b2SDimitry Andric } // end of namespace llvm
4731db9f3b2SDimitry Andric 
4741db9f3b2SDimitry Andric #endif // LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H
475