blob: 6d8eada5055b3966b807ef1701851ecaf60fe915 [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:
98 llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
99
100 uint16_t getEMachine() const { return getObj()->getHeader()->e_machine; }
101
102protected:
103 std::unique_ptr<llvm::object::ELFFile<ELFT>> ELFObj;
104
105 void openELF(MemoryBufferRef MB);
106};
107
108template <class ELFT>
109class ObjectFile : public ObjectFileBase, public ELFData<ELFT> {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000110 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
111 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
112 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
Rafael Espindola20348222015-08-24 21:43:25 +0000113 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000114
115public:
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000116
Rafael Espindola905ad342015-09-02 20:43:43 +0000117 static bool classof(const InputFile *F) {
118 return F->kind() == ObjectKind &&
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000119 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
Rafael Espindola905ad342015-09-02 20:43:43 +0000120 }
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000121
Rafael Espindola905ad342015-09-02 20:43:43 +0000122 explicit ObjectFile(MemoryBufferRef M)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000123 : ObjectFileBase(getStaticELFKind<ELFT>(), M) {}
Michael J. Spencer84487f12015-07-24 21:03:07 +0000124 void parse() override;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000125
Rafael Espindolae7a00e32015-08-05 13:55:34 +0000126 ArrayRef<SectionChunk<ELFT> *> getChunks() { return Chunks; }
127
Michael J. Spencer67bc8d62015-08-27 23:15:56 +0000128 SymbolBody *getSymbolBody(uint32_t SymbolIndex) {
129 uint32_t FirstNonLocal = Symtab->sh_info;
130 if (SymbolIndex < FirstNonLocal)
131 return nullptr;
132 return SymbolBodies[SymbolIndex - FirstNonLocal]->getReplacement();
133 }
134
Michael J. Spencer84487f12015-07-24 21:03:07 +0000135private:
136 void initializeChunks();
137 void initializeSymbols();
138
139 SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym);
140
Rafael Espindolae7a00e32015-08-05 13:55:34 +0000141 // List of all chunks defined by this file.
142 std::vector<SectionChunk<ELFT> *> Chunks;
Rafael Espindolad8340da2015-08-10 15:12:17 +0000143
144 const Elf_Shdr *Symtab = nullptr;
Rafael Espindola20348222015-08-24 21:43:25 +0000145 ArrayRef<Elf_Word> SymtabSHNDX;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000146};
147
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000148class ArchiveFile : public InputFile {
149public:
150 explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
151 static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
152 void parse() override;
153
154 // Returns a memory buffer for a given symbol. An empty memory buffer
155 // is returned if we have already returned the same memory buffer.
156 // (So that we don't instantiate same members more than once.)
157 MemoryBufferRef getMember(const Archive::Symbol *Sym);
158
159 llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
160
161private:
162 std::unique_ptr<Archive> File;
163 std::vector<Lazy> LazySymbols;
164 llvm::DenseSet<uint64_t> Seen;
165};
166
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000167// .so file.
168class SharedFileBase : public ELFFileBase {
169public:
170 explicit SharedFileBase(ELFKind EKind, MemoryBufferRef M)
171 : ELFFileBase(SharedKind, EKind, M) {}
172 static bool classof(const InputFile *F) { return F->kind() == SharedKind; }
173};
174
175template <class ELFT>
176class SharedFile : public SharedFileBase, public ELFData<ELFT> {
177public:
178 static bool classof(const InputFile *F) {
179 return F->kind() == SharedKind &&
180 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
181 }
182
183 explicit SharedFile(MemoryBufferRef M)
184 : SharedFileBase(getStaticELFKind<ELFT>(), M) {}
185
186 void parse() override;
187};
188
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000189template <template <class> class T>
190std::unique_ptr<ELFFileBase> createELFFile(MemoryBufferRef MB) {
191 using namespace llvm;
192
193 std::pair<unsigned char, unsigned char> Type =
194 object::getElfArchType(MB.getBuffer());
195 if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
196 error("Invalid data encoding");
197
198 if (Type.first == ELF::ELFCLASS32) {
199 if (Type.second == ELF::ELFDATA2LSB)
200 return make_unique<T<object::ELF32LE>>(MB);
201 return make_unique<T<object::ELF32BE>>(MB);
202 }
203 if (Type.first == ELF::ELFCLASS64) {
204 if (Type.second == ELF::ELFDATA2LSB)
205 return make_unique<T<object::ELF64LE>>(MB);
206 return make_unique<T<object::ELF64BE>>(MB);
207 }
208 error("Invalid file class");
209}
210
Michael J. Spencer84487f12015-07-24 21:03:07 +0000211} // namespace elf2
212} // namespace lld
213
214#endif