//===- 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/ADT/SmallPtrSet.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELF.h" #include "llvm/Support/MD5.h" #include "llvm/Support/SHA1.h" namespace lld { namespace elf { class SymbolBody; struct SectionPiece; template class SymbolTable; template class SymbolTableSection; template class StringTableSection; template class EhInputSection; template class InputSection; template class InputSectionBase; template class MergeInputSection; template class MipsReginfoInputSection; 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. template class OutputSectionBase { public: typedef typename ELFT::uint uintX_t; typedef typename ELFT::Shdr Elf_Shdr; OutputSectionBase(StringRef Name, uint32_t Type, uintX_t Flags); void setVA(uintX_t VA) { Header.sh_addr = VA; } uintX_t getVA() const { return Header.sh_addr; } void setFileOffset(uintX_t Off) { Header.sh_offset = Off; } void setSHName(unsigned Val) { Header.sh_name = Val; } void writeHeaderTo(Elf_Shdr *SHdr); StringRef getName() { return Name; } virtual void addSection(InputSectionBase *C) {} unsigned SectionIndex; // Returns the size of the section in the output file. uintX_t getSize() const { return Header.sh_size; } void setSize(uintX_t Val) { Header.sh_size = Val; } uintX_t getFlags() const { return Header.sh_flags; } uintX_t getFileOff() const { return Header.sh_offset; } uintX_t getAlignment() const { return Header.sh_addralign; } uint32_t getType() const { return Header.sh_type; } void updateAlignment(uintX_t Alignment) { if (Alignment > Header.sh_addralign) Header.sh_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; virtual void finalize() {} virtual void finalizePieces() {} virtual void assignOffsets() {} virtual void writeTo(uint8_t *Buf) {} virtual ~OutputSectionBase() = default; protected: StringRef Name; Elf_Shdr Header; }; template class GotSection final : public OutputSectionBase { typedef OutputSectionBase Base; typedef typename ELFT::uint uintX_t; public: GotSection(); void finalize() override; void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody &Sym); void addMipsEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr); bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); bool empty() const { return MipsPageEntries == 0 && Entries.empty(); } uintX_t getMipsLocalPageOffset(uintX_t Addr); uintX_t getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const; uintX_t getGlobalDynAddr(const SymbolBody &B) const; uintX_t getGlobalDynOffset(const SymbolBody &B) const; uintX_t getNumEntries() const { return Entries.size(); } // Returns the symbol which corresponds to the first entry of the global part // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic // table properties. // Returns nullptr if the global part is empty. const SymbolBody *getMipsFirstGlobalEntry() const; // Returns the number of entries in the local part of GOT including // the number of reserved entries. This method is MIPS-specific. unsigned getMipsLocalEntriesNum() const; // Returns offset of TLS part of the MIPS GOT table. This part goes // after 'local' and 'global' entries. uintX_t getMipsTlsOffset(); uintX_t getTlsIndexVA() { return Base::getVA() + TlsIndexOff; } uint32_t getTlsIndexOff() { return TlsIndexOff; } // Flag to force GOT to be in output if we have relocations // that relies on its address. bool HasGotOffRel = false; private: std::vector Entries; uint32_t TlsIndexOff = -1; uint32_t MipsPageEntries = 0; // Output sections referenced by MIPS GOT relocations. llvm::SmallPtrSet *, 10> MipsOutSections; llvm::DenseMap MipsLocalGotPos; // MIPS ABI requires to create unique GOT entry for each Symbol/Addend // pairs. The `MipsGotMap` maps (S,A) pair to the GOT index in the `MipsLocal` // or `MipsGlobal` vectors. In general it does not have a sence to take in // account addend for preemptible symbols because the corresponding // GOT entries should have one-to-one mapping with dynamic symbols table. // But we use the same container's types for both kind of GOT entries // to handle them uniformly. typedef std::pair MipsGotEntry; typedef std::vector MipsGotEntries; llvm::DenseMap MipsGotMap; MipsGotEntries MipsLocal; MipsGotEntries MipsGlobal; // Write MIPS-specific parts of the GOT. void writeMipsGot(uint8_t *&Buf); }; template class GotPltSection final : public OutputSectionBase { typedef typename ELFT::uint uintX_t; public: GotPltSection(); void finalize() override; void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody &Sym); bool empty() const; private: std::vector Entries; }; template class PltSection final : public OutputSectionBase { typedef OutputSectionBase Base; typedef typename ELFT::uint uintX_t; public: PltSection(); void finalize() override; void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody &Sym); bool empty() const { return Entries.empty(); } private: std::vector> Entries; }; template class DynamicReloc { typedef typename ELFT::uint uintX_t; public: DynamicReloc(uint32_t Type, const InputSectionBase *InputSec, uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, uintX_t Addend) : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} DynamicReloc(uint32_t Type, const OutputSectionBase *OutputSec, uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, uintX_t Addend) : Type(Type), Sym(Sym), OutputSec(OutputSec), OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} uintX_t getOffset() const; uintX_t getAddend() const; uint32_t getSymIndex() const; const OutputSectionBase *getOutputSec() const { return OutputSec; } uint32_t Type; private: SymbolBody *Sym; const InputSectionBase *InputSec = nullptr; const OutputSectionBase *OutputSec = nullptr; uintX_t OffsetInSec; bool UseSymVA; uintX_t Addend; }; template class SymbolTableSection final : public OutputSectionBase { public: typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::SymRange Elf_Sym_Range; typedef typename ELFT::uint uintX_t; SymbolTableSection(StringTableSection &StrTabSec); void finalize() override; void writeTo(uint8_t *Buf) override; void addSymbol(SymbolBody *Body); StringTableSection &getStrTabSec() const { return StrTabSec; } unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; } ArrayRef> getSymbols() const { return Symbols; } unsigned NumLocals = 0; StringTableSection &StrTabSec; private: void writeLocalSymbols(uint8_t *&Buf); void writeGlobalSymbols(uint8_t *Buf); const OutputSectionBase *getOutputSection(SymbolBody *Sym); // A vector of symbols and their string table offsets. std::vector> Symbols; }; // For more information about .gnu.version and .gnu.version_r see: // https://www.akkadia.org/drepper/symbol-versioning // The .gnu.version_d section which has a section type of SHT_GNU_verdef shall // contain symbol version definitions. The number of entries in this section // shall be contained in the DT_VERDEFNUM entry of the .dynamic section. // The section shall contain an array of Elf_Verdef structures, optionally // followed by an array of Elf_Verdaux structures. template class VersionDefinitionSection final : public OutputSectionBase { typedef typename ELFT::Verdef Elf_Verdef; typedef typename ELFT::Verdaux Elf_Verdaux; public: VersionDefinitionSection(); void finalize() override; void writeTo(uint8_t *Buf) override; private: void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); unsigned FileDefNameOff; }; // The .gnu.version section specifies the required version of each symbol in the // dynamic symbol table. It contains one Elf_Versym for each dynamic symbol // table entry. An Elf_Versym is just a 16-bit integer that refers to a version // identifier defined in the either .gnu.version_r or .gnu.version_d section. // The values 0 and 1 are reserved. All other values are used for versions in // the own object or in any of the dependencies. template class VersionTableSection final : public OutputSectionBase { typedef typename ELFT::Versym Elf_Versym; public: VersionTableSection(); void finalize() override; void writeTo(uint8_t *Buf) override; }; // The .gnu.version_r section defines the version identifiers used by // .gnu.version. It contains a linked list of Elf_Verneed data structures. Each // Elf_Verneed specifies the version requirements for a single DSO, and contains // a reference to a linked list of Elf_Vernaux data structures which define the // mapping from version identifiers to version names. template class VersionNeedSection final : public OutputSectionBase { typedef typename ELFT::Verneed Elf_Verneed; typedef typename ELFT::Vernaux Elf_Vernaux; // A vector of shared files that need Elf_Verneed data structures and the // string table offsets of their sonames. std::vector *, size_t>> Needed; // The next available version identifier. unsigned NextIndex; public: VersionNeedSection(); void addSymbol(SharedSymbol *SS); void finalize() override; void writeTo(uint8_t *Buf) override; size_t getNeedNum() const { return Needed.size(); } }; template class RelocationSection final : public OutputSectionBase { typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::uint uintX_t; public: RelocationSection(StringRef Name, bool Sort); void addReloc(const DynamicReloc &Reloc); unsigned getRelocOffset(); void finalize() override; void writeTo(uint8_t *Buf) override; bool hasRelocs() const { return !Relocs.empty(); } bool Static = false; private: bool Sort; std::vector> Relocs; }; 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(InputSectionBase *C) override; void sortInitFini(); void sortCtorsDtors(); void writeTo(uint8_t *Buf) override; void finalize() override; void assignOffsets() override; std::vector *> Sections; }; 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(InputSectionBase *S) override; void writeTo(uint8_t *Buf) override; unsigned getOffset(StringRef Val); void finalize() override; void finalizePieces() override; bool shouldTailMerge() const; private: llvm::StringTableBuilder Builder; std::vector *> Sections; }; struct CieRecord { SectionPiece *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(InputSectionBase *S) override; size_t NumFdes = 0; private: template void addSectionAux(EhInputSection *S, llvm::ArrayRef Rels); template CieRecord *addCie(SectionPiece &Piece, EhInputSection *Sec, ArrayRef &Rels); template bool isFdeLive(SectionPiece &Piece, EhInputSection *Sec, 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; }; template class InterpSection final : public OutputSectionBase { public: InterpSection(); void writeTo(uint8_t *Buf) override; }; template class StringTableSection final : public OutputSectionBase { public: typedef typename ELFT::uint uintX_t; StringTableSection(StringRef Name, bool Dynamic); unsigned addString(StringRef S, bool HashIt = true); void writeTo(uint8_t *Buf) override; unsigned getSize() const { return Size; } void finalize() override { this->Header.sh_size = getSize(); } bool isDynamic() const { return Dynamic; } private: const bool Dynamic; llvm::DenseMap StringMap; std::vector Strings; unsigned Size = 1; // ELF string tables start with a NUL byte, so 1. }; template class HashTableSection final : public OutputSectionBase { typedef typename ELFT::Word Elf_Word; public: HashTableSection(); void finalize() override; void writeTo(uint8_t *Buf) override; }; // Outputs GNU Hash section. For detailed explanation see: // https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections template class GnuHashTableSection final : public OutputSectionBase { typedef typename ELFT::Off Elf_Off; typedef typename ELFT::Word Elf_Word; typedef typename ELFT::uint uintX_t; public: GnuHashTableSection(); void finalize() override; void writeTo(uint8_t *Buf) override; // Adds symbols to the hash table. // Sorts the input to satisfy GNU hash section requirements. void addSymbols(std::vector> &Symbols); private: static unsigned calcNBuckets(unsigned NumHashed); static unsigned calcMaskWords(unsigned NumHashed); void writeHeader(uint8_t *&Buf); void writeBloomFilter(uint8_t *&Buf); void writeHashTable(uint8_t *Buf); struct SymbolData { SymbolBody *Body; size_t STName; uint32_t Hash; }; std::vector Symbols; unsigned MaskWords; unsigned NBuckets; unsigned Shift2; }; template class DynamicSection final : public OutputSectionBase { typedef OutputSectionBase Base; typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::uint uintX_t; // The .dynamic section contains information for the dynamic linker. // The section consists of fixed size entries, which consist of // type and value fields. Value are one of plain integers, symbol // addresses, or section addresses. This struct represents the entry. struct Entry { int32_t Tag; union { OutputSectionBase *OutSec; uint64_t Val; const SymbolBody *Sym; }; enum KindT { SecAddr, SymAddr, PlainInt } Kind; Entry(int32_t Tag, OutputSectionBase *OutSec) : Tag(Tag), OutSec(OutSec), Kind(SecAddr) {} Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {} Entry(int32_t Tag, const SymbolBody *Sym) : Tag(Tag), Sym(Sym), Kind(SymAddr) {} }; // finalize() fills this vector with the section contents. finalize() // cannot directly create final section contents because when the // function is called, symbol or section addresses are not fixed yet. std::vector Entries; public: explicit DynamicSection(); void finalize() override; void writeTo(uint8_t *Buf) override; OutputSectionBase *PreInitArraySec = nullptr; OutputSectionBase *InitArraySec = nullptr; OutputSectionBase *FiniArraySec = nullptr; }; template class MipsReginfoOutputSection final : public OutputSectionBase { typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; public: MipsReginfoOutputSection(); void writeTo(uint8_t *Buf) override; void addSection(InputSectionBase *S) override; private: uint32_t GprMask = 0; }; template class MipsOptionsOutputSection final : public OutputSectionBase { typedef llvm::object::Elf_Mips_Options Elf_Mips_Options; typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; public: MipsOptionsOutputSection(); void writeTo(uint8_t *Buf) override; void addSection(InputSectionBase *S) override; private: uint32_t GprMask = 0; }; // --eh-frame-hdr option tells linker to construct a header for all the // .eh_frame sections. This header is placed to a section named .eh_frame_hdr // and also to a PT_GNU_EH_FRAME segment. // At runtime the unwinder then can find all the PT_GNU_EH_FRAME segments by // calling dl_iterate_phdr. // This section contains a lookup table for quick binary search of FDEs. // Detailed info about internals can be found in Ian Lance Taylor's blog: // http://www.airs.com/blog/archives/460 (".eh_frame") // http://www.airs.com/blog/archives/462 (".eh_frame_hdr") template class EhFrameHeader final : public OutputSectionBase { typedef typename ELFT::uint uintX_t; public: EhFrameHeader(); void finalize() override; void writeTo(uint8_t *Buf) override; void addFde(uint32_t Pc, uint32_t FdeVA); private: struct FdeData { uint32_t Pc; uint32_t FdeVA; }; std::vector Fdes; }; template class BuildIdSection : public OutputSectionBase { public: void writeTo(uint8_t *Buf) override; virtual void writeBuildId(ArrayRef> Bufs) = 0; protected: BuildIdSection(size_t HashSize); size_t HashSize; uint8_t *HashBuf = nullptr; }; template class BuildIdFnv1 final : public BuildIdSection { public: BuildIdFnv1() : BuildIdSection(8) {} void writeBuildId(ArrayRef> Bufs) override; }; template class BuildIdMd5 final : public BuildIdSection { public: BuildIdMd5() : BuildIdSection(16) {} void writeBuildId(ArrayRef> Bufs) override; }; template class BuildIdSha1 final : public BuildIdSection { public: BuildIdSha1() : BuildIdSection(20) {} void writeBuildId(ArrayRef> Bufs) override; }; template class BuildIdHexstring final : public BuildIdSection { public: BuildIdHexstring(); void writeBuildId(ArrayRef> Bufs) override; }; // 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 BuildIdSection *BuildId; static DynamicSection *Dynamic; static EhFrameHeader *EhFrameHdr; static EhOutputSection *EhFrame; static GnuHashTableSection *GnuHashTab; static GotPltSection *GotPlt; static GotSection *Got; static HashTableSection *HashTab; static InterpSection *Interp; static OutputSection *Bss; static OutputSection *MipsRldMap; static OutputSectionBase *Opd; static uint8_t *OpdBuf; static PltSection *Plt; static RelocationSection *RelaDyn; static RelocationSection *RelaPlt; static StringTableSection *DynStrTab; static StringTableSection *ShStrTab; static StringTableSection *StrTab; static SymbolTableSection *DynSymTab; static SymbolTableSection *SymTab; static VersionDefinitionSection *VerDef; static VersionTableSection *VerSym; static VersionNeedSection *VerNeed; static Elf_Phdr *TlsPhdr; static OutputSectionBase *ElfHeader; static OutputSectionBase *ProgramHeaders; }; template struct SectionKey { typedef typename std::conditional::type uintX_t; StringRef Name; uint32_t Type; uintX_t Flags; uintX_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; typedef typename elf::SectionKey Key; public: std::pair *, bool> create(InputSectionBase *C, StringRef OutsecName); OutputSectionBase *lookup(StringRef Name, uint32_t Type, uintX_t Flags); private: Key createKey(InputSectionBase *C, StringRef OutsecName); llvm::SmallDenseMap *> Map; }; template BuildIdSection *Out::BuildId; template DynamicSection *Out::Dynamic; template EhFrameHeader *Out::EhFrameHdr; template EhOutputSection *Out::EhFrame; template GnuHashTableSection *Out::GnuHashTab; template GotPltSection *Out::GotPlt; template GotSection *Out::Got; template HashTableSection *Out::HashTab; template InterpSection *Out::Interp; template OutputSection *Out::Bss; template OutputSection *Out::MipsRldMap; template OutputSectionBase *Out::Opd; template uint8_t *Out::OpdBuf; template PltSection *Out::Plt; template RelocationSection *Out::RelaDyn; template RelocationSection *Out::RelaPlt; template StringTableSection *Out::DynStrTab; template StringTableSection *Out::ShStrTab; template StringTableSection *Out::StrTab; template SymbolTableSection *Out::DynSymTab; template SymbolTableSection *Out::SymTab; template VersionDefinitionSection *Out::VerDef; template VersionTableSection *Out::VerSym; template VersionNeedSection *Out::VerNeed; template typename ELFT::Phdr *Out::TlsPhdr; template OutputSectionBase *Out::ElfHeader; template OutputSectionBase *Out::ProgramHeaders; } // namespace elf } // namespace lld namespace llvm { template struct DenseMapInfo> { typedef typename lld::elf::SectionKey Key; static Key getEmptyKey(); static Key getTombstoneKey(); static unsigned getHashValue(const Key &Val); static bool isEqual(const Key &LHS, const Key &RHS); }; } #endif