summaryrefslogtreecommitdiff
path: root/ELF/InputFiles.h
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/InputFiles.h')
-rw-r--r--ELF/InputFiles.h211
1 files changed, 211 insertions, 0 deletions
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
new file mode 100644
index 0000000000000..4e529c558cf59
--- /dev/null
+++ b/ELF/InputFiles.h
@@ -0,0 +1,211 @@
+//===- InputFiles.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_INPUT_FILES_H
+#define LLD_ELF_INPUT_FILES_H
+
+#include "Config.h"
+#include "InputSection.h"
+#include "Error.h"
+#include "Symbols.h"
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ELF.h"
+
+namespace lld {
+namespace elf2 {
+
+using llvm::object::Archive;
+
+class InputFile;
+class Lazy;
+class SymbolBody;
+
+// The root class of input files.
+class InputFile {
+public:
+ enum Kind { ObjectKind, SharedKind, ArchiveKind };
+ Kind kind() const { return FileKind; }
+
+ StringRef getName() const { return MB.getBufferIdentifier(); }
+
+protected:
+ InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
+ MemoryBufferRef MB;
+
+private:
+ const Kind FileKind;
+};
+
+template <typename ELFT> class ELFFileBase : public InputFile {
+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_Word Elf_Word;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+
+ ELFFileBase(Kind K, MemoryBufferRef M);
+ static bool classof(const InputFile *F) {
+ Kind K = F->kind();
+ return K == ObjectKind || K == SharedKind;
+ }
+
+ static ELFKind getELFKind();
+ const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; }
+ llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; }
+
+ uint16_t getEMachine() const { return getObj().getHeader()->e_machine; }
+ uint8_t getOSABI() const {
+ return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
+ }
+
+ StringRef getStringTable() const { return StringTable; }
+
+ uint32_t getSectionIndex(const Elf_Sym &Sym) const;
+
+protected:
+ llvm::object::ELFFile<ELFT> ELFObj;
+ const Elf_Shdr *Symtab = nullptr;
+ ArrayRef<Elf_Word> SymtabSHNDX;
+ StringRef StringTable;
+ void initStringTable();
+ Elf_Sym_Range getNonLocalSymbols();
+ Elf_Sym_Range getSymbolsHelper(bool);
+};
+
+// .o file.
+template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
+ typedef ELFFileBase<ELFT> Base;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+
+ typedef llvm::support::detail::packed_endian_specific_integral<
+ uint32_t, ELFT::TargetEndianness, 2> GroupEntryType;
+ StringRef getShtGroupSignature(const Elf_Shdr &Sec);
+ ArrayRef<GroupEntryType> getShtGroupEntries(const Elf_Shdr &Sec);
+
+public:
+ static bool classof(const InputFile *F) {
+ return F->kind() == Base::ObjectKind;
+ }
+
+ ArrayRef<SymbolBody *> getSymbols() { return this->SymbolBodies; }
+
+ explicit ObjectFile(MemoryBufferRef M);
+ void parse(llvm::DenseSet<StringRef> &Comdats);
+
+ ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
+ InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
+
+ SymbolBody *getSymbolBody(uint32_t SymbolIndex) const {
+ uint32_t FirstNonLocal = this->Symtab->sh_info;
+ if (SymbolIndex < FirstNonLocal)
+ return nullptr;
+ return this->SymbolBodies[SymbolIndex - FirstNonLocal];
+ }
+
+ Elf_Sym_Range getLocalSymbols();
+ const Elf_Sym *getLocalSymbol(uintX_t SymIndex);
+
+ const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
+
+ // Get MIPS GP0 value defined by this file. This value represents the gp value
+ // used to create the relocatable object and required to support
+ // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
+ uint32_t getMipsGp0() const;
+
+private:
+ void initializeSections(llvm::DenseSet<StringRef> &Comdats);
+ void initializeSymbols();
+ InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
+
+ SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym);
+
+ // List of all sections defined by this file.
+ std::vector<InputSectionBase<ELFT> *> Sections;
+
+ // List of all symbols referenced or defined by this file.
+ std::vector<SymbolBody *> SymbolBodies;
+
+ // MIPS .reginfo section defined by this file.
+ MipsReginfoInputSection<ELFT> *MipsReginfo = nullptr;
+
+ llvm::BumpPtrAllocator Alloc;
+ llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
+ llvm::SpecificBumpPtrAllocator<EHInputSection<ELFT>> EHAlloc;
+};
+
+class ArchiveFile : public InputFile {
+public:
+ explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
+ static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
+ void parse();
+
+ // Returns a memory buffer for a given symbol. An empty memory buffer
+ // is returned if we have already returned the same memory buffer.
+ // (So that we don't instantiate same members more than once.)
+ MemoryBufferRef getMember(const Archive::Symbol *Sym);
+
+ llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
+ std::vector<MemoryBufferRef> getMembers();
+
+private:
+ std::unique_ptr<Archive> File;
+ std::vector<Lazy> LazySymbols;
+ llvm::DenseSet<uint64_t> Seen;
+};
+
+// .so file.
+template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
+ typedef ELFFileBase<ELFT> Base;
+ 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_Word Elf_Word;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+
+ std::vector<SharedSymbol<ELFT>> SymbolBodies;
+ std::vector<StringRef> Undefs;
+ StringRef SoName;
+
+public:
+ StringRef getSoName() const { return SoName; }
+ llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() {
+ return SymbolBodies;
+ }
+ const Elf_Shdr *getSection(const Elf_Sym &Sym) const;
+ llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
+
+ static bool classof(const InputFile *F) {
+ return F->kind() == Base::SharedKind;
+ }
+
+ explicit SharedFile(MemoryBufferRef M);
+
+ void parseSoName();
+ void parse();
+
+ // Used for --as-needed
+ bool AsNeeded = false;
+ bool IsUsed = false;
+ bool isNeeded() const { return !AsNeeded || IsUsed; }
+};
+
+template <template <class> class T>
+std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB);
+
+} // namespace elf2
+} // namespace lld
+
+#endif