summaryrefslogtreecommitdiff
path: root/ELF/OutputSections.h
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/OutputSections.h')
-rw-r--r--ELF/OutputSections.h596
1 files changed, 421 insertions, 175 deletions
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index d7109c580cdc..5fdf8de4cb46 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -10,64 +10,35 @@
#ifndef LLD_ELF_OUTPUT_SECTIONS_H
#define LLD_ELF_OUTPUT_SECTIONS_H
-#include "lld/Core/LLVM.h"
+#include "Config.h"
+#include "Relocations.h"
-#include "llvm/ADT/MapVector.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELF.h"
-
-#include "Config.h"
-
-#include <type_traits>
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/SHA1.h"
namespace lld {
-namespace elf2 {
+namespace elf {
class SymbolBody;
+struct SectionPiece;
template <class ELFT> class SymbolTable;
template <class ELFT> class SymbolTableSection;
template <class ELFT> class StringTableSection;
-template <class ELFT> class EHInputSection;
+template <class ELFT> class EhInputSection;
template <class ELFT> class InputSection;
template <class ELFT> class InputSectionBase;
template <class ELFT> class MergeInputSection;
template <class ELFT> class MipsReginfoInputSection;
template <class ELFT> class OutputSection;
template <class ELFT> class ObjectFile;
+template <class ELFT> class SharedFile;
+template <class ELFT> class SharedSymbol;
template <class ELFT> class DefinedRegular;
-// Flag to force GOT to be in output if we have relocations
-// that relies on its address.
-extern bool HasGotOffRel;
-
-template <class ELFT>
-static inline typename llvm::object::ELFFile<ELFT>::uintX_t
-getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Rel) {
- return 0;
-}
-
-template <class ELFT>
-static inline typename llvm::object::ELFFile<ELFT>::uintX_t
-getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rela &Rel) {
- return Rel.r_addend;
-}
-
-template <class ELFT>
-typename llvm::object::ELFFile<ELFT>::uintX_t getSymVA(const SymbolBody &S);
-
-template <class ELFT, bool IsRela>
-typename llvm::object::ELFFile<ELFT>::uintX_t
-getLocalRelTarget(const ObjectFile<ELFT> &File,
- const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
- typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
-
-bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
-
-template <class ELFT>
-bool shouldKeepInSymtab(
- const ObjectFile<ELFT> &File, StringRef Name,
- const typename llvm::object::ELFFile<ELFT>::Elf_Sym &Sym);
-
// 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.
@@ -75,13 +46,14 @@ bool shouldKeepInSymtab(
// non-overlapping file offsets and VAs.
template <class ELFT> class OutputSectionBase {
public:
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Shdr Elf_Shdr;
- OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ 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; }
@@ -92,21 +64,24 @@ public:
// 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<uintX_t>(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;
+ 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 writeTo(uint8_t *Buf) = 0;
+ virtual void finalizePieces() {}
+ virtual void assignOffsets() {}
+ virtual void writeTo(uint8_t *Buf) {}
virtual ~OutputSectionBase() = default;
protected:
@@ -116,18 +91,21 @@ protected:
template <class ELFT> class GotSection final : public OutputSectionBase<ELFT> {
typedef OutputSectionBase<ELFT> Base;
- typedef typename Base::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
public:
GotSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addEntry(SymbolBody *Sym);
- bool addDynTlsEntry(SymbolBody *Sym);
- bool addCurrentModuleTlsIndex();
- bool empty() const { return Entries.empty(); }
- uintX_t getEntryAddr(const SymbolBody &B) const;
+ 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
@@ -140,24 +118,52 @@ public:
// the number of reserved entries. This method is MIPS-specific.
unsigned getMipsLocalEntriesNum() const;
- uint32_t getLocalTlsIndexVA() { return Base::getVA() + LocalTlsIndexOff; }
+ // 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<const SymbolBody *> Entries;
- uint32_t LocalTlsIndexOff = -1;
+ uint32_t TlsIndexOff = -1;
+ uint32_t MipsPageEntries = 0;
+ // Output sections referenced by MIPS GOT relocations.
+ llvm::SmallPtrSet<const OutputSectionBase<ELFT> *, 10> MipsOutSections;
+ llvm::DenseMap<uintX_t, size_t> 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<const SymbolBody*, uintX_t> MipsGotEntry;
+ typedef std::vector<MipsGotEntry> MipsGotEntries;
+ llvm::DenseMap<MipsGotEntry, size_t> MipsGotMap;
+ MipsGotEntries MipsLocal;
+ MipsGotEntries MipsGlobal;
+
+ // Write MIPS-specific parts of the GOT.
+ void writeMipsGot(uint8_t *&Buf);
};
template <class ELFT>
class GotPltSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
public:
GotPltSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addEntry(SymbolBody *Sym);
+ void addEntry(SymbolBody &Sym);
bool empty() const;
- uintX_t getEntryAddr(const SymbolBody &B) const;
private:
std::vector<const SymbolBody *> Entries;
@@ -165,156 +171,248 @@ private:
template <class ELFT> class PltSection final : public OutputSectionBase<ELFT> {
typedef OutputSectionBase<ELFT> Base;
- typedef typename Base::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
public:
PltSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addEntry(SymbolBody *Sym);
+ void addEntry(SymbolBody &Sym);
bool empty() const { return Entries.empty(); }
- uintX_t getEntryAddr(const SymbolBody &B) const;
private:
std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
};
-template <class ELFT> struct DynamicReloc {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- InputSectionBase<ELFT> *C;
- const Elf_Rel *RI;
+template <class ELFT> class DynamicReloc {
+ typedef typename ELFT::uint uintX_t;
+
+public:
+ DynamicReloc(uint32_t Type, const InputSectionBase<ELFT> *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<ELFT> *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<ELFT> *getOutputSec() const { return OutputSec; }
+
+ uint32_t Type;
+
+private:
+ SymbolBody *Sym;
+ const InputSectionBase<ELFT> *InputSec = nullptr;
+ const OutputSectionBase<ELFT> *OutputSec = nullptr;
+ uintX_t OffsetInSec;
+ bool UseSymVA;
+ uintX_t Addend;
};
template <class ELFT>
class SymbolTableSection final : public OutputSectionBase<ELFT> {
public:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- SymbolTableSection(SymbolTable<ELFT> &Table,
- StringTableSection<ELFT> &StrTabSec);
+ 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<ELFT> &StrTabSec);
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addLocalSymbol(StringRef Name);
void addSymbol(SymbolBody *Body);
StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
- unsigned getNumSymbols() const { return NumVisible + 1; }
+ unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
- ArrayRef<SymbolBody *> getSymbols() const { return Symbols; }
+ ArrayRef<std::pair<SymbolBody *, size_t>> getSymbols() const {
+ return Symbols;
+ }
+
+ unsigned NumLocals = 0;
+ StringTableSection<ELFT> &StrTabSec;
private:
void writeLocalSymbols(uint8_t *&Buf);
void writeGlobalSymbols(uint8_t *Buf);
- static uint8_t getSymbolBinding(SymbolBody *Body);
+ const OutputSectionBase<ELFT> *getOutputSection(SymbolBody *Sym);
- SymbolTable<ELFT> &Table;
- StringTableSection<ELFT> &StrTabSec;
- std::vector<SymbolBody *> Symbols;
- unsigned NumVisible = 0;
- unsigned NumLocals = 0;
+ // A vector of symbols and their string table offsets.
+ std::vector<std::pair<SymbolBody *, size_t>> 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 ELFT>
+class VersionDefinitionSection final : public OutputSectionBase<ELFT> {
+ 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 ELFT>
+class VersionTableSection final : public OutputSectionBase<ELFT> {
+ 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 ELFT>
+class VersionNeedSection final : public OutputSectionBase<ELFT> {
+ 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<std::pair<SharedFile<ELFT> *, size_t>> Needed;
+
+ // The next available version identifier.
+ unsigned NextIndex;
+
+public:
+ VersionNeedSection();
+ void addSymbol(SharedSymbol<ELFT> *SS);
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+ size_t getNeedNum() const { return Needed.size(); }
};
template <class ELFT>
class RelocationSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Rel Elf_Rel;
+ typedef typename ELFT::Rela Elf_Rela;
+ typedef typename ELFT::uint uintX_t;
public:
- RelocationSection(StringRef Name, bool IsRela);
- void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(Reloc); }
+ RelocationSection(StringRef Name, bool Sort);
+ void addReloc(const DynamicReloc<ELFT> &Reloc);
unsigned getRelocOffset();
void finalize() override;
void writeTo(uint8_t *Buf) override;
bool hasRelocs() const { return !Relocs.empty(); }
- bool isRela() const { return IsRela; }
bool Static = false;
private:
- bool applyTlsDynamicReloc(SymbolBody *Body, uint32_t Type, Elf_Rel *P,
- Elf_Rel *N);
-
+ bool Sort;
std::vector<DynamicReloc<ELFT>> Relocs;
- const bool IsRela;
};
template <class ELFT>
class OutputSection final : public OutputSectionBase<ELFT> {
public:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ 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<ELFT> *C) override;
+ void sortInitFini();
+ void sortCtorsDtors();
void writeTo(uint8_t *Buf) override;
-
-private:
+ void finalize() override;
+ void assignOffsets() override;
std::vector<InputSection<ELFT> *> Sections;
};
template <class ELFT>
class MergeOutputSection final : public OutputSectionBase<ELFT> {
- typedef typename OutputSectionBase<ELFT>::uintX_t uintX_t;
-
- bool shouldTailMerge() const;
+ typedef typename ELFT::uint uintX_t;
public:
- MergeOutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ MergeOutputSection(StringRef Name, uint32_t Type, uintX_t Flags,
+ uintX_t Alignment);
void addSection(InputSectionBase<ELFT> *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{llvm::StringTableBuilder::RAW};
+ llvm::StringTableBuilder Builder;
+ std::vector<MergeInputSection<ELFT> *> Sections;
};
-// FDE or CIE
-template <class ELFT> struct EHRegion {
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- EHRegion(EHInputSection<ELFT> *S, unsigned Index);
- StringRef data() const;
- EHInputSection<ELFT> *S;
- unsigned Index;
-};
-
-template <class ELFT> struct Cie : public EHRegion<ELFT> {
- Cie(EHInputSection<ELFT> *S, unsigned Index);
- std::vector<EHRegion<ELFT>> Fdes;
+struct CieRecord {
+ SectionPiece *Piece = nullptr;
+ std::vector<SectionPiece *> FdePieces;
};
+// Output section for .eh_frame.
template <class ELFT>
-class EHOutputSection final : public OutputSectionBase<ELFT> {
+class EhOutputSection final : public OutputSectionBase<ELFT> {
+ 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:
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- EHOutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ EhOutputSection();
void writeTo(uint8_t *Buf) override;
-
- template <bool IsRela>
- void addSectionAux(
- EHInputSection<ELFT> *S,
- llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT, IsRela> *>
- Rels);
+ void finalize() override;
+ bool empty() const { return Sections.empty(); }
void addSection(InputSectionBase<ELFT> *S) override;
+ size_t NumFdes = 0;
+
private:
- uintX_t readEntryLength(ArrayRef<uint8_t> D);
+ template <class RelTy>
+ void addSectionAux(EhInputSection<ELFT> *S, llvm::ArrayRef<RelTy> Rels);
+
+ template <class RelTy>
+ CieRecord *addCie(SectionPiece &Piece, EhInputSection<ELFT> *Sec,
+ ArrayRef<RelTy> &Rels);
+
+ template <class RelTy>
+ bool isFdeLive(SectionPiece &Piece, EhInputSection<ELFT> *Sec,
+ ArrayRef<RelTy> &Rels);
+
+ uintX_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc);
- std::vector<EHInputSection<ELFT> *> Sections;
- std::vector<Cie<ELFT>> Cies;
+ std::vector<EhInputSection<ELFT> *> Sections;
+ std::vector<CieRecord *> Cies;
- // Maps CIE content + personality to a index in Cies.
- llvm::DenseMap<std::pair<StringRef, StringRef>, unsigned> CieMap;
+ // CIE records are uniquified by their contents and personality functions.
+ llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
};
template <class ELFT>
@@ -327,25 +425,24 @@ public:
template <class ELFT>
class StringTableSection final : public OutputSectionBase<ELFT> {
public:
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
StringTableSection(StringRef Name, bool Dynamic);
- void reserve(StringRef S);
- size_t addString(StringRef S);
+ unsigned addString(StringRef S, bool HashIt = true);
void writeTo(uint8_t *Buf) override;
- size_t getSize() const { return Used + Reserved; }
+ unsigned getSize() const { return Size; }
void finalize() override { this->Header.sh_size = getSize(); }
bool isDynamic() const { return Dynamic; }
private:
const bool Dynamic;
+ llvm::DenseMap<StringRef, unsigned> StringMap;
std::vector<StringRef> Strings;
- size_t Used = 1; // ELF string tables start with a NUL byte, so 1.
- size_t Reserved = 0;
+ unsigned Size = 1; // ELF string tables start with a NUL byte, so 1.
};
template <class ELFT>
class HashTableSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
+ typedef typename ELFT::Word Elf_Word;
public:
HashTableSection();
@@ -357,9 +454,9 @@ public:
// https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
template <class ELFT>
class GnuHashTableSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Off Elf_Off;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Off Elf_Off;
+ typedef typename ELFT::Word Elf_Word;
+ typedef typename ELFT::uint uintX_t;
public:
GnuHashTableSection();
@@ -368,7 +465,7 @@ public:
// Adds symbols to the hash table.
// Sorts the input to satisfy GNU hash section requirements.
- void addSymbols(std::vector<SymbolBody *> &Symbols);
+ void addSymbols(std::vector<std::pair<SymbolBody *, size_t>> &Symbols);
private:
static unsigned calcNBuckets(unsigned NumHashed);
@@ -378,12 +475,13 @@ private:
void writeBloomFilter(uint8_t *&Buf);
void writeHashTable(uint8_t *Buf);
- struct HashedSymbolData {
+ struct SymbolData {
SymbolBody *Body;
+ size_t STName;
uint32_t Hash;
};
- std::vector<HashedSymbolData> HashedSymbols;
+ std::vector<SymbolData> Symbols;
unsigned MaskWords;
unsigned NBuckets;
@@ -393,27 +491,45 @@ private:
template <class ELFT>
class DynamicSection final : public OutputSectionBase<ELFT> {
typedef OutputSectionBase<ELFT> Base;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+ 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<ELFT> *OutSec;
+ uint64_t Val;
+ const SymbolBody *Sym;
+ };
+ enum KindT { SecAddr, SymAddr, PlainInt } Kind;
+ Entry(int32_t Tag, OutputSectionBase<ELFT> *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<Entry> Entries;
public:
- DynamicSection(SymbolTable<ELFT> &SymTab);
+ explicit DynamicSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
OutputSectionBase<ELFT> *PreInitArraySec = nullptr;
OutputSectionBase<ELFT> *InitArraySec = nullptr;
OutputSectionBase<ELFT> *FiniArraySec = nullptr;
-
-private:
- SymbolTable<ELFT> &SymTab;
- const SymbolBody *InitSym = nullptr;
- const SymbolBody *FiniSym = nullptr;
- uint32_t DtFlags = 0;
- uint32_t DtFlags1 = 0;
};
template <class ELFT>
@@ -429,17 +545,94 @@ private:
uint32_t GprMask = 0;
};
-inline uint64_t align(uint64_t Value, uint64_t Align) {
- return llvm::RoundUpToAlignment(Value, Align);
-}
+template <class ELFT>
+class MipsOptionsOutputSection final : public OutputSectionBase<ELFT> {
+ typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+public:
+ MipsOptionsOutputSection();
+ void writeTo(uint8_t *Buf) override;
+ void addSection(InputSectionBase<ELFT> *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 ELFT>
+class EhFrameHeader final : public OutputSectionBase<ELFT> {
+ 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<FdeData> Fdes;
+};
+
+template <class ELFT> class BuildIdSection : public OutputSectionBase<ELFT> {
+public:
+ void writeTo(uint8_t *Buf) override;
+ virtual void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) = 0;
+
+protected:
+ BuildIdSection(size_t HashSize);
+ size_t HashSize;
+ uint8_t *HashBuf = nullptr;
+};
+
+template <class ELFT> class BuildIdFnv1 final : public BuildIdSection<ELFT> {
+public:
+ BuildIdFnv1() : BuildIdSection<ELFT>(8) {}
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
+};
+
+template <class ELFT> class BuildIdMd5 final : public BuildIdSection<ELFT> {
+public:
+ BuildIdMd5() : BuildIdSection<ELFT>(16) {}
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
+};
+
+template <class ELFT> class BuildIdSha1 final : public BuildIdSection<ELFT> {
+public:
+ BuildIdSha1() : BuildIdSection<ELFT>(20) {}
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
+};
+
+template <class ELFT>
+class BuildIdHexstring final : public BuildIdSection<ELFT> {
+public:
+ BuildIdHexstring();
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> 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 <class ELFT> struct Out {
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Phdr Elf_Phdr;
+ static BuildIdSection<ELFT> *BuildId;
static DynamicSection<ELFT> *Dynamic;
+ static EhFrameHeader<ELFT> *EhFrameHdr;
+ static EhOutputSection<ELFT> *EhFrame;
static GnuHashTableSection<ELFT> *GnuHashTab;
static GotPltSection<ELFT> *GotPlt;
static GotSection<ELFT> *Got;
@@ -457,10 +650,47 @@ template <class ELFT> struct Out {
static StringTableSection<ELFT> *StrTab;
static SymbolTableSection<ELFT> *DynSymTab;
static SymbolTableSection<ELFT> *SymTab;
+ static VersionDefinitionSection<ELFT> *VerDef;
+ static VersionTableSection<ELFT> *VerSym;
+ static VersionNeedSection<ELFT> *VerNeed;
static Elf_Phdr *TlsPhdr;
+ static OutputSectionBase<ELFT> *ElfHeader;
+ static OutputSectionBase<ELFT> *ProgramHeaders;
};
+template <bool Is64Bits> struct SectionKey {
+ typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::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 ELFT> class OutputSectionFactory {
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename elf::SectionKey<ELFT::Is64Bits> Key;
+
+public:
+ std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C,
+ StringRef OutsecName);
+
+ OutputSectionBase<ELFT> *lookup(StringRef Name, uint32_t Type, uintX_t Flags);
+
+private:
+ Key createKey(InputSectionBase<ELFT> *C, StringRef OutsecName);
+
+ llvm::SmallDenseMap<Key, OutputSectionBase<ELFT> *> Map;
+};
+
+template <class ELFT> BuildIdSection<ELFT> *Out<ELFT>::BuildId;
template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic;
+template <class ELFT> EhFrameHeader<ELFT> *Out<ELFT>::EhFrameHdr;
+template <class ELFT> EhOutputSection<ELFT> *Out<ELFT>::EhFrame;
template <class ELFT> GnuHashTableSection<ELFT> *Out<ELFT>::GnuHashTab;
template <class ELFT> GotPltSection<ELFT> *Out<ELFT>::GotPlt;
template <class ELFT> GotSection<ELFT> *Out<ELFT>::Got;
@@ -478,9 +708,25 @@ template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::ShStrTab;
template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
-template <class ELFT> typename Out<ELFT>::Elf_Phdr *Out<ELFT>::TlsPhdr;
-
-} // namespace elf2
+template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef;
+template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
+template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;
+template <class ELFT> typename ELFT::Phdr *Out<ELFT>::TlsPhdr;
+template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::ElfHeader;
+template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::ProgramHeaders;
+
+} // namespace elf
} // namespace lld
-#endif // LLD_ELF_OUTPUT_SECTIONS_H
+namespace llvm {
+template <bool Is64Bits> struct DenseMapInfo<lld::elf::SectionKey<Is64Bits>> {
+ typedef typename lld::elf::SectionKey<Is64Bits> Key;
+
+ static Key getEmptyKey();
+ static Key getTombstoneKey();
+ static unsigned getHashValue(const Key &Val);
+ static bool isEqual(const Key &LHS, const Key &RHS);
+};
+}
+
+#endif