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.
152*7a6dacacSDimitry Andric struct SectionDescriptor : SectionDescriptorBase {
1531db9f3b2SDimitry Andric   friend OutputSections;
1541db9f3b2SDimitry Andric 
SectionDescriptorSectionDescriptor1551db9f3b2SDimitry Andric   SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData,
1561db9f3b2SDimitry Andric                     dwarf::FormParams Format, llvm::endianness Endianess)
157*7a6dacacSDimitry Andric       : SectionDescriptorBase(SectionKind, Format, Endianess), OS(Contents),
158*7a6dacacSDimitry 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()),
170*7a6dacacSDimitry Andric         GlobalData(GlobalData) {}
1711db9f3b2SDimitry Andric 
172*7a6dacacSDimitry 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)
ADD_PATCHES_LISTSectionDescriptor1931db9f3b2SDimitry 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.
getContentsSectionDescriptor221*7a6dacacSDimitry Andric   StringRef getContents() override {
2221db9f3b2SDimitry Andric     if (SectionOffsetInsideAsmPrinterOutputStart == 0)
2231db9f3b2SDimitry Andric       return StringRef(Contents.data(), Contents.size());
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.
emitUnitLengthSectionDescriptor2301db9f3b2SDimitry 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.
maybeEmitDwarf64MarkSectionDescriptor2361db9f3b2SDimitry 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.
emitOffsetSectionDescriptor2431db9f3b2SDimitry 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.
emitInplaceStringSectionDescriptor2551db9f3b2SDimitry Andric   void emitInplaceString(StringRef String) {
2561db9f3b2SDimitry Andric     OS << GlobalData.translateString(String);
2571db9f3b2SDimitry Andric     emitIntVal(0, 1);
2581db9f3b2SDimitry Andric   }
2591db9f3b2SDimitry Andric 
2601db9f3b2SDimitry Andric   /// Emit string placeholder into the current section contents.
emitStringPlaceholderSectionDescriptor2611db9f3b2SDimitry 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.
setOutputFormatSectionDescriptor2831db9f3b2SDimitry 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:
OutputSections(LinkingGlobalData & GlobalData)3051db9f3b2SDimitry Andric   OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {}
3061db9f3b2SDimitry Andric 
3071db9f3b2SDimitry Andric   /// Sets output format for all keeping sections.
setOutputFormat(dwarf::FormParams Format,llvm::endianness Endianness)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 &
getSectionDescriptor(DebugSectionKind SectionKind)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 
326*7a6dacacSDimitry 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.
getSectionDescriptor(DebugSectionKind SectionKind)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 
341*7a6dacacSDimitry Andric     assert(It->second.get() != nullptr);
342*7a6dacacSDimitry Andric 
343*7a6dacacSDimitry 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 *>
tryGetSectionDescriptor(DebugSectionKind SectionKind)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 
355*7a6dacacSDimitry 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 *>
tryGetSectionDescriptor(DebugSectionKind SectionKind)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 
367*7a6dacacSDimitry 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 &
getOrCreateSectionDescriptor(DebugSectionKind SectionKind)3731db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind SectionKind) {
374*7a6dacacSDimitry Andric     SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
375*7a6dacacSDimitry Andric 
376*7a6dacacSDimitry Andric     if (It == SectionDescriptors.end()) {
377*7a6dacacSDimitry Andric       SectionDescriptor *Section =
378*7a6dacacSDimitry Andric           new SectionDescriptor(SectionKind, GlobalData, Format, Endianness);
379*7a6dacacSDimitry Andric       auto Result = SectionDescriptors.try_emplace(SectionKind, Section);
380*7a6dacacSDimitry Andric       assert(Result.second);
381*7a6dacacSDimitry Andric 
382*7a6dacacSDimitry Andric       It = Result.first;
383*7a6dacacSDimitry Andric     }
384*7a6dacacSDimitry Andric 
385*7a6dacacSDimitry Andric     return *It->second;
3861db9f3b2SDimitry Andric   }
3871db9f3b2SDimitry Andric 
3881db9f3b2SDimitry Andric   /// Erases data of all sections.
eraseSections()3891db9f3b2SDimitry Andric   void eraseSections() {
3901db9f3b2SDimitry Andric     for (auto &Section : SectionDescriptors)
391*7a6dacacSDimitry Andric       Section.second->clearAllSectionData();
3921db9f3b2SDimitry Andric   }
3931db9f3b2SDimitry Andric 
3941db9f3b2SDimitry Andric   /// Enumerate all sections and call \p Handler for each.
forEach(function_ref<void (SectionDescriptor &)> Handler)3951db9f3b2SDimitry Andric   void forEach(function_ref<void(SectionDescriptor &)> Handler) {
396*7a6dacacSDimitry Andric     for (auto &Section : SectionDescriptors) {
397*7a6dacacSDimitry Andric       assert(Section.second.get() != nullptr);
398*7a6dacacSDimitry Andric       Handler(*(Section.second));
399*7a6dacacSDimitry Andric     }
400*7a6dacacSDimitry Andric   }
401*7a6dacacSDimitry Andric 
402*7a6dacacSDimitry Andric   /// Enumerate all sections and call \p Handler for each.
forEach(function_ref<void (std::shared_ptr<SectionDescriptor> Section)> Handler)403*7a6dacacSDimitry Andric   void forEach(
404*7a6dacacSDimitry 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.
assignSectionsOffsetAndAccumulateSize(std::array<uint64_t,SectionKindsNum> & SectionSizesAccumulator)4121db9f3b2SDimitry Andric   void assignSectionsOffsetAndAccumulateSize(
4131db9f3b2SDimitry Andric       std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) {
4141db9f3b2SDimitry Andric     for (auto &Section : SectionDescriptors) {
415*7a6dacacSDimitry Andric       Section.second->StartOffset =
416*7a6dacacSDimitry Andric           SectionSizesAccumulator[static_cast<uint8_t>(
417*7a6dacacSDimitry Andric               Section.second->getKind())];
418*7a6dacacSDimitry Andric       SectionSizesAccumulator[static_cast<uint8_t>(
419*7a6dacacSDimitry 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.
getEndianness()4301db9f3b2SDimitry Andric   llvm::endianness getEndianness() const { return Endianness; }
4311db9f3b2SDimitry Andric 
4321db9f3b2SDimitry Andric   /// Return DWARF version.
getVersion()4331db9f3b2SDimitry Andric   uint16_t getVersion() const { return Format.Version; }
4341db9f3b2SDimitry Andric 
4351db9f3b2SDimitry Andric   /// Return size of header of debug_info table.
getDebugInfoHeaderSize()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.
getDebugAddrHeaderSize()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.
getDebugStrOffsetsHeaderSize()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.
getFormParams()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.
465*7a6dacacSDimitry Andric   using SectionsSetTy =
466*7a6dacacSDimitry 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