blob: f689b42388810f8f2c1556fa889d6d3bae8dadd0 [file] [log] [blame]
Rafael Espindolabeee25e2015-08-14 14:12:54 +00001//===- InputFiles.h ---------------------------------------------*- C++ -*-===//
Michael J. Spencer84487f12015-07-24 21:03:07 +00002//
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
Rafael Espindolae7a00e32015-08-05 13:55:34 +000013#include "Chunks.h"
Michael J. Spencer1b348a62015-09-04 22:28:10 +000014#include "Error.h"
Rafael Espindolaf2f41a92015-08-28 02:40:04 +000015#include "Symbols.h"
16
Michael J. Spencer84487f12015-07-24 21:03:07 +000017#include "lld/Core/LLVM.h"
Michael J. Spencer1b348a62015-09-04 22:28:10 +000018#include "llvm/ADT/DenseSet.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/Object/Archive.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000021#include "llvm/Object/ELF.h"
22
23namespace lld {
24namespace elf2 {
Michael J. Spencer1b348a62015-09-04 22:28:10 +000025
26using llvm::object::Archive;
27
28class Lazy;
Michael J. Spencer84487f12015-07-24 21:03:07 +000029class SymbolBody;
Michael J. Spencer84487f12015-07-24 21:03:07 +000030
31// The root class of input files.
32class InputFile {
33public:
Michael J. Spencer1b348a62015-09-04 22:28:10 +000034 enum Kind { ObjectKind, SharedKind, ArchiveKind };
Michael J. Spencer84487f12015-07-24 21:03:07 +000035 Kind kind() const { return FileKind; }
36 virtual ~InputFile() {}
37
Michael J. Spencer84487f12015-07-24 21:03:07 +000038 // Reads a file (constructors don't do that).
39 virtual void parse() = 0;
40
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000041 StringRef getName() const { return MB.getBufferIdentifier(); }
42
Michael J. Spencer84487f12015-07-24 21:03:07 +000043protected:
44 explicit InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
45 MemoryBufferRef MB;
46
47private:
48 const Kind FileKind;
49};
50
Rafael Espindola905ad342015-09-02 20:43:43 +000051enum ELFKind { ELF32LEKind, ELF32BEKind, ELF64LEKind, ELF64BEKind };
52
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000053class ELFFileBase : public InputFile {
54public:
55 explicit ELFFileBase(Kind K, ELFKind EKind, MemoryBufferRef M)
56 : InputFile(K, M), EKind(EKind) {}
57 static bool classof(const InputFile *F) {
58 Kind K = F->kind();
59 return K == ObjectKind || K == SharedKind;
60 }
61
62 bool isCompatibleWith(const ELFFileBase &Other) const;
63 ELFKind getELFKind() const { return EKind; }
64
65protected:
66 const ELFKind EKind;
67};
68
Michael J. Spencer84487f12015-07-24 21:03:07 +000069// .o file.
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000070class ObjectFileBase : public ELFFileBase {
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000071public:
Rafael Espindola905ad342015-09-02 20:43:43 +000072 explicit ObjectFileBase(ELFKind EKind, MemoryBufferRef M)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000073 : ELFFileBase(ObjectKind, EKind, M) {}
Rafael Espindola905ad342015-09-02 20:43:43 +000074 static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000075
Rafael Espindola8788e1a2015-09-02 23:01:37 +000076 ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000077
78protected:
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000079 // List of all symbols referenced or defined by this file.
80 std::vector<SymbolBody *> SymbolBodies;
81
82 llvm::BumpPtrAllocator Alloc;
83};
84
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000085template <class ELFT> static ELFKind getStaticELFKind() {
86 if (!ELFT::Is64Bits) {
87 if (ELFT::TargetEndianness == llvm::support::little)
88 return ELF32LEKind;
89 return ELF32BEKind;
90 }
91 if (ELFT::TargetEndianness == llvm::support::little)
92 return ELF64LEKind;
93 return ELF64BEKind;
94}
95
96template <class ELFT> class ELFData {
97public:
Rafael Espindola18173d42015-09-08 15:50:05 +000098 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
99 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
100
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000101 llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
102
103 uint16_t getEMachine() const { return getObj()->getHeader()->e_machine; }
104
Davide Italiano6d328d32015-09-16 20:45:57 +0000105 StringRef getStringTable() const { return StringTable; }
106
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000107protected:
108 std::unique_ptr<llvm::object::ELFFile<ELFT>> ELFObj;
Rafael Espindola18173d42015-09-08 15:50:05 +0000109 const Elf_Shdr *Symtab = nullptr;
110 StringRef StringTable;
111 Elf_Sym_Range getNonLocalSymbols();
Davide Italiano6d328d32015-09-16 20:45:57 +0000112 Elf_Sym_Range getSymbolsHelper(bool);
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000113
114 void openELF(MemoryBufferRef MB);
115};
116
117template <class ELFT>
118class ObjectFile : public ObjectFileBase, public ELFData<ELFT> {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000119 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
120 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
121 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
Rafael Espindola20348222015-08-24 21:43:25 +0000122 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000123
124public:
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000125
Rafael Espindola905ad342015-09-02 20:43:43 +0000126 static bool classof(const InputFile *F) {
127 return F->kind() == ObjectKind &&
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000128 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
Rafael Espindola905ad342015-09-02 20:43:43 +0000129 }
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000130
Rafael Espindola905ad342015-09-02 20:43:43 +0000131 explicit ObjectFile(MemoryBufferRef M)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000132 : ObjectFileBase(getStaticELFKind<ELFT>(), M) {}
Michael J. Spencer84487f12015-07-24 21:03:07 +0000133 void parse() override;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000134
Davide Italianof7892a12015-09-18 18:28:08 +0000135 ArrayRef<SectionChunk<ELFT> *> getChunks() const { return Chunks; }
Rafael Espindolae7a00e32015-08-05 13:55:34 +0000136
Rafael Espindola5c2310c2015-09-18 14:40:19 +0000137 SymbolBody *getSymbolBody(uint32_t SymbolIndex) const {
Rafael Espindola18173d42015-09-08 15:50:05 +0000138 uint32_t FirstNonLocal = this->Symtab->sh_info;
Michael J. Spencer67bc8d62015-08-27 23:15:56 +0000139 if (SymbolIndex < FirstNonLocal)
140 return nullptr;
141 return SymbolBodies[SymbolIndex - FirstNonLocal]->getReplacement();
142 }
143
Davide Italiano6d328d32015-09-16 20:45:57 +0000144 Elf_Sym_Range getLocalSymbols();
145
Davide Italianof7892a12015-09-18 18:28:08 +0000146 const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
147 ArrayRef<Elf_Word> getSymbolTableShndx() const { return SymtabSHNDX; };
Davide Italianob5b47b42015-09-18 01:08:17 +0000148
Michael J. Spencer84487f12015-07-24 21:03:07 +0000149private:
150 void initializeChunks();
151 void initializeSymbols();
152
153 SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym);
154
Rafael Espindolae7a00e32015-08-05 13:55:34 +0000155 // List of all chunks defined by this file.
156 std::vector<SectionChunk<ELFT> *> Chunks;
Rafael Espindolad8340da2015-08-10 15:12:17 +0000157
Rafael Espindola20348222015-08-24 21:43:25 +0000158 ArrayRef<Elf_Word> SymtabSHNDX;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000159};
160
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000161class ArchiveFile : public InputFile {
162public:
163 explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
164 static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
165 void parse() override;
166
167 // Returns a memory buffer for a given symbol. An empty memory buffer
168 // is returned if we have already returned the same memory buffer.
169 // (So that we don't instantiate same members more than once.)
170 MemoryBufferRef getMember(const Archive::Symbol *Sym);
171
172 llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
173
174private:
175 std::unique_ptr<Archive> File;
176 std::vector<Lazy> LazySymbols;
177 llvm::DenseSet<uint64_t> Seen;
178};
179
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000180// .so file.
181class SharedFileBase : public ELFFileBase {
182public:
183 explicit SharedFileBase(ELFKind EKind, MemoryBufferRef M)
184 : ELFFileBase(SharedKind, EKind, M) {}
185 static bool classof(const InputFile *F) { return F->kind() == SharedKind; }
186};
187
188template <class ELFT>
189class SharedFile : public SharedFileBase, public ELFData<ELFT> {
Rafael Espindola18173d42015-09-08 15:50:05 +0000190 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
191 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
192 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
193
194 std::vector<SharedSymbol<ELFT>> SymbolBodies;
195
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000196public:
Rafael Espindola18173d42015-09-08 15:50:05 +0000197 llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() {
198 return SymbolBodies;
199 }
200
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000201 static bool classof(const InputFile *F) {
202 return F->kind() == SharedKind &&
203 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
204 }
205
206 explicit SharedFile(MemoryBufferRef M)
207 : SharedFileBase(getStaticELFKind<ELFT>(), M) {}
208
209 void parse() override;
210};
211
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000212template <template <class> class T>
213std::unique_ptr<ELFFileBase> createELFFile(MemoryBufferRef MB) {
214 using namespace llvm;
215
216 std::pair<unsigned char, unsigned char> Type =
217 object::getElfArchType(MB.getBuffer());
218 if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
219 error("Invalid data encoding");
220
221 if (Type.first == ELF::ELFCLASS32) {
222 if (Type.second == ELF::ELFDATA2LSB)
223 return make_unique<T<object::ELF32LE>>(MB);
224 return make_unique<T<object::ELF32BE>>(MB);
225 }
226 if (Type.first == ELF::ELFCLASS64) {
227 if (Type.second == ELF::ELFDATA2LSB)
228 return make_unique<T<object::ELF64LE>>(MB);
229 return make_unique<T<object::ELF64BE>>(MB);
230 }
231 error("Invalid file class");
232}
233
Michael J. Spencer84487f12015-07-24 21:03:07 +0000234} // namespace elf2
235} // namespace lld
236
237#endif