Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.h
35292 views
//===- OutputSections.h -----------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H9#define LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H1011#include "ArrayList.h"12#include "StringEntryToDwarfStringPoolEntryMap.h"13#include "llvm/ADT/SmallString.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/BinaryFormat/Dwarf.h"16#include "llvm/CodeGen/DwarfStringPoolEntry.h"17#include "llvm/DWARFLinker/StringPool.h"18#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"19#include "llvm/DebugInfo/DWARF/DWARFObject.h"20#include "llvm/Object/ObjectFile.h"21#include "llvm/Support/Endian.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/FormatVariadic.h"24#include "llvm/Support/LEB128.h"25#include "llvm/Support/MemoryBufferRef.h"26#include "llvm/Support/raw_ostream.h"27#include <array>28#include <cstdint>2930namespace llvm {31namespace dwarf_linker {32namespace parallel {3334class TypeUnit;3536/// There are fields(sizes, offsets) which should be updated after37/// sections are generated. To remember offsets and related data38/// the descendants of SectionPatch structure should be used.3940struct SectionPatch {41uint64_t PatchOffset = 0;42};4344/// This structure is used to update strings offsets into .debug_str.45struct DebugStrPatch : SectionPatch {46const StringEntry *String = nullptr;47};4849/// This structure is used to update strings offsets into .debug_line_str.50struct DebugLineStrPatch : SectionPatch {51const StringEntry *String = nullptr;52};5354/// This structure is used to update range list offset into55/// .debug_ranges/.debug_rnglists.56struct DebugRangePatch : SectionPatch {57/// Indicates patch which points to immediate compile unit's attribute.58bool IsCompileUnitRanges = false;59};6061/// This structure is used to update location list offset into62/// .debug_loc/.debug_loclists.63struct DebugLocPatch : SectionPatch {64int64_t AddrAdjustmentValue = 0;65};6667/// This structure is used to update offset with start of another section.68struct SectionDescriptor;69struct DebugOffsetPatch : SectionPatch {70DebugOffsetPatch(uint64_t PatchOffset, SectionDescriptor *SectionPtr,71bool AddLocalValue = false)72: SectionPatch({PatchOffset}), SectionPtr(SectionPtr, AddLocalValue) {}7374PointerIntPair<SectionDescriptor *, 1> SectionPtr;75};7677/// This structure is used to update reference to the DIE.78struct DebugDieRefPatch : SectionPatch {79DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU,80uint32_t RefIdx);8182PointerIntPair<CompileUnit *, 1> RefCU;83uint64_t RefDieIdxOrClonedOffset = 0;84};8586/// This structure is used to update reference to the DIE of ULEB128 form.87struct DebugULEB128DieRefPatch : SectionPatch {88DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,89CompileUnit *RefCU, uint32_t RefIdx);9091PointerIntPair<CompileUnit *, 1> RefCU;92uint64_t RefDieIdxOrClonedOffset = 0;93};9495/// This structure is used to update reference to the type DIE.96struct DebugDieTypeRefPatch : SectionPatch {97DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName);9899TypeEntry *RefTypeName = nullptr;100};101102/// This structure is used to update reference to the type DIE.103struct DebugType2TypeDieRefPatch : SectionPatch {104DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,105TypeEntry *RefTypeName);106107DIE *Die = nullptr;108TypeEntry *TypeName = nullptr;109TypeEntry *RefTypeName = nullptr;110};111112struct DebugTypeStrPatch : SectionPatch {113DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,114StringEntry *String);115116DIE *Die = nullptr;117TypeEntry *TypeName = nullptr;118StringEntry *String = nullptr;119};120121struct DebugTypeLineStrPatch : SectionPatch {122DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,123StringEntry *String);124125DIE *Die = nullptr;126TypeEntry *TypeName = nullptr;127StringEntry *String = nullptr;128};129130struct DebugTypeDeclFilePatch {131DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory,132StringEntry *FilePath);133134DIE *Die = nullptr;135TypeEntry *TypeName = nullptr;136StringEntry *Directory = nullptr;137StringEntry *FilePath = nullptr;138uint32_t FileID = 0;139};140141/// Type for section data.142using OutSectionDataTy = SmallString<0>;143144/// Type for list of pointers to patches offsets.145using OffsetsPtrVector = SmallVector<uint64_t *>;146147class OutputSections;148149/// This structure is used to keep data of the concrete section.150/// Like data bits, list of patches, format.151struct SectionDescriptor : SectionDescriptorBase {152friend OutputSections;153154SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData,155dwarf::FormParams Format, llvm::endianness Endianess)156: SectionDescriptorBase(SectionKind, Format, Endianess), OS(Contents),157ListDebugStrPatch(&GlobalData.getAllocator()),158ListDebugLineStrPatch(&GlobalData.getAllocator()),159ListDebugRangePatch(&GlobalData.getAllocator()),160ListDebugLocPatch(&GlobalData.getAllocator()),161ListDebugDieRefPatch(&GlobalData.getAllocator()),162ListDebugULEB128DieRefPatch(&GlobalData.getAllocator()),163ListDebugOffsetPatch(&GlobalData.getAllocator()),164ListDebugDieTypeRefPatch(&GlobalData.getAllocator()),165ListDebugType2TypeDieRefPatch(&GlobalData.getAllocator()),166ListDebugTypeStrPatch(&GlobalData.getAllocator()),167ListDebugTypeLineStrPatch(&GlobalData.getAllocator()),168ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()),169GlobalData(GlobalData) {}170171/// Erase whole section content(data bits, list of patches).172void clearAllSectionData();173174/// Erase only section output data bits.175void clearSectionContent();176177/// When objects(f.e. compile units) are glued into the single file,178/// the debug sections corresponding to the concrete object are assigned179/// with offsets inside the whole file. This field keeps offset180/// to the debug section, corresponding to this object.181uint64_t StartOffset = 0;182183/// Stream which stores data to the Contents.184raw_svector_ostream OS;185186/// Section patches.187#define ADD_PATCHES_LIST(T) \188T ¬ePatch(const T &Patch) { return List##T.add(Patch); } \189ArrayList<T> List##T;190191ADD_PATCHES_LIST(DebugStrPatch)192ADD_PATCHES_LIST(DebugLineStrPatch)193ADD_PATCHES_LIST(DebugRangePatch)194ADD_PATCHES_LIST(DebugLocPatch)195ADD_PATCHES_LIST(DebugDieRefPatch)196ADD_PATCHES_LIST(DebugULEB128DieRefPatch)197ADD_PATCHES_LIST(DebugOffsetPatch)198ADD_PATCHES_LIST(DebugDieTypeRefPatch)199ADD_PATCHES_LIST(DebugType2TypeDieRefPatch)200ADD_PATCHES_LIST(DebugTypeStrPatch)201ADD_PATCHES_LIST(DebugTypeLineStrPatch)202ADD_PATCHES_LIST(DebugTypeDeclFilePatch)203204/// While creating patches, offsets to attributes may be partially205/// unknown(because size of abbreviation number is unknown). In such case we206/// remember patch itself and pointer to patch application offset to add size207/// of abbreviation number later.208template <typename T>209void notePatchWithOffsetUpdate(const T &Patch,210OffsetsPtrVector &PatchesOffsetsList) {211PatchesOffsetsList.emplace_back(¬ePatch(Patch).PatchOffset);212}213214/// Some sections are emitted using AsmPrinter. In that case "Contents"215/// member of SectionDescriptor contains elf file. This method searches216/// for section data inside elf file and remember offset to it.217void setSizesForSectionCreatedByAsmPrinter();218219/// Returns section content.220StringRef getContents() override {221if (SectionOffsetInsideAsmPrinterOutputStart == 0)222return Contents;223224return Contents.slice(SectionOffsetInsideAsmPrinterOutputStart,225SectionOffsetInsideAsmPrinterOutputEnd);226}227228/// Emit unit length into the current section contents.229void emitUnitLength(uint64_t Length) {230maybeEmitDwarf64Mark();231emitIntVal(Length, getFormParams().getDwarfOffsetByteSize());232}233234/// Emit DWARF64 mark into the current section contents.235void maybeEmitDwarf64Mark() {236if (getFormParams().Format != dwarf::DWARF64)237return;238emitIntVal(dwarf::DW_LENGTH_DWARF64, 4);239}240241/// Emit specified offset value into the current section contents.242void emitOffset(uint64_t Val) {243emitIntVal(Val, getFormParams().getDwarfOffsetByteSize());244}245246/// Emit specified integer value into the current section contents.247void emitIntVal(uint64_t Val, unsigned Size);248249void emitString(dwarf::Form StringForm, const char *StringVal);250251void emitBinaryData(llvm::StringRef Data);252253/// Emit specified inplace string value into the current section contents.254void emitInplaceString(StringRef String) {255OS << String;256emitIntVal(0, 1);257}258259/// Emit string placeholder into the current section contents.260void emitStringPlaceholder() {261// emit bad offset which should be updated later.262emitOffset(0xBADDEF);263}264265/// Write specified \p Value of \p AttrForm to the \p PatchOffset.266void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val);267268/// Returns integer value of \p Size located by specified \p PatchOffset.269uint64_t getIntVal(uint64_t PatchOffset, unsigned Size);270271protected:272/// Writes integer value \p Val of \p Size by specified \p PatchOffset.273void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size);274275/// Writes integer value \p Val of ULEB128 format by specified \p PatchOffset.276void applyULEB128(uint64_t PatchOffset, uint64_t Val);277278/// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.279void applySLEB128(uint64_t PatchOffset, uint64_t Val);280281/// Sets output format.282void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianess) {283this->Format = Format;284this->Endianess = Endianess;285}286287LinkingGlobalData &GlobalData;288289/// Section data bits.290OutSectionDataTy Contents;291292/// Some sections are generated using AsmPrinter. The real section data293/// located inside elf file in that case. Following fields points to the294/// real section content inside elf file.295size_t SectionOffsetInsideAsmPrinterOutputStart = 0;296size_t SectionOffsetInsideAsmPrinterOutputEnd = 0;297};298299/// This class keeps contents and offsets to the debug sections. Any objects300/// which is supposed to be emitted into the debug sections should use this301/// class to track debug sections offsets and keep sections data.302class OutputSections {303public:304OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {}305306/// Sets output format for all keeping sections.307void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness) {308this->Format = Format;309this->Endianness = Endianness;310}311312/// Returns descriptor for the specified section of \p SectionKind.313/// The descriptor should already be created. The llvm_unreachable314/// would be raised if it is not.315const SectionDescriptor &316getSectionDescriptor(DebugSectionKind SectionKind) const {317SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);318319if (It == SectionDescriptors.end())320llvm_unreachable(321formatv("Section {0} does not exist", getSectionName(SectionKind))322.str()323.c_str());324325return *It->second;326}327328/// Returns descriptor for the specified section of \p SectionKind.329/// The descriptor should already be created. The llvm_unreachable330/// would be raised if it is not.331SectionDescriptor &getSectionDescriptor(DebugSectionKind SectionKind) {332SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);333334if (It == SectionDescriptors.end())335llvm_unreachable(336formatv("Section {0} does not exist", getSectionName(SectionKind))337.str()338.c_str());339340assert(It->second.get() != nullptr);341342return *It->second;343}344345/// Returns descriptor for the specified section of \p SectionKind.346/// Returns std::nullopt if section descriptor is not created yet.347std::optional<const SectionDescriptor *>348tryGetSectionDescriptor(DebugSectionKind SectionKind) const {349SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind);350351if (It == SectionDescriptors.end())352return std::nullopt;353354return It->second.get();355}356357/// Returns descriptor for the specified section of \p SectionKind.358/// Returns std::nullopt if section descriptor is not created yet.359std::optional<SectionDescriptor *>360tryGetSectionDescriptor(DebugSectionKind SectionKind) {361SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);362363if (It == SectionDescriptors.end())364return std::nullopt;365366return It->second.get();367}368369/// Returns descriptor for the specified section of \p SectionKind.370/// If descriptor does not exist then creates it.371SectionDescriptor &372getOrCreateSectionDescriptor(DebugSectionKind SectionKind) {373SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);374375if (It == SectionDescriptors.end()) {376SectionDescriptor *Section =377new SectionDescriptor(SectionKind, GlobalData, Format, Endianness);378auto Result = SectionDescriptors.try_emplace(SectionKind, Section);379assert(Result.second);380381It = Result.first;382}383384return *It->second;385}386387/// Erases data of all sections.388void eraseSections() {389for (auto &Section : SectionDescriptors)390Section.second->clearAllSectionData();391}392393/// Enumerate all sections and call \p Handler for each.394void forEach(function_ref<void(SectionDescriptor &)> Handler) {395for (auto &Section : SectionDescriptors) {396assert(Section.second.get() != nullptr);397Handler(*(Section.second));398}399}400401/// Enumerate all sections and call \p Handler for each.402void forEach(403function_ref<void(std::shared_ptr<SectionDescriptor> Section)> Handler) {404for (auto &Section : SectionDescriptors)405Handler(Section.second);406}407408/// Enumerate all sections, for each section set current offset409/// (kept by \p SectionSizesAccumulator), update current offset with section410/// length.411void assignSectionsOffsetAndAccumulateSize(412std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) {413for (auto &Section : SectionDescriptors) {414Section.second->StartOffset =415SectionSizesAccumulator[static_cast<uint8_t>(416Section.second->getKind())];417SectionSizesAccumulator[static_cast<uint8_t>(418Section.second->getKind())] += Section.second->getContents().size();419}420}421422/// Enumerate all sections, for each section apply all section patches.423void applyPatches(SectionDescriptor &Section,424StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,425StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,426TypeUnit *TypeUnitPtr);427428/// Endiannes for the sections.429llvm::endianness getEndianness() const { return Endianness; }430431/// Return DWARF version.432uint16_t getVersion() const { return Format.Version; }433434/// Return size of header of debug_info table.435uint16_t getDebugInfoHeaderSize() const {436return Format.Version >= 5 ? 12 : 11;437}438439/// Return size of header of debug_ table.440uint16_t getDebugAddrHeaderSize() const {441assert(Format.Version >= 5);442return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;443}444445/// Return size of header of debug_str_offsets table.446uint16_t getDebugStrOffsetsHeaderSize() const {447assert(Format.Version >= 5);448return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16;449}450451/// Return size of address.452const dwarf::FormParams &getFormParams() const { return Format; }453454protected:455LinkingGlobalData &GlobalData;456457/// Format for sections.458dwarf::FormParams Format = {4, 4, dwarf::DWARF32};459460/// Endiannes for sections.461llvm::endianness Endianness = llvm::endianness::native;462463/// All keeping sections.464using SectionsSetTy =465std::map<DebugSectionKind, std::shared_ptr<SectionDescriptor>>;466SectionsSetTy SectionDescriptors;467};468469} // end of namespace parallel470} // end of namespace dwarf_linker471} // end of namespace llvm472473#endif // LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H474475476