blob: 09cb1bb853aa7f65a90b042bf454b2c5c9045d00 [file] [log] [blame]
Rui Ueyama411c63602015-05-28 19:09:301//===- Symbols.h ----------------------------------------------------------===//
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_COFF_SYMBOLS_H
11#define LLD_COFF_SYMBOLS_H
12
13#include "Chunks.h"
14#include "Config.h"
15#include "lld/Core/LLVM.h"
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/Object/Archive.h"
18#include "llvm/Object/COFF.h"
19#include <memory>
20#include <vector>
21
22namespace lld {
23namespace coff {
24
25using llvm::object::Archive;
26using llvm::object::COFFSymbolRef;
Rui Ueyamac9bfe322015-05-29 15:45:3527using llvm::object::coff_import_header;
Rui Ueyama411c63602015-05-28 19:09:3028
29class ArchiveFile;
30class InputFile;
31class ObjectFile;
32class SymbolBody;
33
34// A real symbol object, SymbolBody, is usually accessed indirectly
35// through a Symbol. There's always one Symbol for each symbol name.
36// The resolver updates SymbolBody pointers as it resolves symbols.
37struct Symbol {
38 explicit Symbol(SymbolBody *P) : Body(P) {}
39 SymbolBody *Body;
40};
41
42// The base class for real symbol classes.
43class SymbolBody {
44public:
45 enum Kind {
46 DefinedFirst,
47 DefinedRegularKind,
48 DefinedAbsoluteKind,
49 DefinedImportDataKind,
50 DefinedImportThunkKind,
51 DefinedLast,
52 UndefinedKind,
53 LazyKind,
54 };
55
56 Kind kind() const { return SymbolKind; }
57 virtual ~SymbolBody() {}
58
59 // Returns true if this is an external symbol.
60 virtual bool isExternal() { return true; }
61
62 // Returns the symbol name.
63 StringRef getName() { return Name; }
64
65 // A SymbolBody has a backreference to a Symbol. Originally they are
66 // doubly-linked. A backreference will never change. But the pointer
67 // in the Symbol may be mutated by the resolver. If you have a
68 // pointer P to a SymbolBody and are not sure whether the resolver
69 // has chosen the object among other objects having the same name,
70 // you can access P->getSymbol()->Body to get the resolver's result.
71 void setBackref(Symbol *P) { Backref = P; }
72 SymbolBody *getReplacement() { return Backref ? Backref->Body : this; }
73
74 // Decides which symbol should "win" in the symbol table, this or
75 // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
76 // they are duplicate (conflicting) symbols.
77 virtual int compare(SymbolBody *Other) = 0;
78
79protected:
80 SymbolBody(Kind K, StringRef N) : SymbolKind(K), Name(N) {}
81
82private:
83 const Kind SymbolKind;
84 StringRef Name;
85 Symbol *Backref = nullptr;
86};
87
88// The base class for any defined symbols, including absolute symbols,
89// etc.
90class Defined : public SymbolBody {
91public:
92 Defined(Kind K, StringRef Name) : SymbolBody(K, Name) {}
93
94 static bool classof(const SymbolBody *S) {
95 Kind K = S->kind();
96 return DefinedFirst <= K && K <= DefinedLast;
97 }
98
99 // Returns the RVA (relative virtual address) of this symbol. The
100 // writer sets and uses RVAs.
101 virtual uint64_t getRVA() = 0;
102
103 // Returns the file offset of this symbol in the final executable.
104 // The writer uses this information to apply relocations.
105 virtual uint64_t getFileOff() = 0;
106
107 // Called by the garbage collector. All Defined subclasses should
108 // know how to call markLive to dependent symbols.
109 virtual void markLive() {}
110
111 int compare(SymbolBody *Other) override;
112};
113
114// Regular defined symbols read from object file symbol tables.
115class DefinedRegular : public Defined {
116public:
117 DefinedRegular(StringRef Name, COFFSymbolRef S, Chunk *C)
118 : Defined(DefinedRegularKind, Name), Sym(S), Data(C) {}
119
120 static bool classof(const SymbolBody *S) {
121 return S->kind() == DefinedRegularKind;
122 }
123
124 uint64_t getRVA() override { return Data->getRVA() + Sym.getValue(); }
125 bool isExternal() override { return Sym.isExternal(); }
126 void markLive() override { Data->markLive(); }
127 uint64_t getFileOff() override { return Data->getFileOff() + Sym.getValue(); }
128 bool isCOMDAT() const { return Data->isCOMDAT(); }
129
130 // Returns true if this is a common symbol.
131 bool isCommon() const { return Sym.isCommon(); }
132 uint32_t getCommonSize() const { return Sym.getValue(); }
133
134private:
135 COFFSymbolRef Sym;
136 Chunk *Data;
137};
138
139// Absolute symbols.
140class DefinedAbsolute : public Defined {
141public:
142 DefinedAbsolute(StringRef Name, uint64_t VA)
143 : Defined(DefinedAbsoluteKind, Name), RVA(VA - Config->ImageBase) {}
144
145 static bool classof(const SymbolBody *S) {
146 return S->kind() == DefinedAbsoluteKind;
147 }
148
149 uint64_t getRVA() override { return RVA; }
150 uint64_t getFileOff() override { llvm_unreachable("internal error"); }
151
152private:
153 uint64_t RVA;
154};
155
Rui Ueyama411c63602015-05-28 19:09:30156// This class represents a symbol defined in an archive file. It is
157// created from an archive file header, and it knows how to load an
158// object file from an archive to replace itself with a defined
159// symbol. If the resolver finds both Undefined and Lazy for
160// the same name, it will ask the Lazy to load a file.
161class Lazy : public SymbolBody {
162public:
163 Lazy(ArchiveFile *F, const Archive::Symbol S)
164 : SymbolBody(LazyKind, S.getName()), File(F), Sym(S) {}
165
166 static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }
167
168 // Returns an object file for this symbol, or a nullptr if the file
169 // was already returned.
170 ErrorOr<std::unique_ptr<InputFile>> getMember();
171
172 int compare(SymbolBody *Other) override;
173
174private:
175 ArchiveFile *File;
176 const Archive::Symbol Sym;
177};
178
179// Undefined symbols.
180class Undefined : public SymbolBody {
181public:
182 explicit Undefined(StringRef Name, SymbolBody **S = nullptr)
183 : SymbolBody(UndefinedKind, Name), Alias(S) {}
184
185 static bool classof(const SymbolBody *S) {
186 return S->kind() == UndefinedKind;
187 }
188
189 // An undefined symbol can have a fallback symbol which gives an
190 // undefined symbol a second chance if it would remain undefined.
191 // If it remains undefined, it'll be replaced with whatever the
192 // Alias pointer points to.
193 SymbolBody *getWeakAlias() { return Alias ? *Alias : nullptr; }
194
195 int compare(SymbolBody *Other) override;
196
197private:
198 SymbolBody **Alias;
199};
200
201// Windows-specific classes.
202
Rui Ueyama7c4fcdd2015-05-29 15:49:09203// This class represents a symbol imported from a DLL. This has two
204// names for internal use and external use. The former is used for
205// name resolution, and the latter is used for the import descriptor
206// table in an output. The former has "__imp_" prefix.
207class DefinedImportData : public Defined {
208public:
209 DefinedImportData(StringRef D, StringRef ImportName, StringRef ExportName,
210 const coff_import_header *H)
211 : Defined(DefinedImportDataKind, ImportName), DLLName(D),
212 ExpName(ExportName), Hdr(H) {}
213
214 static bool classof(const SymbolBody *S) {
215 return S->kind() == DefinedImportDataKind;
216 }
217
218 uint64_t getRVA() override { return Location->getRVA(); }
219 uint64_t getFileOff() override { return Location->getFileOff(); }
220 StringRef getDLLName() { return DLLName; }
221 StringRef getExportName() { return ExpName; }
222 void setLocation(Chunk *AddressTable) { Location = AddressTable; }
223 uint16_t getOrdinal() { return Hdr->OrdinalHint; }
224
225private:
226 StringRef DLLName;
227 StringRef ExpName;
228 const coff_import_header *Hdr;
229 Chunk *Location = nullptr;
230};
231
Rui Ueyama411c63602015-05-28 19:09:30232// This class represents a symbol for a jump table entry which jumps
233// to a function in a DLL. Linker are supposed to create such symbols
234// without "__imp_" prefix for all function symbols exported from
235// DLLs, so that you can call DLL functions as regular functions with
236// a regular name. A function pointer is given as a DefinedImportData.
237class DefinedImportThunk : public Defined {
238public:
239 DefinedImportThunk(StringRef Name, DefinedImportData *S)
240 : Defined(DefinedImportThunkKind, Name), Data(S) {}
241
242 static bool classof(const SymbolBody *S) {
243 return S->kind() == DefinedImportThunkKind;
244 }
245
246 uint64_t getRVA() override { return Data.getRVA(); }
247 uint64_t getFileOff() override { return Data.getFileOff(); }
248 Chunk *getChunk() { return &Data; }
249
250private:
251 ImportThunkChunk Data;
252};
253
254} // namespace coff
255} // namespace lld
256
257#endif