1 //===- InputFiles.h ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLD_ELF_INPUT_FILES_H 11 #define LLD_ELF_INPUT_FILES_H 12 13 #include "Config.h" 14 #include "InputSection.h" 15 #include "Error.h" 16 #include "Symbols.h" 17 18 #include "lld/Core/LLVM.h" 19 #include "llvm/ADT/DenseSet.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/Object/Archive.h" 22 #include "llvm/Object/ELF.h" 23 24 namespace lld { 25 namespace elf2 { 26 27 using llvm::object::Archive; 28 29 class InputFile; 30 class Lazy; 31 class SymbolBody; 32 33 // The root class of input files. 34 class InputFile { 35 public: 36 enum Kind { ObjectKind, SharedKind, ArchiveKind }; 37 Kind kind() const { return FileKind; } 38 39 StringRef getName() const { return MB.getBufferIdentifier(); } 40 41 protected: 42 InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} 43 MemoryBufferRef MB; 44 45 private: 46 const Kind FileKind; 47 }; 48 49 template <typename ELFT> class ELFFileBase : public InputFile { 50 public: 51 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; 52 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; 53 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word; 54 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; 55 56 ELFFileBase(Kind K, MemoryBufferRef M); 57 static bool classof(const InputFile *F) { 58 Kind K = F->kind(); 59 return K == ObjectKind || K == SharedKind; 60 } 61 62 static ELFKind getELFKind(); 63 const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; } 64 llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; } 65 66 uint16_t getEMachine() const { return getObj().getHeader()->e_machine; } 67 uint8_t getOSABI() const { 68 return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI]; 69 } 70 71 StringRef getStringTable() const { return StringTable; } 72 73 uint32_t getSectionIndex(const Elf_Sym &Sym) const; 74 75 protected: 76 llvm::object::ELFFile<ELFT> ELFObj; 77 const Elf_Shdr *Symtab = nullptr; 78 ArrayRef<Elf_Word> SymtabSHNDX; 79 StringRef StringTable; 80 void initStringTable(); 81 Elf_Sym_Range getNonLocalSymbols(); 82 Elf_Sym_Range getSymbolsHelper(bool); 83 }; 84 85 // .o file. 86 template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> { 87 typedef ELFFileBase<ELFT> Base; 88 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; 89 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; 90 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; 91 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word; 92 typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; 93 94 typedef llvm::support::detail::packed_endian_specific_integral< 95 uint32_t, ELFT::TargetEndianness, 2> GroupEntryType; 96 StringRef getShtGroupSignature(const Elf_Shdr &Sec); 97 ArrayRef<GroupEntryType> getShtGroupEntries(const Elf_Shdr &Sec); 98 99 public: 100 static bool classof(const InputFile *F) { 101 return F->kind() == Base::ObjectKind; 102 } 103 104 ArrayRef<SymbolBody *> getSymbols() { return this->SymbolBodies; } 105 106 explicit ObjectFile(MemoryBufferRef M); 107 void parse(llvm::DenseSet<StringRef> &Comdats); 108 109 ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; } 110 InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const; 111 112 SymbolBody *getSymbolBody(uint32_t SymbolIndex) const { 113 uint32_t FirstNonLocal = this->Symtab->sh_info; 114 if (SymbolIndex < FirstNonLocal) 115 return nullptr; 116 return this->SymbolBodies[SymbolIndex - FirstNonLocal]; 117 } 118 119 Elf_Sym_Range getLocalSymbols(); 120 const Elf_Sym *getLocalSymbol(uintX_t SymIndex); 121 122 const Elf_Shdr *getSymbolTable() const { return this->Symtab; }; 123 124 private: 125 void initializeSections(llvm::DenseSet<StringRef> &Comdats); 126 void initializeSymbols(); 127 128 SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym); 129 130 // List of all sections defined by this file. 131 std::vector<InputSectionBase<ELFT> *> Sections; 132 133 // List of all symbols referenced or defined by this file. 134 std::vector<SymbolBody *> SymbolBodies; 135 136 llvm::BumpPtrAllocator Alloc; 137 }; 138 139 class ArchiveFile : public InputFile { 140 public: 141 explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} 142 static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } 143 void parse(); 144 145 // Returns a memory buffer for a given symbol. An empty memory buffer 146 // is returned if we have already returned the same memory buffer. 147 // (So that we don't instantiate same members more than once.) 148 MemoryBufferRef getMember(const Archive::Symbol *Sym); 149 150 llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; } 151 std::vector<MemoryBufferRef> getMembers(); 152 153 private: 154 std::unique_ptr<Archive> File; 155 std::vector<Lazy> LazySymbols; 156 llvm::DenseSet<uint64_t> Seen; 157 }; 158 159 // .so file. 160 template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { 161 typedef ELFFileBase<ELFT> Base; 162 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; 163 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; 164 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word; 165 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; 166 167 std::vector<SharedSymbol<ELFT>> SymbolBodies; 168 std::vector<StringRef> Undefs; 169 StringRef SoName; 170 171 public: 172 StringRef getSoName() const { return SoName; } 173 llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() { 174 return SymbolBodies; 175 } 176 const Elf_Shdr *getSection(const Elf_Sym &Sym) const; 177 llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; } 178 179 static bool classof(const InputFile *F) { 180 return F->kind() == Base::SharedKind; 181 } 182 183 explicit SharedFile(MemoryBufferRef M); 184 185 void parseSoName(); 186 void parse(); 187 188 // Used for --as-needed 189 bool AsNeeded = false; 190 bool IsUsed = false; 191 bool isNeeded() const { return !AsNeeded || IsUsed; } 192 }; 193 194 template <template <class> class T> 195 std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB); 196 197 } // namespace elf2 198 } // namespace lld 199 200 #endif 201