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 ¬ePatch(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(¬ePatch(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