blob: d8a030705e271c41c97b08bb936e160ea4339149 [file] [log] [blame]
Rafael Espindolabeee25e2015-08-14 14:12:541//===- Symbols.h ------------------------------------------------*- C++ -*-===//
Rui Ueyama411c63602015-05-28 19:09:302//
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"
Rui Ueyama3f851702017-10-02 21:00:4115#include "lld/Common/LLVM.h"
Rui Ueyama2017d522017-11-28 20:39:1716#include "lld/Common/Memory.h"
Rui Ueyama411c63602015-05-28 19:09:3017#include "llvm/ADT/ArrayRef.h"
18#include "llvm/Object/Archive.h"
19#include "llvm/Object/COFF.h"
Rui Ueyamac80c03d2015-07-05 21:54:4220#include <atomic>
Rui Ueyama411c63602015-05-28 19:09:3021#include <memory>
22#include <vector>
23
24namespace lld {
25namespace coff {
26
27using llvm::object::Archive;
28using llvm::object::COFFSymbolRef;
Rui Ueyamac9bfe322015-05-29 15:45:3529using llvm::object::coff_import_header;
Rui Ueyamac15139b2015-06-30 00:10:5430using llvm::object::coff_symbol_generic;
Rui Ueyama411c63602015-05-28 19:09:3031
32class ArchiveFile;
33class InputFile;
Rui Ueyamae1b48e02017-07-26 23:05:2434class ObjFile;
Peter Collingbourne79a5e6b2016-12-09 21:55:2435class SymbolTable;
Rui Ueyama411c63602015-05-28 19:09:3036
37// The base class for real symbol classes.
Rui Ueyamaf52496e2017-11-03 21:21:4738class Symbol {
Rui Ueyama411c63602015-05-28 19:09:3039public:
40 enum Kind {
Chandler Carruth64c17c72015-06-29 21:35:4841 // The order of these is significant. We start with the regular defined
42 // symbols as those are the most prevelant and the zero tag is the cheapest
43 // to set. Among the defined kinds, the lower the kind is preferred over
44 // the higher kind when testing wether one symbol should take precedence
45 // over another.
46 DefinedRegularKind = 0,
Rui Ueyamaefb7e1a2015-06-20 07:21:5747 DefinedCommonKind,
Chandler Carruth64c17c72015-06-29 21:35:4848 DefinedLocalImportKind,
49 DefinedImportThunkKind,
50 DefinedImportDataKind,
51 DefinedAbsoluteKind,
Reid Kleckner502d4ce2017-06-26 15:39:5252 DefinedSyntheticKind,
Chandler Carruth64c17c72015-06-29 21:35:4853
Rui Ueyamae2514762015-06-15 19:06:5354 UndefinedKind,
Rui Ueyama8d3010a2015-06-30 19:35:2155 LazyKind,
Chandler Carruth64c17c72015-06-29 21:35:4856
57 LastDefinedCOFFKind = DefinedCommonKind,
Reid Kleckner502d4ce2017-06-26 15:39:5258 LastDefinedKind = DefinedSyntheticKind,
Rui Ueyama411c63602015-05-28 19:09:3059 };
60
Chandler Carruth64c17c72015-06-29 21:35:4861 Kind kind() const { return static_cast<Kind>(SymbolKind); }
Rui Ueyama411c63602015-05-28 19:09:3062
63 // Returns true if this is an external symbol.
Chandler Carruth64c17c72015-06-29 21:35:4864 bool isExternal() { return IsExternal; }
Rui Ueyama411c63602015-05-28 19:09:3065
66 // Returns the symbol name.
Chandler Carruth64c17c72015-06-29 21:35:4867 StringRef getName();
Rui Ueyama411c63602015-05-28 19:09:3068
Rui Ueyamaa45d45e2016-12-07 23:17:0269 // Returns the file from which this symbol was created.
70 InputFile *getFile();
71
Reid Klecknereacdf042017-07-27 18:25:5972 // Indicates that this symbol will be included in the final image. Only valid
73 // after calling markLive.
74 bool isLive() const;
75
Rui Ueyama411c63602015-05-28 19:09:3076protected:
Peter Collingbourne79a5e6b2016-12-09 21:55:2477 friend SymbolTable;
Rui Ueyamaf52496e2017-11-03 21:21:4778 explicit Symbol(Kind K, StringRef N = "")
Chandler Carruth64c17c72015-06-29 21:35:4879 : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
Peter Collingbournef874bd62017-11-21 01:14:1480 WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false),
81 Name(N) {}
Rui Ueyama411c63602015-05-28 19:09:3082
Chandler Carruth64c17c72015-06-29 21:35:4883 const unsigned SymbolKind : 8;
84 unsigned IsExternal : 1;
85
86 // This bit is used by the \c DefinedRegular subclass.
87 unsigned IsCOMDAT : 1;
88
Peter Collingbourne99111282016-12-11 22:15:2089public:
Peter Collingbournef874bd62017-11-21 01:14:1490 // This bit is used by Writer::createSymbolAndStringTable() to prevent
91 // symbols from being written to the symbol table more than once.
92 unsigned WrittenToSymtab : 1;
93
Rui Ueyama616cd992017-10-31 16:10:2494 // True if this symbol was referenced by a regular (non-bitcode) object.
95 unsigned IsUsedInRegularObj : 1;
96
97 // True if we've seen both a lazy and an undefined symbol with this symbol
98 // name, which means that we have enqueued an archive member load and should
99 // not load any more archive members to resolve the same symbol.
100 unsigned PendingArchiveLoad : 1;
101
Reid Kleckner58839892017-11-13 18:38:53102 /// True if we've already added this symbol to the list of GC roots.
103 unsigned IsGCRoot : 1;
104
Peter Collingbourne99111282016-12-11 22:15:20105protected:
Chandler Carruth64c17c72015-06-29 21:35:48106 StringRef Name;
Rui Ueyama411c63602015-05-28 19:09:30107};
108
109// The base class for any defined symbols, including absolute symbols,
110// etc.
Rui Ueyamaf52496e2017-11-03 21:21:47111class Defined : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30112public:
Rui Ueyamaf52496e2017-11-03 21:21:47113 Defined(Kind K, StringRef N) : Symbol(K, N) {}
Rui Ueyama411c63602015-05-28 19:09:30114
Rui Ueyamaf52496e2017-11-03 21:21:47115 static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; }
Rui Ueyama411c63602015-05-28 19:09:30116
117 // Returns the RVA (relative virtual address) of this symbol. The
118 // writer sets and uses RVAs.
Chandler Carruth64c17c72015-06-29 21:35:48119 uint64_t getRVA();
Rui Ueyama411c63602015-05-28 19:09:30120
Reid Klecknera1001b82017-06-28 17:06:35121 // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
122 // do not have chunks, so this may return null.
123 Chunk *getChunk();
Chandler Carruth64c17c72015-06-29 21:35:48124};
Rui Ueyama411c63602015-05-28 19:09:30125
Bob Haarmancde5e5b2017-02-02 23:58:14126// Symbols defined via a COFF object file or bitcode file. For COFF files, this
127// stores a coff_symbol_generic*, and names of internal symbols are lazily
128// loaded through that. For bitcode files, Sym is nullptr and the name is stored
129// as a StringRef.
Chandler Carruth64c17c72015-06-29 21:35:48130class DefinedCOFF : public Defined {
Rui Ueyamaf52496e2017-11-03 21:21:47131 friend Symbol;
132
Chandler Carruth64c17c72015-06-29 21:35:48133public:
Bob Haarmancde5e5b2017-02-02 23:58:14134 DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S)
135 : Defined(K, N), File(F), Sym(S) {}
Chandler Carruth64c17c72015-06-29 21:35:48136
Rui Ueyamaf52496e2017-11-03 21:21:47137 static bool classof(const Symbol *S) {
Chandler Carruth64c17c72015-06-29 21:35:48138 return S->kind() <= LastDefinedCOFFKind;
139 }
140
Bob Haarmancde5e5b2017-02-02 23:58:14141 InputFile *getFile() { return File; }
Rui Ueyama65813ed2015-07-02 20:33:48142
David Majnemer3a62d3d2015-07-09 17:43:50143 COFFSymbolRef getCOFFSymbol();
144
Bob Haarmancde5e5b2017-02-02 23:58:14145 InputFile *File;
Rui Ueyamaa45d45e2016-12-07 23:17:02146
147protected:
Rui Ueyamac15139b2015-06-30 00:10:54148 const coff_symbol_generic *Sym;
Rui Ueyama411c63602015-05-28 19:09:30149};
150
151// Regular defined symbols read from object file symbol tables.
Chandler Carruth64c17c72015-06-29 21:35:48152class DefinedRegular : public DefinedCOFF {
Rui Ueyama411c63602015-05-28 19:09:30153public:
Bob Haarmancde5e5b2017-02-02 23:58:14154 DefinedRegular(InputFile *F, StringRef N, bool IsCOMDAT,
155 bool IsExternal = false,
156 const coff_symbol_generic *S = nullptr,
157 SectionChunk *C = nullptr)
Bob Haarmancd7197f2017-02-03 23:05:17158 : DefinedCOFF(DefinedRegularKind, F, N, S), Data(C ? &C->Repl : nullptr) {
Bob Haarmancde5e5b2017-02-02 23:58:14159 this->IsExternal = IsExternal;
160 this->IsCOMDAT = IsCOMDAT;
Chandler Carruth64c17c72015-06-29 21:35:48161 }
Rui Ueyama411c63602015-05-28 19:09:30162
Rui Ueyamaf52496e2017-11-03 21:21:47163 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30164 return S->kind() == DefinedRegularKind;
165 }
166
Reid Klecknereacdf042017-07-27 18:25:59167 uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; }
168 bool isCOMDAT() const { return IsCOMDAT; }
169 SectionChunk *getChunk() const { return *Data; }
170 uint32_t getValue() const { return Sym->Value; }
Rui Ueyama411c63602015-05-28 19:09:30171
Rui Ueyama9b921e52015-06-25 22:00:42172 SectionChunk **Data;
Rui Ueyamaefb7e1a2015-06-20 07:21:57173};
174
Chandler Carruth64c17c72015-06-29 21:35:48175class DefinedCommon : public DefinedCOFF {
Rui Ueyamaefb7e1a2015-06-20 07:21:57176public:
Bob Haarmancde5e5b2017-02-02 23:58:14177 DefinedCommon(InputFile *F, StringRef N, uint64_t Size,
178 const coff_symbol_generic *S = nullptr,
179 CommonChunk *C = nullptr)
180 : DefinedCOFF(DefinedCommonKind, F, N, S), Data(C), Size(Size) {
181 this->IsExternal = true;
Chandler Carruth64c17c72015-06-29 21:35:48182 }
Rui Ueyamaefb7e1a2015-06-20 07:21:57183
Rui Ueyamaf52496e2017-11-03 21:21:47184 static bool classof(const Symbol *S) {
Rui Ueyamaefb7e1a2015-06-20 07:21:57185 return S->kind() == DefinedCommonKind;
186 }
187
Chandler Carruth64c17c72015-06-29 21:35:48188 uint64_t getRVA() { return Data->getRVA(); }
Martin Storsjod2752aa2017-08-14 19:07:27189 CommonChunk *getChunk() { return Data; }
Rui Ueyama411c63602015-05-28 19:09:30190
191private:
Peter Collingbourne79a5e6b2016-12-09 21:55:24192 friend SymbolTable;
Bob Haarmancde5e5b2017-02-02 23:58:14193 uint64_t getSize() const { return Size; }
Rui Ueyamafc510f42015-06-25 19:10:58194 CommonChunk *Data;
Bob Haarmancde5e5b2017-02-02 23:58:14195 uint64_t Size;
Rui Ueyama411c63602015-05-28 19:09:30196};
197
198// Absolute symbols.
199class DefinedAbsolute : public Defined {
200public:
Rui Ueyamaccde19d2015-06-26 03:09:23201 DefinedAbsolute(StringRef N, COFFSymbolRef S)
Chandler Carruth64c17c72015-06-29 21:35:48202 : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) {
203 IsExternal = S.isExternal();
204 }
Rui Ueyamaccde19d2015-06-26 03:09:23205
206 DefinedAbsolute(StringRef N, uint64_t V)
Chandler Carruth64c17c72015-06-29 21:35:48207 : Defined(DefinedAbsoluteKind, N), VA(V) {}
Rui Ueyama411c63602015-05-28 19:09:30208
Rui Ueyamaf52496e2017-11-03 21:21:47209 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30210 return S->kind() == DefinedAbsoluteKind;
211 }
212
Chandler Carruth64c17c72015-06-29 21:35:48213 uint64_t getRVA() { return VA - Config->ImageBase; }
Rui Ueyamacd3f99b2015-07-24 23:51:14214 void setVA(uint64_t V) { VA = V; }
Rui Ueyama411c63602015-05-28 19:09:30215
Reid Kleckner84564112017-06-22 23:33:04216 // The sentinel absolute symbol section index. Section index relocations
217 // against absolute symbols resolve to this 16 bit number, and it is the
218 // largest valid section index plus one. This is written by the Writer.
219 static uint16_t OutputSectionIndex;
Reid Klecknera1001b82017-06-28 17:06:35220 uint16_t getSecIdx() { return OutputSectionIndex; }
Reid Kleckner84564112017-06-22 23:33:04221
Rui Ueyama411c63602015-05-28 19:09:30222private:
Rui Ueyamaccde19d2015-06-26 03:09:23223 uint64_t VA;
Rui Ueyama411c63602015-05-28 19:09:30224};
225
Reid Kleckner502d4ce2017-06-26 15:39:52226// This symbol is used for linker-synthesized symbols like __ImageBase and
227// __safe_se_handler_table.
228class DefinedSynthetic : public Defined {
Rui Ueyama3cb895c2015-07-24 22:58:44229public:
Reid Kleckner502d4ce2017-06-26 15:39:52230 explicit DefinedSynthetic(StringRef Name, Chunk *C)
231 : Defined(DefinedSyntheticKind, Name), C(C) {}
Rui Ueyama3cb895c2015-07-24 22:58:44232
Rui Ueyamaf52496e2017-11-03 21:21:47233 static bool classof(const Symbol *S) {
Reid Kleckner502d4ce2017-06-26 15:39:52234 return S->kind() == DefinedSyntheticKind;
Rui Ueyama3cb895c2015-07-24 22:58:44235 }
236
Reid Kleckner502d4ce2017-06-26 15:39:52237 // A null chunk indicates that this is __ImageBase. Otherwise, this is some
238 // other synthesized chunk, like SEHTableChunk.
Reid Klecknera1001b82017-06-28 17:06:35239 uint32_t getRVA() { return C ? C->getRVA() : 0; }
240 Chunk *getChunk() { return C; }
Rui Ueyama3cb895c2015-07-24 22:58:44241
242private:
Reid Kleckner502d4ce2017-06-26 15:39:52243 Chunk *C;
Rui Ueyama3cb895c2015-07-24 22:58:44244};
245
Rui Ueyama411c63602015-05-28 19:09:30246// This class represents a symbol defined in an archive file. It is
247// created from an archive file header, and it knows how to load an
248// object file from an archive to replace itself with a defined
249// symbol. If the resolver finds both Undefined and Lazy for
250// the same name, it will ask the Lazy to load a file.
Rui Ueyamaf52496e2017-11-03 21:21:47251class Lazy : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30252public:
253 Lazy(ArchiveFile *F, const Archive::Symbol S)
Rui Ueyamaf52496e2017-11-03 21:21:47254 : Symbol(LazyKind, S.getName()), File(F), Sym(S) {}
Rui Ueyama411c63602015-05-28 19:09:30255
Rui Ueyamaf52496e2017-11-03 21:21:47256 static bool classof(const Symbol *S) { return S->kind() == LazyKind; }
Rui Ueyama411c63602015-05-28 19:09:30257
Rui Ueyama411c63602015-05-28 19:09:30258 ArchiveFile *File;
Rui Ueyamaa45d45e2016-12-07 23:17:02259
260private:
Peter Collingbourne79a5e6b2016-12-09 21:55:24261 friend SymbolTable;
262
263private:
Rui Ueyama411c63602015-05-28 19:09:30264 const Archive::Symbol Sym;
265};
266
267// Undefined symbols.
Rui Ueyamaf52496e2017-11-03 21:21:47268class Undefined : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30269public:
Rui Ueyamaf52496e2017-11-03 21:21:47270 explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {}
Rui Ueyama411c63602015-05-28 19:09:30271
Rui Ueyamaf52496e2017-11-03 21:21:47272 static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }
Rui Ueyama411c63602015-05-28 19:09:30273
274 // An undefined symbol can have a fallback symbol which gives an
275 // undefined symbol a second chance if it would remain undefined.
276 // If it remains undefined, it'll be replaced with whatever the
277 // Alias pointer points to.
Rui Ueyamaf52496e2017-11-03 21:21:47278 Symbol *WeakAlias = nullptr;
Peter Collingbourne2612a322015-07-04 05:28:41279
280 // If this symbol is external weak, try to resolve it to a defined
281 // symbol by searching the chain of fallback symbols. Returns the symbol if
282 // successful, otherwise returns null.
283 Defined *getWeakAlias();
Rui Ueyama411c63602015-05-28 19:09:30284};
285
286// Windows-specific classes.
287
Rui Ueyama7c4fcdd2015-05-29 15:49:09288// This class represents a symbol imported from a DLL. This has two
289// names for internal use and external use. The former is used for
290// name resolution, and the latter is used for the import descriptor
291// table in an output. The former has "__imp_" prefix.
292class DefinedImportData : public Defined {
293public:
Peter Collingbourne79a5e6b2016-12-09 21:55:24294 DefinedImportData(StringRef N, ImportFile *F)
Rui Ueyamab6632d92017-05-22 06:01:37295 : Defined(DefinedImportDataKind, N), File(F) {
296 }
Rui Ueyama7c4fcdd2015-05-29 15:49:09297
Rui Ueyamaf52496e2017-11-03 21:21:47298 static bool classof(const Symbol *S) {
Rui Ueyama7c4fcdd2015-05-29 15:49:09299 return S->kind() == DefinedImportDataKind;
300 }
301
Peter Collingbourne79a5e6b2016-12-09 21:55:24302 uint64_t getRVA() { return File->Location->getRVA(); }
Reid Klecknera1001b82017-06-28 17:06:35303 Chunk *getChunk() { return File->Location; }
304 void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
305
Peter Collingbourne79a5e6b2016-12-09 21:55:24306 StringRef getDLLName() { return File->DLLName; }
307 StringRef getExternalName() { return File->ExternalName; }
Peter Collingbourne79a5e6b2016-12-09 21:55:24308 uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
Rui Ueyama7c4fcdd2015-05-29 15:49:09309
Peter Collingbourne79a5e6b2016-12-09 21:55:24310 ImportFile *File;
Rui Ueyama7c4fcdd2015-05-29 15:49:09311};
312
Rui Ueyama411c63602015-05-28 19:09:30313// This class represents a symbol for a jump table entry which jumps
314// to a function in a DLL. Linker are supposed to create such symbols
315// without "__imp_" prefix for all function symbols exported from
316// DLLs, so that you can call DLL functions as regular functions with
317// a regular name. A function pointer is given as a DefinedImportData.
318class DefinedImportThunk : public Defined {
319public:
Rui Ueyama5e706b32015-07-25 21:54:50320 DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine);
Rui Ueyama411c63602015-05-28 19:09:30321
Rui Ueyamaf52496e2017-11-03 21:21:47322 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30323 return S->kind() == DefinedImportThunkKind;
324 }
325
Rui Ueyama28df0422015-07-25 01:16:06326 uint64_t getRVA() { return Data->getRVA(); }
Peter Collingbournee50f4852016-12-12 18:42:09327 Chunk *getChunk() { return Data; }
Rui Ueyama411c63602015-05-28 19:09:30328
Rui Ueyama9aa82f72017-05-24 22:30:06329 DefinedImportData *WrappedSym;
330
Rui Ueyama411c63602015-05-28 19:09:30331private:
Peter Collingbournee50f4852016-12-12 18:42:09332 Chunk *Data;
Rui Ueyama411c63602015-05-28 19:09:30333};
334
Rui Ueyama88e0f922015-06-25 03:31:47335// If you have a symbol "__imp_foo" in your object file, a symbol name
336// "foo" becomes automatically available as a pointer to "__imp_foo".
337// This class is for such automatically-created symbols.
338// Yes, this is an odd feature. We didn't intend to implement that.
339// This is here just for compatibility with MSVC.
340class DefinedLocalImport : public Defined {
341public:
342 DefinedLocalImport(StringRef N, Defined *S)
Rui Ueyamab6632d92017-05-22 06:01:37343 : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {}
Rui Ueyama88e0f922015-06-25 03:31:47344
Rui Ueyamaf52496e2017-11-03 21:21:47345 static bool classof(const Symbol *S) {
Rui Ueyama88e0f922015-06-25 03:31:47346 return S->kind() == DefinedLocalImportKind;
347 }
348
Peter Collingbourne79a5e6b2016-12-09 21:55:24349 uint64_t getRVA() { return Data->getRVA(); }
Peter Collingbournee50f4852016-12-12 18:42:09350 Chunk *getChunk() { return Data; }
Rui Ueyama88e0f922015-06-25 03:31:47351
352private:
Peter Collingbournee50f4852016-12-12 18:42:09353 LocalImportChunk *Data;
Rui Ueyama88e0f922015-06-25 03:31:47354};
355
Rui Ueyamacb71c722015-07-13 22:01:27356inline uint64_t Defined::getRVA() {
357 switch (kind()) {
358 case DefinedAbsoluteKind:
359 return cast<DefinedAbsolute>(this)->getRVA();
Reid Kleckner502d4ce2017-06-26 15:39:52360 case DefinedSyntheticKind:
361 return cast<DefinedSynthetic>(this)->getRVA();
Rui Ueyamacb71c722015-07-13 22:01:27362 case DefinedImportDataKind:
363 return cast<DefinedImportData>(this)->getRVA();
364 case DefinedImportThunkKind:
365 return cast<DefinedImportThunk>(this)->getRVA();
366 case DefinedLocalImportKind:
367 return cast<DefinedLocalImport>(this)->getRVA();
368 case DefinedCommonKind:
369 return cast<DefinedCommon>(this)->getRVA();
370 case DefinedRegularKind:
371 return cast<DefinedRegular>(this)->getRVA();
Rui Ueyamacb71c722015-07-13 22:01:27372 case LazyKind:
373 case UndefinedKind:
374 llvm_unreachable("Cannot get the address for an undefined symbol.");
375 }
376 llvm_unreachable("unknown symbol kind");
377}
378
Reid Klecknera1001b82017-06-28 17:06:35379inline Chunk *Defined::getChunk() {
380 switch (kind()) {
381 case DefinedRegularKind:
382 return cast<DefinedRegular>(this)->getChunk();
383 case DefinedAbsoluteKind:
384 return nullptr;
385 case DefinedSyntheticKind:
386 return cast<DefinedSynthetic>(this)->getChunk();
387 case DefinedImportDataKind:
388 return cast<DefinedImportData>(this)->getChunk();
389 case DefinedImportThunkKind:
390 return cast<DefinedImportThunk>(this)->getChunk();
391 case DefinedLocalImportKind:
392 return cast<DefinedLocalImport>(this)->getChunk();
393 case DefinedCommonKind:
394 return cast<DefinedCommon>(this)->getChunk();
395 case LazyKind:
396 case UndefinedKind:
397 llvm_unreachable("Cannot get the chunk of an undefined symbol.");
398 }
399 llvm_unreachable("unknown symbol kind");
400}
401
Rui Ueyamaf52496e2017-11-03 21:21:47402// A buffer class that is large enough to hold any Symbol-derived
Rui Ueyama616cd992017-10-31 16:10:24403// object. We allocate memory using this class and instantiate a symbol
404// using the placement new.
405union SymbolUnion {
Rui Ueyamaf78d0972017-10-31 17:07:47406 alignas(DefinedRegular) char A[sizeof(DefinedRegular)];
407 alignas(DefinedCommon) char B[sizeof(DefinedCommon)];
408 alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)];
409 alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)];
410 alignas(Lazy) char E[sizeof(Lazy)];
411 alignas(Undefined) char F[sizeof(Undefined)];
412 alignas(DefinedImportData) char G[sizeof(DefinedImportData)];
413 alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)];
414 alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)];
Peter Collingbourne79a5e6b2016-12-09 21:55:24415};
416
417template <typename T, typename... ArgT>
Rui Ueyamaf483da02017-11-03 22:48:47418void replaceSymbol(Symbol *S, ArgT &&... Arg) {
Rui Ueyama616cd992017-10-31 16:10:24419 static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
420 static_assert(alignof(T) <= alignof(SymbolUnion),
421 "SymbolUnion not aligned enough");
Rui Ueyamaf52496e2017-11-03 21:21:47422 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
423 "Not a Symbol");
Rui Ueyama616cd992017-10-31 16:10:24424 new (S) T(std::forward<ArgT>(Arg)...);
Peter Collingbourne79a5e6b2016-12-09 21:55:24425}
Rui Ueyama411c63602015-05-28 19:09:30426} // namespace coff
Rui Ueyamace039262017-01-06 10:04:08427
Rui Ueyamaf52496e2017-11-03 21:21:47428std::string toString(coff::Symbol &B);
Rui Ueyama411c63602015-05-28 19:09:30429} // namespace lld
430
Rui Ueyama411c63602015-05-28 19:09:30431#endif