summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/SectionChunks.h
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/SectionChunks.h')
-rw-r--r--lld/lib/ReaderWriter/ELF/SectionChunks.h616
1 files changed, 0 insertions, 616 deletions
diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h
deleted file mode 100644
index b10ba05237f..00000000000
--- a/lld/lib/ReaderWriter/ELF/SectionChunks.h
+++ /dev/null
@@ -1,616 +0,0 @@
-//===- lib/ReaderWriter/ELF/SectionChunks.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
-#define LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
-
-#include "Chunk.h"
-#include "TargetHandler.h"
-#include "Writer.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/range.h"
-#include "lld/ReaderWriter/AtomLayout.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <memory>
-#include <mutex>
-
-namespace lld {
-namespace elf {
-template <class> class OutputSection;
-using namespace llvm::ELF;
-template <class ELFT> class Segment;
-template <class ELFT> class TargetLayout;
-
-/// \brief An ELF section.
-template <class ELFT> class Section : public Chunk<ELFT> {
-public:
- Section(const ELFLinkingContext &ctx, StringRef sectionName,
- StringRef chunkName,
- typename Chunk<ELFT>::Kind k = Chunk<ELFT>::Kind::ELFSection);
-
- /// \brief Modify the section contents before assigning virtual addresses
- // or assigning file offsets
-
- /// \brief Finalize the section contents before writing
-
- /// \brief Does this section have an output segment.
- virtual bool hasOutputSegment() const { return false; }
-
- /// Return if the section is a loadable section that occupies memory
- virtual bool isLoadableSection() const { return false; }
-
- /// \brief Assign file offsets starting at offset.
- virtual void assignFileOffsets(uint64_t offset) {}
-
- /// \brief Assign virtual addresses starting at addr.
- virtual void assignVirtualAddress(uint64_t addr) {}
-
- uint64_t getFlags() const { return _flags; }
- uint64_t getEntSize() const { return _entSize; }
- uint32_t getType() const { return _type; }
- uint32_t getLink() const { return _link; }
- uint32_t getInfo() const { return _info; }
-
- typename TargetLayout<ELFT>::SegmentType getSegmentType() const {
- return _segmentType;
- }
-
- /// \brief Return the type of content that the section contains
- int getContentType() const override;
-
- /// \brief convert the segment type to a String for diagnostics and printing
- /// purposes
- virtual StringRef segmentKindToStr() const;
-
- /// \brief Records the segmentType, that this section belongs to
- void
- setSegmentType(const typename TargetLayout<ELFT>::SegmentType segmentType) {
- this->_segmentType = segmentType;
- }
-
- virtual const AtomLayout *findAtomLayoutByName(StringRef) const {
- return nullptr;
- }
-
- const OutputSection<ELFT> *getOutputSection() const {
- return _outputSection;
- }
-
- void setOutputSection(OutputSection<ELFT> *os, bool isFirst = false) {
- _outputSection = os;
- _isFirstSectionInOutputSection = isFirst;
- }
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::ELFSection ||
- c->kind() == Chunk<ELFT>::Kind::AtomSection;
- }
-
- uint64_t alignment() const override {
- return _isFirstSectionInOutputSection ? _outputSection->alignment()
- : this->_alignment;
- }
-
- virtual StringRef inputSectionName() const { return _inputSectionName; }
-
- virtual StringRef outputSectionName() const { return _outputSectionName; }
-
- virtual void setOutputSectionName(StringRef outputSectionName) {
- _outputSectionName = outputSectionName;
- }
-
- void setArchiveNameOrPath(StringRef name) { _archivePath = name; }
-
- void setMemberNameOrPath(StringRef name) { _memberPath = name; }
-
- StringRef archivePath() { return _archivePath; }
-
- StringRef memberPath() { return _memberPath; }
-
-protected:
- /// \brief OutputSection this Section is a member of, or nullptr.
- OutputSection<ELFT> *_outputSection = nullptr;
- /// \brief ELF SHF_* flags.
- uint64_t _flags = 0;
- /// \brief The size of each entity.
- uint64_t _entSize = 0;
- /// \brief ELF SHT_* type.
- uint32_t _type = 0;
- /// \brief sh_link field.
- uint32_t _link = 0;
- /// \brief the sh_info field.
- uint32_t _info = 0;
- /// \brief Is this the first section in the output section.
- bool _isFirstSectionInOutputSection = false;
- /// \brief the output ELF segment type of this section.
- typename TargetLayout<ELFT>::SegmentType _segmentType = SHT_NULL;
- /// \brief Input section name.
- StringRef _inputSectionName;
- /// \brief Output section name.
- StringRef _outputSectionName;
- StringRef _archivePath;
- StringRef _memberPath;
-};
-
-/// \brief A section containing atoms.
-template <class ELFT> class AtomSection : public Section<ELFT> {
-public:
- AtomSection(const ELFLinkingContext &ctx, StringRef sectionName,
- int32_t contentType, int32_t permissions, int32_t order);
-
- /// Align the offset to the required modulus defined by the atom alignment
- uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign);
-
- /// Return if the section is a loadable section that occupies memory
- bool isLoadableSection() const override { return _isLoadedInMemory; }
-
- // \brief Append an atom to a Section. The atom gets pushed into a vector
- // contains the atom, the atom file offset, the atom virtual address
- // the atom file offset is aligned appropriately as set by the Reader
- virtual const AtomLayout *appendAtom(const Atom *atom);
-
- /// \brief Set the virtual address of each Atom in the Section. This
- /// routine gets called after the linker fixes up the virtual address
- /// of the section
- void assignVirtualAddress(uint64_t addr) override;
-
- /// \brief Set the file offset of each Atom in the section. This routine
- /// gets called after the linker fixes up the section offset
- void assignFileOffsets(uint64_t offset) override;
-
- /// \brief Find the Atom address given a name, this is needed to properly
- /// apply relocation. The section class calls this to find the atom address
- /// to fix the relocation
- const AtomLayout *findAtomLayoutByName(StringRef name) const override;
-
- /// \brief Return the raw flags, we need this to sort segments
- int64_t atomflags() const { return _contentPermissions; }
-
- /// Atom Iterators
- typedef typename std::vector<AtomLayout *>::iterator atom_iter;
-
- range<atom_iter> atoms() { return _atoms; }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::AtomSection;
- }
-
-protected:
- llvm::BumpPtrAllocator _alloc;
- int32_t _contentType;
- int32_t _contentPermissions;
- bool _isLoadedInMemory = true;
- std::vector<AtomLayout *> _atoms;
- mutable std::mutex _outputMutex;
-
- std::string formatError(const std::string &errorStr, const AtomLayout &atom,
- const Reference &ref) const;
-};
-
-/// \brief A OutputSection represents a set of sections grouped by the same
-/// name. The output file that gets written by the linker has sections grouped
-/// by similar names
-template <class ELFT> class OutputSection {
-public:
- // Iterators
- typedef typename std::vector<Section<ELFT> *>::iterator SectionIter;
-
- OutputSection(StringRef name) : _name(name) {}
-
- // Appends a section into the list of sections that are part of this Output
- // Section
- void appendSection(Section<ELFT> *c);
-
- // Set the OutputSection is associated with a segment
- void setHasSegment() { _hasSegment = true; }
-
- /// Sets the ordinal
- void setOrdinal(uint64_t ordinal) { _ordinal = ordinal; }
-
- /// Sets the Memory size
- void setMemSize(uint64_t memsz) { _memSize = memsz; }
-
- /// Sets the size fo the output Section.
- void setSize(uint64_t fsiz) { _size = fsiz; }
-
- // The offset of the first section contained in the output section is
- // contained here.
- void setFileOffset(uint64_t foffset) { _fileOffset = foffset; }
-
- // Sets the starting address of the section
- void setAddr(uint64_t addr) { _virtualAddr = addr; }
-
- // Is the section loadable?
- bool isLoadableSection() const { return _isLoadableSection; }
-
- // Set section Loadable
- void setLoadableSection(bool isLoadable) {
- _isLoadableSection = isLoadable;
- }
-
- void setLink(uint64_t link) { _link = link; }
- void setInfo(uint64_t info) { _shInfo = info; }
- void setFlag(uint64_t flags) { _flags = flags; }
- void setType(int64_t type) { _type = type; }
- range<SectionIter> sections() { return _sections; }
-
- // The below functions returns the properties of the OutputSection.
- bool hasSegment() const { return _hasSegment; }
- StringRef name() const { return _name; }
- int64_t shinfo() const { return _shInfo; }
- uint64_t alignment() const { return _alignment; }
- int64_t link() const { return _link; }
- int64_t type() const { return _type; }
- uint64_t virtualAddr() const { return _virtualAddr; }
- int64_t ordinal() const { return _ordinal; }
- int64_t kind() const { return _kind; }
- uint64_t fileSize() const { return _size; }
- int64_t entsize() const { return _entSize; }
- uint64_t fileOffset() const { return _fileOffset; }
- uint64_t flags() const { return _flags; }
- uint64_t memSize() const { return _memSize; }
-
-private:
- StringRef _name;
- bool _hasSegment = false;
- uint64_t _ordinal = 0;
- uint64_t _flags = 0;
- uint64_t _size = 0;
- uint64_t _memSize = 0;
- uint64_t _fileOffset = 0;
- uint64_t _virtualAddr = 0;
- int64_t _shInfo = 0;
- int64_t _entSize = 0;
- int64_t _link = 0;
- uint64_t _alignment = 1;
- int64_t _kind = 0;
- int64_t _type = 0;
- bool _isLoadableSection = false;
- std::vector<Section<ELFT> *> _sections;
-};
-
-/// \brief The class represents the ELF String Table
-template <class ELFT> class StringTable : public Section<ELFT> {
-public:
- StringTable(const ELFLinkingContext &, const char *str, int32_t order,
- bool dynamic = false);
-
- uint64_t addString(StringRef symname);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- void setNumEntries(int64_t numEntries) { _stringMap.resize(numEntries); }
-
-private:
- std::vector<StringRef> _strings;
-
- struct StringRefMappingInfo {
- static StringRef getEmptyKey() { return StringRef(); }
- static StringRef getTombstoneKey() { return StringRef(" ", 1); }
- static unsigned getHashValue(StringRef const val) {
- return llvm::HashString(val);
- }
- static bool isEqual(StringRef const lhs, StringRef const rhs) {
- return lhs.equals(rhs);
- }
- };
- typedef typename llvm::DenseMap<StringRef, uint64_t, StringRefMappingInfo>
- StringMapT;
- typedef typename StringMapT::iterator StringMapTIter;
- StringMapT _stringMap;
-};
-
-/// \brief The SymbolTable class represents the symbol table in a ELF file
-template <class ELFT> class SymbolTable : public Section<ELFT> {
- typedef
- typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Addr Elf_Addr;
-
-public:
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
- SymbolTable(const ELFLinkingContext &ctx, const char *str, int32_t order);
-
- /// \brief set the number of entries that would exist in the symbol
- /// table for the current link
- void setNumEntries(int64_t numEntries) const {
- if (_stringSection)
- _stringSection->setNumEntries(numEntries);
- }
-
- /// \brief return number of entries
- std::size_t size() const { return _symbolTable.size(); }
-
- void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0,
- const AtomLayout *layout = nullptr);
-
- /// \brief Get the symbol table index for an Atom. If it's not in the symbol
- /// table, return STN_UNDEF.
- uint32_t getSymbolTableIndex(const Atom *a) const {
- for (size_t i = 0, e = _symbolTable.size(); i < e; ++i)
- if (_symbolTable[i]._atom == a)
- return i;
- return STN_UNDEF;
- }
-
- void finalize() override { finalize(true); }
-
- virtual void sortSymbols() {
- std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
- [](const SymbolEntry &A, const SymbolEntry &B) {
- return A._symbol.getBinding() < B._symbol.getBinding();
- });
- }
-
- virtual void addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
- int64_t addr);
-
- virtual void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr);
-
- virtual void addUndefinedAtom(Elf_Sym &sym, const UndefinedAtom *ua);
-
- virtual void addSharedLibAtom(Elf_Sym &sym, const SharedLibraryAtom *sla);
-
- virtual void finalize(bool sort);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- void setStringSection(StringTable<ELFT> *s) { _stringSection = s; }
-
- StringTable<ELFT> *getStringTable() const { return _stringSection; }
-
-protected:
- struct SymbolEntry {
- SymbolEntry(const Atom *a, const Elf_Sym &sym, const AtomLayout *layout)
- : _atom(a), _atomLayout(layout), _symbol(sym) {}
-
- const Atom *_atom;
- const AtomLayout *_atomLayout;
- Elf_Sym _symbol;
- };
-
- llvm::BumpPtrAllocator _symbolAllocate;
- StringTable<ELFT> *_stringSection;
- std::vector<SymbolEntry> _symbolTable;
-};
-
-template <class ELFT> class HashSection;
-
-template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> {
-public:
- DynamicSymbolTable(const ELFLinkingContext &ctx, TargetLayout<ELFT> &layout,
- const char *str, int32_t order);
-
- // Set the dynamic hash table for symbols to be added into
- void setHashTable(HashSection<ELFT> *hashTable) { _hashTable = hashTable; }
-
- // Add all the dynamic symbos to the hash table
- void addSymbolsToHashTable();
-
- void finalize() override;
-
-protected:
- HashSection<ELFT> *_hashTable = nullptr;
- TargetLayout<ELFT> &_layout;
-};
-
-template <class ELFT> class RelocationTable : public Section<ELFT> {
-public:
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
-
- RelocationTable(const ELFLinkingContext &ctx, StringRef str, int32_t order);
-
- /// \returns the index of the relocation added.
- uint32_t addRelocation(const DefinedAtom &da, const Reference &r);
-
- bool getRelocationIndex(const Reference &r, uint32_t &res);
-
- void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable) {
- _symbolTable = symbolTable;
- }
-
- /// \brief Check if any relocation modifies a read-only section.
- bool canModifyReadonlySection() const;
-
- void finalize() override;
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-protected:
- const DynamicSymbolTable<ELFT> *_symbolTable = nullptr;
-
- virtual void writeRela(ELFWriter *writer, Elf_Rela &r,
- const DefinedAtom &atom, const Reference &ref);
- virtual void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom,
- const Reference &ref);
- uint32_t getSymbolIndex(const Atom *a);
-
-private:
- std::vector<std::pair<const DefinedAtom *, const Reference *>> _relocs;
-};
-
-template <class ELFT> class HashSection;
-
-template <class ELFT> class DynamicTable : public Section<ELFT> {
-public:
- typedef llvm::object::Elf_Dyn_Impl<ELFT> Elf_Dyn;
- typedef std::vector<Elf_Dyn> EntriesT;
-
- DynamicTable(const ELFLinkingContext &ctx, TargetLayout<ELFT> &layout,
- StringRef str, int32_t order);
-
- range<typename EntriesT::iterator> entries() { return _entries; }
-
- /// \returns the index of the entry.
- std::size_t addEntry(int64_t tag, uint64_t val);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- virtual void createDefaultEntries();
- void doPreFlight() override;
-
- /// \brief Dynamic table tag for .got.plt section referencing.
- /// Usually but not always targets use DT_PLTGOT for that.
- virtual int64_t getGotPltTag() { return DT_PLTGOT; }
-
- void finalize() override;
-
- void setSymbolTable(DynamicSymbolTable<ELFT> *dynsym) {
- _dynamicSymbolTable = dynsym;
- }
-
- const DynamicSymbolTable<ELFT> *getSymbolTable() const {
- return _dynamicSymbolTable;
- }
-
- void setHashTable(HashSection<ELFT> *hsh) { _hashTable = hsh; }
-
- virtual void updateDynamicTable();
-
-protected:
- EntriesT _entries;
-
- /// \brief Return a virtual address (maybe adjusted) for the atom layout
- /// Some targets like microMIPS and ARM Thumb use the last bit
- /// of a symbol's value to mark 'compressed' code. This function allows
- /// to adjust a virtal address before using it in the dynamic table tag.
- virtual uint64_t getAtomVirtualAddress(const AtomLayout *al) const {
- return al->_virtualAddr;
- }
-
-private:
- std::size_t _dt_hash;
- std::size_t _dt_strtab;
- std::size_t _dt_symtab;
- std::size_t _dt_rela;
- std::size_t _dt_relasz;
- std::size_t _dt_relaent;
- std::size_t _dt_strsz;
- std::size_t _dt_syment;
- std::size_t _dt_pltrelsz;
- std::size_t _dt_pltgot;
- std::size_t _dt_pltrel;
- std::size_t _dt_jmprel;
- std::size_t _dt_init_array;
- std::size_t _dt_init_arraysz;
- std::size_t _dt_fini_array;
- std::size_t _dt_fini_arraysz;
- std::size_t _dt_textrel;
- std::size_t _dt_init;
- std::size_t _dt_fini;
- TargetLayout<ELFT> &_layout;
- DynamicSymbolTable<ELFT> *_dynamicSymbolTable;
- HashSection<ELFT> *_hashTable;
-
- const AtomLayout *getInitAtomLayout();
-
- const AtomLayout *getFiniAtomLayout();
-};
-
-template <class ELFT> class InterpSection : public Section<ELFT> {
-public:
- InterpSection(const ELFLinkingContext &ctx, StringRef str, int32_t order,
- StringRef interp);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-private:
- StringRef _interp;
-};
-
-/// The hash table in the dynamic linker is organized into
-///
-/// [ nbuckets ]
-/// [ nchains ]
-/// [ buckets[0] ]
-/// .........................
-/// [ buckets[nbuckets-1] ]
-/// [ chains[0] ]
-/// .........................
-/// [ chains[nchains - 1] ]
-///
-/// nbuckets - total number of hash buckets
-/// nchains is equal to the number of dynamic symbols.
-///
-/// The symbol is searched by the dynamic linker using the below approach.
-/// * Calculate the hash of the symbol that needs to be searched
-/// * Take the value from the buckets[hash % nbuckets] as the index of symbol
-/// * Compare the symbol's name, if true return, if false, look through the
-/// * array since there was a collision
-template <class ELFT> class HashSection : public Section<ELFT> {
- struct SymbolTableEntry {
- StringRef _name;
- uint32_t _index;
- };
-
-public:
- HashSection(const ELFLinkingContext &ctx, StringRef name, int32_t order);
-
- /// \brief add the dynamic symbol into the table so that the
- /// hash could be calculated
- void addSymbol(StringRef name, uint32_t index);
-
- /// \brief Set the dynamic symbol table
- void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable);
-
- // The size of the section has to be determined so that fileoffsets
- // may be properly assigned. Let's calculate the buckets and the chains
- // and fill the chains and the buckets hash table used by the dynamic
- // linker and update the filesize and memory size accordingly
- void doPreFlight() override;
-
- void finalize() override;
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-private:
- typedef
- typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Word Elf_Word;
-
- std::vector<SymbolTableEntry> _entries;
- std::vector<Elf_Word> _buckets;
- std::vector<Elf_Word> _chains;
- const DynamicSymbolTable<ELFT> *_symbolTable = nullptr;
-};
-
-template <class ELFT> class EHFrameHeader : public Section<ELFT> {
-public:
- EHFrameHeader(const ELFLinkingContext &ctx, StringRef name,
- TargetLayout<ELFT> &layout, int32_t order);
- void doPreFlight() override;
- void finalize() override;
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-private:
- int32_t _ehFrameOffset = 0;
- TargetLayout<ELFT> &_layout;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
OpenPOWER on IntegriCloud