blob: 52f4d1751d2b2f4b8d205417abb7ab4d57d32791 [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 Espindola9d06ab62015-09-22 00:01:39 +000013#include "InputSection.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
Rafael Espindola503fe942015-09-22 16:53:55 +000065 uint16_t getEMachine() const;
66
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000067protected:
68 const ELFKind EKind;
69};
70
Michael J. Spencer84487f12015-07-24 21:03:07 +000071// .o file.
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000072class ObjectFileBase : public ELFFileBase {
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000073public:
Rafael Espindola905ad342015-09-02 20:43:43 +000074 explicit ObjectFileBase(ELFKind EKind, MemoryBufferRef M)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000075 : ELFFileBase(ObjectKind, EKind, M) {}
Rafael Espindola905ad342015-09-02 20:43:43 +000076 static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000077
Rafael Espindola8788e1a2015-09-02 23:01:37 +000078 ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000079
80protected:
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000081 // List of all symbols referenced or defined by this file.
82 std::vector<SymbolBody *> SymbolBodies;
83
84 llvm::BumpPtrAllocator Alloc;
85};
86
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000087template <class ELFT> static ELFKind getStaticELFKind() {
88 if (!ELFT::Is64Bits) {
89 if (ELFT::TargetEndianness == llvm::support::little)
90 return ELF32LEKind;
91 return ELF32BEKind;
92 }
93 if (ELFT::TargetEndianness == llvm::support::little)
94 return ELF64LEKind;
95 return ELF64BEKind;
96}
97
98template <class ELFT> class ELFData {
99public:
Rafael Espindola18173d42015-09-08 15:50:05 +0000100 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
101 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
102
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000103 llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
104
105 uint16_t getEMachine() const { return getObj()->getHeader()->e_machine; }
106
Davide Italiano6d328d32015-09-16 20:45:57 +0000107 StringRef getStringTable() const { return StringTable; }
108
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000109protected:
110 std::unique_ptr<llvm::object::ELFFile<ELFT>> ELFObj;
Rafael Espindola18173d42015-09-08 15:50:05 +0000111 const Elf_Shdr *Symtab = nullptr;
112 StringRef StringTable;
113 Elf_Sym_Range getNonLocalSymbols();
Davide Italiano6d328d32015-09-16 20:45:57 +0000114 Elf_Sym_Range getSymbolsHelper(bool);
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000115
116 void openELF(MemoryBufferRef MB);
117};
118
119template <class ELFT>
120class ObjectFile : public ObjectFileBase, public ELFData<ELFT> {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000121 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
122 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
123 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
Rafael Espindola20348222015-08-24 21:43:25 +0000124 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000125
126public:
Rafael Espindola503fe942015-09-22 16:53:55 +0000127 using ELFData<ELFT>::getEMachine;
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000128
Rafael Espindola905ad342015-09-02 20:43:43 +0000129 static bool classof(const InputFile *F) {
130 return F->kind() == ObjectKind &&
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000131 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
Rafael Espindola905ad342015-09-02 20:43:43 +0000132 }
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000133
Rafael Espindola905ad342015-09-02 20:43:43 +0000134 explicit ObjectFile(MemoryBufferRef M)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000135 : ObjectFileBase(getStaticELFKind<ELFT>(), M) {}
Michael J. Spencer84487f12015-07-24 21:03:07 +0000136 void parse() override;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000137
Rafael Espindola71675852015-09-22 00:16:19 +0000138 ArrayRef<InputSection<ELFT> *> getSections() const { return Sections; }
Rafael Espindolae7a00e32015-08-05 13:55:34 +0000139
Rafael Espindola5c2310c2015-09-18 14:40:19 +0000140 SymbolBody *getSymbolBody(uint32_t SymbolIndex) const {
Rafael Espindola18173d42015-09-08 15:50:05 +0000141 uint32_t FirstNonLocal = this->Symtab->sh_info;
Michael J. Spencer67bc8d62015-08-27 23:15:56 +0000142 if (SymbolIndex < FirstNonLocal)
143 return nullptr;
144 return SymbolBodies[SymbolIndex - FirstNonLocal]->getReplacement();
145 }
146
Davide Italiano6d328d32015-09-16 20:45:57 +0000147 Elf_Sym_Range getLocalSymbols();
148
Davide Italianof7892a12015-09-18 18:28:08 +0000149 const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
150 ArrayRef<Elf_Word> getSymbolTableShndx() const { return SymtabSHNDX; };
Davide Italianob5b47b42015-09-18 01:08:17 +0000151
Michael J. Spencer84487f12015-07-24 21:03:07 +0000152private:
Rafael Espindola71675852015-09-22 00:16:19 +0000153 void initializeSections();
Michael J. Spencer84487f12015-07-24 21:03:07 +0000154 void initializeSymbols();
155
156 SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym);
157
Rafael Espindola71675852015-09-22 00:16:19 +0000158 // List of all sections defined by this file.
159 std::vector<InputSection<ELFT> *> Sections;
Rafael Espindolad8340da2015-08-10 15:12:17 +0000160
Rafael Espindola20348222015-08-24 21:43:25 +0000161 ArrayRef<Elf_Word> SymtabSHNDX;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000162};
163
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000164class ArchiveFile : public InputFile {
165public:
166 explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
167 static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
168 void parse() override;
169
170 // Returns a memory buffer for a given symbol. An empty memory buffer
171 // is returned if we have already returned the same memory buffer.
172 // (So that we don't instantiate same members more than once.)
173 MemoryBufferRef getMember(const Archive::Symbol *Sym);
174
175 llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
176
177private:
178 std::unique_ptr<Archive> File;
179 std::vector<Lazy> LazySymbols;
180 llvm::DenseSet<uint64_t> Seen;
181};
182
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000183// .so file.
184class SharedFileBase : public ELFFileBase {
185public:
186 explicit SharedFileBase(ELFKind EKind, MemoryBufferRef M)
187 : ELFFileBase(SharedKind, EKind, M) {}
188 static bool classof(const InputFile *F) { return F->kind() == SharedKind; }
189};
190
191template <class ELFT>
192class SharedFile : public SharedFileBase, public ELFData<ELFT> {
Rafael Espindola18173d42015-09-08 15:50:05 +0000193 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
194 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
195 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
196
197 std::vector<SharedSymbol<ELFT>> SymbolBodies;
198
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000199public:
Rafael Espindola503fe942015-09-22 16:53:55 +0000200 using ELFData<ELFT>::getEMachine;
Rafael Espindola18173d42015-09-08 15:50:05 +0000201 llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() {
202 return SymbolBodies;
203 }
204
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000205 static bool classof(const InputFile *F) {
206 return F->kind() == SharedKind &&
207 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
208 }
209
210 explicit SharedFile(MemoryBufferRef M)
211 : SharedFileBase(getStaticELFKind<ELFT>(), M) {}
212
213 void parse() override;
214};
215
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000216template <template <class> class T>
217std::unique_ptr<ELFFileBase> createELFFile(MemoryBufferRef MB) {
218 using namespace llvm;
219
220 std::pair<unsigned char, unsigned char> Type =
221 object::getElfArchType(MB.getBuffer());
222 if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
223 error("Invalid data encoding");
224
225 if (Type.first == ELF::ELFCLASS32) {
226 if (Type.second == ELF::ELFDATA2LSB)
227 return make_unique<T<object::ELF32LE>>(MB);
228 return make_unique<T<object::ELF32BE>>(MB);
229 }
230 if (Type.first == ELF::ELFCLASS64) {
231 if (Type.second == ELF::ELFDATA2LSB)
232 return make_unique<T<object::ELF64LE>>(MB);
233 return make_unique<T<object::ELF64BE>>(MB);
234 }
235 error("Invalid file class");
236}
237
Michael J. Spencer84487f12015-07-24 21:03:07 +0000238} // namespace elf2
239} // namespace lld
240
241#endif