//===- 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 "lld/Core/LLVM.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELF.h" namespace lld { namespace elf { class SymbolBody; 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 DefinedRegular; template static inline typename llvm::object::ELFFile::uintX_t getAddend(const typename llvm::object::ELFFile::Elf_Rel &Rel) { return 0; } template static inline typename llvm::object::ELFFile::uintX_t getAddend(const typename llvm::object::ELFFile::Elf_Rela &Rel) { return Rel.r_addend; } bool isValidCIdentifier(StringRef S); // 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 llvm::object::ELFFile::uintX_t uintX_t; typedef typename llvm::object::ELFFile::Elf_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() { return Header.sh_flags; } uintX_t getFileOff() { return Header.sh_offset; } uintX_t getAlign() { // The ELF spec states that a value of 0 means the section has no alignment // constraits. return std::max(Header.sh_addralign, 1); } uint32_t getType() { return Header.sh_type; } void updateAlign(uintX_t Align) { if (Align > Header.sh_addralign) Header.sh_addralign = Align; } virtual void finalize() {} 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 Base::uintX_t uintX_t; public: GotSection(); void finalize() override; void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody &Sym); void addMipsLocalEntry(); bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); bool empty() const { return MipsLocalEntries == 0 && Entries.empty(); } uintX_t getMipsLocalFullAddr(const SymbolBody &B); uintX_t getMipsLocalPageAddr(uintX_t Addr); uintX_t getGlobalDynAddr(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; uintX_t getTlsIndexVA() { return Base::getVA() + TlsIndexOff; } private: std::vector Entries; uint32_t TlsIndexOff = -1; uint32_t MipsLocalEntries = 0; llvm::DenseMap MipsLocalGotPos; uintX_t getMipsLocalEntryAddr(uintX_t EntryValue); }; template class GotPltSection final : public OutputSectionBase { typedef typename llvm::object::ELFFile::uintX_t 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 Base::uintX_t 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 struct DynamicReloc { typedef typename llvm::object::ELFFile::uintX_t uintX_t; uint32_t Type; // Where the relocation is. enum OffsetKind { Off_Got, // The got entry of Sym. Off_GotPlt, // The got.plt entry of Sym. Off_Bss, // The bss entry of Sym (copy reloc). Off_Sec, // The final position of the given input section and offset. Off_LTlsIndex, // The local tls index. Off_GTlsIndex, // The global tls index of Sym. Off_GTlsOffset // The global tls offset of Sym. } OKind; SymbolBody *Sym = nullptr; InputSectionBase *OffsetSec = nullptr; uintX_t OffsetInSec = 0; bool UseSymVA = false; uintX_t Addend = 0; DynamicReloc(uint32_t Type, OffsetKind OKind, SymbolBody *Sym) : Type(Type), OKind(OKind), Sym(Sym) {} DynamicReloc(uint32_t Type, OffsetKind OKind, bool UseSymVA, SymbolBody *Sym) : Type(Type), OKind(OKind), Sym(Sym), UseSymVA(UseSymVA) {} DynamicReloc(uint32_t Type, InputSectionBase *OffsetSec, uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, uintX_t Addend) : Type(Type), OKind(Off_Sec), Sym(Sym), OffsetSec(OffsetSec), OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} uintX_t getOffset() const; }; template class SymbolTableSection final : public OutputSectionBase { public: typedef typename llvm::object::ELFFile::Elf_Shdr Elf_Shdr; typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; typedef typename llvm::object::ELFFile::Elf_Sym_Range Elf_Sym_Range; typedef typename llvm::object::ELFFile::uintX_t uintX_t; SymbolTableSection(SymbolTable &Table, 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); static uint8_t getSymbolBinding(SymbolBody *Body); SymbolTable &Table; // A vector of symbols and their string table offsets. std::vector> Symbols; }; template class RelocationSection final : public OutputSectionBase { typedef typename llvm::object::ELFFile::Elf_Rel Elf_Rel; typedef typename llvm::object::ELFFile::Elf_Rela Elf_Rela; typedef typename llvm::object::ELFFile::uintX_t uintX_t; public: RelocationSection(StringRef Name); 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: std::vector> Relocs; }; template class OutputSection final : public OutputSectionBase { public: typedef typename llvm::object::ELFFile::Elf_Shdr Elf_Shdr; typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; typedef typename llvm::object::ELFFile::Elf_Rel Elf_Rel; typedef typename llvm::object::ELFFile::Elf_Rela Elf_Rela; typedef typename llvm::object::ELFFile::uintX_t 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; private: void reassignOffsets(); std::vector *> Sections; }; template class MergeOutputSection final : public OutputSectionBase { typedef typename OutputSectionBase::uintX_t uintX_t; bool shouldTailMerge() const; 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; private: llvm::StringTableBuilder Builder; }; // FDE or CIE template struct EHRegion { typedef typename llvm::object::ELFFile::uintX_t uintX_t; EHRegion(EHInputSection *S, unsigned Index); StringRef data() const; EHInputSection *S; unsigned Index; }; template struct Cie : public EHRegion { Cie(EHInputSection *S, unsigned Index); std::vector> Fdes; uint8_t FdeEncoding; }; template class EHOutputSection final : public OutputSectionBase { public: typedef typename llvm::object::ELFFile::uintX_t uintX_t; typedef typename llvm::object::ELFFile::Elf_Shdr Elf_Shdr; typedef typename llvm::object::ELFFile::Elf_Rel Elf_Rel; typedef typename llvm::object::ELFFile::Elf_Rela Elf_Rela; EHOutputSection(StringRef Name, uint32_t Type, uintX_t Flags); void writeTo(uint8_t *Buf) override; template void addSectionAux(EHInputSection *S, llvm::iterator_range Rels); void addSection(InputSectionBase *S) override; private: uint8_t getFdeEncoding(ArrayRef D); std::vector *> Sections; std::vector> Cies; // Maps CIE content + personality to a index in Cies. llvm::DenseMap, unsigned> CieMap; }; template class InterpSection final : public OutputSectionBase { public: InterpSection(); void writeTo(uint8_t *Buf) override; }; template class StringTableSection final : public OutputSectionBase { public: typedef typename llvm::object::ELFFile::uintX_t 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 llvm::object::ELFFile::Elf_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 llvm::object::ELFFile::Elf_Off Elf_Off; typedef typename llvm::object::ELFFile::Elf_Word Elf_Word; typedef typename llvm::object::ELFFile::uintX_t 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 llvm::object::ELFFile::Elf_Dyn Elf_Dyn; typedef typename llvm::object::ELFFile::Elf_Rel Elf_Rel; typedef typename llvm::object::ELFFile::Elf_Rela Elf_Rela; typedef typename llvm::object::ELFFile::Elf_Shdr Elf_Shdr; typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; typedef typename llvm::object::ELFFile::uintX_t 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: DynamicSection(SymbolTable &SymTab); void finalize() override; void writeTo(uint8_t *Buf) override; OutputSectionBase *PreInitArraySec = nullptr; OutputSectionBase *InitArraySec = nullptr; OutputSectionBase *FiniArraySec = nullptr; private: SymbolTable &SymTab; }; 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; }; // --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 llvm::object::ELFFile::uintX_t uintX_t; public: EhFrameHeader(); void writeTo(uint8_t *Buf) override; void addFde(uint8_t Enc, size_t Off, uint8_t *PCRel); void assignEhFrame(EHOutputSection *Sec); void reserveFde(); bool Live = false; private: struct FdeData { uint8_t Enc; size_t Off; uint8_t *PCRel; }; uintX_t getFdePc(uintX_t EhVA, const FdeData &F); EHOutputSection *Sec = nullptr; std::vector FdeList; }; template class BuildIdSection final : public OutputSectionBase { public: BuildIdSection(); void writeTo(uint8_t *Buf) override; void update(ArrayRef Buf); void writeBuildId(); private: uint64_t Hash = 0xcbf29ce484222325; // FNV1 hash basis uint8_t *HashBuf; }; // 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 llvm::object::ELFFile::uintX_t uintX_t; typedef typename llvm::object::ELFFile::Elf_Phdr Elf_Phdr; static BuildIdSection *BuildId; static DynamicSection *Dynamic; static EhFrameHeader *EhFrameHdr; 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 Elf_Phdr *TlsPhdr; static OutputSectionBase *ElfHeader; static OutputSectionBase *ProgramHeaders; }; template BuildIdSection *Out::BuildId; template DynamicSection *Out::Dynamic; template EhFrameHeader *Out::EhFrameHdr; 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 typename Out::Elf_Phdr *Out::TlsPhdr; template OutputSectionBase *Out::ElfHeader; template OutputSectionBase *Out::ProgramHeaders; } // namespace elf } // namespace lld #endif // LLD_ELF_OUTPUT_SECTIONS_H