blob: e5dc7c3d73a1f016b9ce08053acadcbaa883d090 [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"
Rafael Espindolaf2f41a92015-08-28 02:40:04 +000014#include "Symbols.h"
15
Michael J. Spencer84487f12015-07-24 21:03:07 +000016#include "lld/Core/LLVM.h"
17#include "llvm/Object/ELF.h"
18
19namespace lld {
20namespace elf2 {
21class SymbolBody;
Michael J. Spencer84487f12015-07-24 21:03:07 +000022
23// The root class of input files.
24class InputFile {
25public:
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000026 enum Kind { ObjectKind, SharedKind };
Michael J. Spencer84487f12015-07-24 21:03:07 +000027 Kind kind() const { return FileKind; }
28 virtual ~InputFile() {}
29
Michael J. Spencer84487f12015-07-24 21:03:07 +000030 // Reads a file (constructors don't do that).
31 virtual void parse() = 0;
32
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000033 StringRef getName() const { return MB.getBufferIdentifier(); }
34
Michael J. Spencer84487f12015-07-24 21:03:07 +000035protected:
36 explicit InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
37 MemoryBufferRef MB;
38
39private:
40 const Kind FileKind;
41};
42
Rafael Espindola905ad342015-09-02 20:43:43 +000043enum ELFKind { ELF32LEKind, ELF32BEKind, ELF64LEKind, ELF64BEKind };
44
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000045class ELFFileBase : public InputFile {
46public:
47 explicit ELFFileBase(Kind K, ELFKind EKind, MemoryBufferRef M)
48 : InputFile(K, M), EKind(EKind) {}
49 static bool classof(const InputFile *F) {
50 Kind K = F->kind();
51 return K == ObjectKind || K == SharedKind;
52 }
53
54 bool isCompatibleWith(const ELFFileBase &Other) const;
55 ELFKind getELFKind() const { return EKind; }
56
57protected:
58 const ELFKind EKind;
59};
60
Michael J. Spencer84487f12015-07-24 21:03:07 +000061// .o file.
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000062class ObjectFileBase : public ELFFileBase {
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000063public:
Rafael Espindola905ad342015-09-02 20:43:43 +000064 explicit ObjectFileBase(ELFKind EKind, MemoryBufferRef M)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000065 : ELFFileBase(ObjectKind, EKind, M) {}
Rafael Espindola905ad342015-09-02 20:43:43 +000066 static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000067
Rafael Espindola8788e1a2015-09-02 23:01:37 +000068 ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000069
70protected:
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000071 // List of all symbols referenced or defined by this file.
72 std::vector<SymbolBody *> SymbolBodies;
73
74 llvm::BumpPtrAllocator Alloc;
75};
76
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000077template <class ELFT> static ELFKind getStaticELFKind() {
78 if (!ELFT::Is64Bits) {
79 if (ELFT::TargetEndianness == llvm::support::little)
80 return ELF32LEKind;
81 return ELF32BEKind;
82 }
83 if (ELFT::TargetEndianness == llvm::support::little)
84 return ELF64LEKind;
85 return ELF64BEKind;
86}
87
88template <class ELFT> class ELFData {
89public:
90 llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
91
92 uint16_t getEMachine() const { return getObj()->getHeader()->e_machine; }
93
94protected:
95 std::unique_ptr<llvm::object::ELFFile<ELFT>> ELFObj;
96
97 void openELF(MemoryBufferRef MB);
98};
99
100template <class ELFT>
101class ObjectFile : public ObjectFileBase, public ELFData<ELFT> {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000102 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
103 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
104 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
Rafael Espindola20348222015-08-24 21:43:25 +0000105 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000106
107public:
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000108
Rafael Espindola905ad342015-09-02 20:43:43 +0000109 static bool classof(const InputFile *F) {
110 return F->kind() == ObjectKind &&
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000111 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
Rafael Espindola905ad342015-09-02 20:43:43 +0000112 }
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +0000113
Rafael Espindola905ad342015-09-02 20:43:43 +0000114 explicit ObjectFile(MemoryBufferRef M)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000115 : ObjectFileBase(getStaticELFKind<ELFT>(), M) {}
Michael J. Spencer84487f12015-07-24 21:03:07 +0000116 void parse() override;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000117
Rafael Espindolae7a00e32015-08-05 13:55:34 +0000118 ArrayRef<SectionChunk<ELFT> *> getChunks() { return Chunks; }
119
Michael J. Spencer67bc8d62015-08-27 23:15:56 +0000120 SymbolBody *getSymbolBody(uint32_t SymbolIndex) {
121 uint32_t FirstNonLocal = Symtab->sh_info;
122 if (SymbolIndex < FirstNonLocal)
123 return nullptr;
124 return SymbolBodies[SymbolIndex - FirstNonLocal]->getReplacement();
125 }
126
Michael J. Spencer84487f12015-07-24 21:03:07 +0000127private:
128 void initializeChunks();
129 void initializeSymbols();
130
131 SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym);
132
Rafael Espindolae7a00e32015-08-05 13:55:34 +0000133 // List of all chunks defined by this file.
134 std::vector<SectionChunk<ELFT> *> Chunks;
Rafael Espindolad8340da2015-08-10 15:12:17 +0000135
136 const Elf_Shdr *Symtab = nullptr;
Rafael Espindola20348222015-08-24 21:43:25 +0000137 ArrayRef<Elf_Word> SymtabSHNDX;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000138};
139
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000140// .so file.
141class SharedFileBase : public ELFFileBase {
142public:
143 explicit SharedFileBase(ELFKind EKind, MemoryBufferRef M)
144 : ELFFileBase(SharedKind, EKind, M) {}
145 static bool classof(const InputFile *F) { return F->kind() == SharedKind; }
146};
147
148template <class ELFT>
149class SharedFile : public SharedFileBase, public ELFData<ELFT> {
150public:
151 static bool classof(const InputFile *F) {
152 return F->kind() == SharedKind &&
153 cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
154 }
155
156 explicit SharedFile(MemoryBufferRef M)
157 : SharedFileBase(getStaticELFKind<ELFT>(), M) {}
158
159 void parse() override;
160};
161
Michael J. Spencer84487f12015-07-24 21:03:07 +0000162} // namespace elf2
163} // namespace lld
164
165#endif