//===- OutputSections.h -----------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_OUTPUT_SECTIONS_H #define LLD_ELF_OUTPUT_SECTIONS_H #include "Config.h" #include "Relocations.h" #include "lld/Core/LLVM.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELF.h" namespace lld { namespace elf { struct PhdrEntry; class SymbolBody; struct EhSectionPiece; template class EhInputSection; template class InputSection; template class InputSectionBase; template class MergeInputSection; template class OutputSection; template class ObjectFile; template class SharedFile; template class SharedSymbol; template class DefinedRegular; // This represents a section in an output file. // Different sub classes represent different types of sections. Some contain // input sections, others are created by the linker. // The writer creates multiple OutputSections and assign them unique, // non-overlapping file offsets and VAs. class OutputSectionBase { public: enum Kind { Base, EHFrame, Merge, Regular, }; OutputSectionBase(StringRef Name, uint32_t Type, uint64_t Flags); void setLMAOffset(uint64_t LMAOff) { LMAOffset = LMAOff; } uint64_t getLMA() const { return Addr + LMAOffset; } template void writeHeaderTo(typename ELFT::Shdr *SHdr); StringRef getName() const { return Name; } virtual void addSection(InputSectionData *C) {} virtual Kind getKind() const { return Base; } static bool classof(const OutputSectionBase *B) { return B->getKind() == Base; } unsigned SectionIndex; uint32_t getPhdrFlags() const; void updateAlignment(uint64_t Alignment) { if (Alignment > Addralign) Addralign = Alignment; } // If true, this section will be page aligned on disk. // Typically the first section of each PT_LOAD segment has this flag. bool PageAlign = false; // Pointer to the first section in PT_LOAD segment, which this section // also resides in. This field is used to correctly compute file offset // of a section. When two sections share the same load segment, difference // between their file offsets should be equal to difference between their // virtual addresses. To compute some section offset we use the following // formula: Off = Off_first + VA - VA_first. OutputSectionBase *FirstInPtLoad = nullptr; virtual void finalize() {} virtual void assignOffsets() {} virtual void writeTo(uint8_t *Buf) {} virtual ~OutputSectionBase() = default; StringRef Name; // The following fields correspond to Elf_Shdr members. uint64_t Size = 0; uint64_t Entsize = 0; uint64_t Addralign = 0; uint64_t Offset = 0; uint64_t Flags = 0; uint64_t LMAOffset = 0; uint64_t Addr = 0; uint32_t ShName = 0; uint32_t Type = 0; uint32_t Info = 0; uint32_t Link = 0; }; template class OutputSection final : public OutputSectionBase { public: typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::uint uintX_t; OutputSection(StringRef Name, uint32_t Type, uintX_t Flags); void addSection(InputSectionData *C) override; void sort(std::function *S)> Order); void sortInitFini(); void sortCtorsDtors(); void writeTo(uint8_t *Buf) override; void finalize() override; void assignOffsets() override; Kind getKind() const override { return Regular; } static bool classof(const OutputSectionBase *B) { return B->getKind() == Regular; } std::vector *> Sections; // Location in the output buffer. uint8_t *Loc = nullptr; }; template class MergeOutputSection final : public OutputSectionBase { typedef typename ELFT::uint uintX_t; public: MergeOutputSection(StringRef Name, uint32_t Type, uintX_t Flags, uintX_t Alignment); void addSection(InputSectionData *S) override; void writeTo(uint8_t *Buf) override; void finalize() override; bool shouldTailMerge() const; Kind getKind() const override { return Merge; } static bool classof(const OutputSectionBase *B) { return B->getKind() == Merge; } private: void finalizeTailMerge(); void finalizeNoTailMerge(); llvm::StringTableBuilder Builder; std::vector *> Sections; }; struct CieRecord { EhSectionPiece *Piece = nullptr; std::vector FdePieces; }; // Output section for .eh_frame. template class EhOutputSection final : public OutputSectionBase { typedef typename ELFT::uint uintX_t; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; public: EhOutputSection(); void writeTo(uint8_t *Buf) override; void finalize() override; bool empty() const { return Sections.empty(); } void addSection(InputSectionData *S) override; Kind getKind() const override { return EHFrame; } static bool classof(const OutputSectionBase *B) { return B->getKind() == EHFrame; } size_t NumFdes = 0; private: template void addSectionAux(EhInputSection *S, llvm::ArrayRef Rels); template CieRecord *addCie(EhSectionPiece &Piece, ArrayRef Rels); template bool isFdeLive(EhSectionPiece &Piece, ArrayRef Rels); uintX_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc); std::vector *> Sections; std::vector Cies; // CIE records are uniquified by their contents and personality functions. llvm::DenseMap, SymbolBody *>, CieRecord> CieMap; }; // All output sections that are hadnled by the linker specially are // globally accessible. Writer initializes them, so don't use them // until Writer is initialized. template struct Out { typedef typename ELFT::uint uintX_t; typedef typename ELFT::Phdr Elf_Phdr; static uint8_t First; static EhOutputSection *EhFrame; static OutputSection *Bss; static OutputSectionBase *Opd; static uint8_t *OpdBuf; static PhdrEntry *TlsPhdr; static OutputSectionBase *DebugInfo; static OutputSectionBase *ElfHeader; static OutputSectionBase *ProgramHeaders; static OutputSectionBase *PreinitArray; static OutputSectionBase *InitArray; static OutputSectionBase *FiniArray; }; struct SectionKey { StringRef Name; uint64_t Flags; uint64_t Alignment; }; // This class knows how to create an output section for a given // input section. Output section type is determined by various // factors, including input section's sh_flags, sh_type and // linker scripts. template class OutputSectionFactory { typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::uint uintX_t; public: OutputSectionFactory(); ~OutputSectionFactory(); std::pair create(InputSectionBase *C, StringRef OutsecName); std::pair create(const SectionKey &Key, InputSectionBase *C); private: llvm::SmallDenseMap Map; }; template uint64_t getHeaderSize() { if (Config->OFormatBinary) return 0; return Out::ElfHeader->Size + Out::ProgramHeaders->Size; } template uint8_t Out::First; template EhOutputSection *Out::EhFrame; template OutputSection *Out::Bss; template OutputSectionBase *Out::Opd; template uint8_t *Out::OpdBuf; template PhdrEntry *Out::TlsPhdr; template OutputSectionBase *Out::DebugInfo; template OutputSectionBase *Out::ElfHeader; template OutputSectionBase *Out::ProgramHeaders; template OutputSectionBase *Out::PreinitArray; template OutputSectionBase *Out::InitArray; template OutputSectionBase *Out::FiniArray; } // namespace elf } // namespace lld #endif