blob: 53e45a8064eacffcd0d1f3a179b232e6157419bf [file] [log] [blame]
Rafael Espindolabeee25e2015-08-14 14:12:541//===- Symbols.h ------------------------------------------------*- C++ -*-===//
Rui Ueyama411c63602015-05-28 19:09:302//
Chandler Carruth2946cd72019-01-19 08:50:563// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Rui Ueyama411c63602015-05-28 19:09:306//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_COFF_SYMBOLS_H
10#define LLD_COFF_SYMBOLS_H
11
12#include "Chunks.h"
13#include "Config.h"
Rui Ueyama3f851702017-10-02 21:00:4114#include "lld/Common/LLVM.h"
Rui Ueyama2017d522017-11-28 20:39:1715#include "lld/Common/Memory.h"
Rui Ueyama411c63602015-05-28 19:09:3016#include "llvm/ADT/ArrayRef.h"
17#include "llvm/Object/Archive.h"
18#include "llvm/Object/COFF.h"
Rui Ueyamac80c03d2015-07-05 21:54:4219#include <atomic>
Rui Ueyama411c63602015-05-28 19:09:3020#include <memory>
21#include <vector>
22
23namespace lld {
24namespace coff {
25
26using llvm::object::Archive;
27using llvm::object::COFFSymbolRef;
Rui Ueyamac9bfe322015-05-29 15:45:3528using llvm::object::coff_import_header;
Rui Ueyamac15139b2015-06-30 00:10:5429using llvm::object::coff_symbol_generic;
Rui Ueyama411c63602015-05-28 19:09:3030
31class ArchiveFile;
32class InputFile;
Rui Ueyamae1b48e02017-07-26 23:05:2433class ObjFile;
Peter Collingbourne79a5e6b2016-12-09 21:55:2434class SymbolTable;
Rui Ueyama411c63602015-05-28 19:09:3035
36// The base class for real symbol classes.
Rui Ueyamaf52496e2017-11-03 21:21:4737class Symbol {
Rui Ueyama411c63602015-05-28 19:09:3038public:
39 enum Kind {
Chandler Carruth64c17c72015-06-29 21:35:4840 // The order of these is significant. We start with the regular defined
Nico Weber1f3ab982019-01-14 19:05:2141 // symbols as those are the most prevalent and the zero tag is the cheapest
Chandler Carruth64c17c72015-06-29 21:35:4842 // to set. Among the defined kinds, the lower the kind is preferred over
Nico Weberc7bad572018-08-27 14:22:2543 // the higher kind when testing whether one symbol should take precedence
Chandler Carruth64c17c72015-06-29 21:35:4844 // over another.
45 DefinedRegularKind = 0,
Rui Ueyamaefb7e1a2015-06-20 07:21:5746 DefinedCommonKind,
Chandler Carruth64c17c72015-06-29 21:35:4847 DefinedLocalImportKind,
48 DefinedImportThunkKind,
49 DefinedImportDataKind,
50 DefinedAbsoluteKind,
Reid Kleckner502d4ce2017-06-26 15:39:5251 DefinedSyntheticKind,
Chandler Carruth64c17c72015-06-29 21:35:4852
Rui Ueyamae2514762015-06-15 19:06:5353 UndefinedKind,
Rui Ueyama8d3010a2015-06-30 19:35:2154 LazyKind,
Chandler Carruth64c17c72015-06-29 21:35:4855
56 LastDefinedCOFFKind = DefinedCommonKind,
Reid Kleckner502d4ce2017-06-26 15:39:5257 LastDefinedKind = DefinedSyntheticKind,
Rui Ueyama411c63602015-05-28 19:09:3058 };
59
Chandler Carruth64c17c72015-06-29 21:35:4860 Kind kind() const { return static_cast<Kind>(SymbolKind); }
Rui Ueyama411c63602015-05-28 19:09:3061
Rui Ueyama411c63602015-05-28 19:09:3062 // Returns the symbol name.
Chandler Carruth64c17c72015-06-29 21:35:4863 StringRef getName();
Rui Ueyama411c63602015-05-28 19:09:3064
Martin Storsjoeac1b052018-08-27 08:43:3165 void replaceKeepingName(Symbol *Other, size_t Size);
66
Rui Ueyamaa45d45e2016-12-07 23:17:0267 // Returns the file from which this symbol was created.
68 InputFile *getFile();
69
Reid Klecknereacdf042017-07-27 18:25:5970 // Indicates that this symbol will be included in the final image. Only valid
71 // after calling markLive.
72 bool isLive() const;
73
Rui Ueyama411c63602015-05-28 19:09:3074protected:
Peter Collingbourne79a5e6b2016-12-09 21:55:2475 friend SymbolTable;
Rui Ueyamaf52496e2017-11-03 21:21:4776 explicit Symbol(Kind K, StringRef N = "")
Chandler Carruth64c17c72015-06-29 21:35:4877 : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
Peter Collingbournef874bd62017-11-21 01:14:1478 WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false),
Reid Klecknera30920c2019-04-19 22:51:4979 IsRuntimePseudoReloc(false), NameSize(N.size()),
80 NameData(N.empty() ? nullptr : N.data()) {}
Rui Ueyama411c63602015-05-28 19:09:3081
Chandler Carruth64c17c72015-06-29 21:35:4882 const unsigned SymbolKind : 8;
83 unsigned IsExternal : 1;
84
Rui Ueyama7e296ad2019-07-10 09:10:0185public:
Chandler Carruth64c17c72015-06-29 21:35:4886 // This bit is used by the \c DefinedRegular subclass.
87 unsigned IsCOMDAT : 1;
88
Peter Collingbournef874bd62017-11-21 01:14:1489 // This bit is used by Writer::createSymbolAndStringTable() to prevent
90 // symbols from being written to the symbol table more than once.
91 unsigned WrittenToSymtab : 1;
92
Rui Ueyama616cd992017-10-31 16:10:2493 // True if this symbol was referenced by a regular (non-bitcode) object.
94 unsigned IsUsedInRegularObj : 1;
95
96 // True if we've seen both a lazy and an undefined symbol with this symbol
97 // name, which means that we have enqueued an archive member load and should
98 // not load any more archive members to resolve the same symbol.
99 unsigned PendingArchiveLoad : 1;
100
Reid Kleckner58839892017-11-13 18:38:53101 /// True if we've already added this symbol to the list of GC roots.
102 unsigned IsGCRoot : 1;
103
Martin Storsjo2bfa1252018-09-26 06:13:39104 unsigned IsRuntimePseudoReloc : 1;
105
Peter Collingbourne99111282016-12-11 22:15:20106protected:
Reid Klecknera30920c2019-04-19 22:51:49107 // Symbol name length. Assume symbol lengths fit in a 32-bit integer.
108 uint32_t NameSize;
109
110 const char *NameData;
Rui Ueyama411c63602015-05-28 19:09:30111};
112
113// The base class for any defined symbols, including absolute symbols,
114// etc.
Rui Ueyamaf52496e2017-11-03 21:21:47115class Defined : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30116public:
Rui Ueyamaf52496e2017-11-03 21:21:47117 Defined(Kind K, StringRef N) : Symbol(K, N) {}
Rui Ueyama411c63602015-05-28 19:09:30118
Rui Ueyamaf52496e2017-11-03 21:21:47119 static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; }
Rui Ueyama411c63602015-05-28 19:09:30120
121 // Returns the RVA (relative virtual address) of this symbol. The
122 // writer sets and uses RVAs.
Chandler Carruth64c17c72015-06-29 21:35:48123 uint64_t getRVA();
Rui Ueyama411c63602015-05-28 19:09:30124
Reid Klecknera1001b82017-06-28 17:06:35125 // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
126 // do not have chunks, so this may return null.
127 Chunk *getChunk();
Chandler Carruth64c17c72015-06-29 21:35:48128};
Rui Ueyama411c63602015-05-28 19:09:30129
Bob Haarmancde5e5b2017-02-02 23:58:14130// Symbols defined via a COFF object file or bitcode file. For COFF files, this
131// stores a coff_symbol_generic*, and names of internal symbols are lazily
132// loaded through that. For bitcode files, Sym is nullptr and the name is stored
Reid Klecknera30920c2019-04-19 22:51:49133// as a decomposed StringRef.
Chandler Carruth64c17c72015-06-29 21:35:48134class DefinedCOFF : public Defined {
Rui Ueyamaf52496e2017-11-03 21:21:47135 friend Symbol;
136
Chandler Carruth64c17c72015-06-29 21:35:48137public:
Bob Haarmancde5e5b2017-02-02 23:58:14138 DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S)
139 : Defined(K, N), File(F), Sym(S) {}
Chandler Carruth64c17c72015-06-29 21:35:48140
Rui Ueyamaf52496e2017-11-03 21:21:47141 static bool classof(const Symbol *S) {
Chandler Carruth64c17c72015-06-29 21:35:48142 return S->kind() <= LastDefinedCOFFKind;
143 }
144
Bob Haarmancde5e5b2017-02-02 23:58:14145 InputFile *getFile() { return File; }
Rui Ueyama65813ed2015-07-02 20:33:48146
David Majnemer3a62d3d2015-07-09 17:43:50147 COFFSymbolRef getCOFFSymbol();
148
Bob Haarmancde5e5b2017-02-02 23:58:14149 InputFile *File;
Rui Ueyamaa45d45e2016-12-07 23:17:02150
151protected:
Rui Ueyamac15139b2015-06-30 00:10:54152 const coff_symbol_generic *Sym;
Rui Ueyama411c63602015-05-28 19:09:30153};
154
155// Regular defined symbols read from object file symbol tables.
Chandler Carruth64c17c72015-06-29 21:35:48156class DefinedRegular : public DefinedCOFF {
Rui Ueyama411c63602015-05-28 19:09:30157public:
Bob Haarmancde5e5b2017-02-02 23:58:14158 DefinedRegular(InputFile *F, StringRef N, bool IsCOMDAT,
159 bool IsExternal = false,
160 const coff_symbol_generic *S = nullptr,
161 SectionChunk *C = nullptr)
Bob Haarmancd7197f2017-02-03 23:05:17162 : DefinedCOFF(DefinedRegularKind, F, N, S), Data(C ? &C->Repl : nullptr) {
Bob Haarmancde5e5b2017-02-02 23:58:14163 this->IsExternal = IsExternal;
164 this->IsCOMDAT = IsCOMDAT;
Chandler Carruth64c17c72015-06-29 21:35:48165 }
Rui Ueyama411c63602015-05-28 19:09:30166
Rui Ueyamaf52496e2017-11-03 21:21:47167 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30168 return S->kind() == DefinedRegularKind;
169 }
170
Reid Klecknereacdf042017-07-27 18:25:59171 uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; }
Reid Klecknereacdf042017-07-27 18:25:59172 SectionChunk *getChunk() const { return *Data; }
173 uint32_t getValue() const { return Sym->Value; }
Rui Ueyama411c63602015-05-28 19:09:30174
Rui Ueyama9b921e52015-06-25 22:00:42175 SectionChunk **Data;
Rui Ueyamaefb7e1a2015-06-20 07:21:57176};
177
Chandler Carruth64c17c72015-06-29 21:35:48178class DefinedCommon : public DefinedCOFF {
Rui Ueyamaefb7e1a2015-06-20 07:21:57179public:
Bob Haarmancde5e5b2017-02-02 23:58:14180 DefinedCommon(InputFile *F, StringRef N, uint64_t Size,
181 const coff_symbol_generic *S = nullptr,
182 CommonChunk *C = nullptr)
183 : DefinedCOFF(DefinedCommonKind, F, N, S), Data(C), Size(Size) {
184 this->IsExternal = true;
Chandler Carruth64c17c72015-06-29 21:35:48185 }
Rui Ueyamaefb7e1a2015-06-20 07:21:57186
Rui Ueyamaf52496e2017-11-03 21:21:47187 static bool classof(const Symbol *S) {
Rui Ueyamaefb7e1a2015-06-20 07:21:57188 return S->kind() == DefinedCommonKind;
189 }
190
Chandler Carruth64c17c72015-06-29 21:35:48191 uint64_t getRVA() { return Data->getRVA(); }
Martin Storsjod2752aa2017-08-14 19:07:27192 CommonChunk *getChunk() { return Data; }
Rui Ueyama411c63602015-05-28 19:09:30193
194private:
Peter Collingbourne79a5e6b2016-12-09 21:55:24195 friend SymbolTable;
Bob Haarmancde5e5b2017-02-02 23:58:14196 uint64_t getSize() const { return Size; }
Rui Ueyamafc510f42015-06-25 19:10:58197 CommonChunk *Data;
Bob Haarmancde5e5b2017-02-02 23:58:14198 uint64_t Size;
Rui Ueyama411c63602015-05-28 19:09:30199};
200
201// Absolute symbols.
202class DefinedAbsolute : public Defined {
203public:
Rui Ueyamaccde19d2015-06-26 03:09:23204 DefinedAbsolute(StringRef N, COFFSymbolRef S)
Chandler Carruth64c17c72015-06-29 21:35:48205 : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) {
206 IsExternal = S.isExternal();
207 }
Rui Ueyamaccde19d2015-06-26 03:09:23208
209 DefinedAbsolute(StringRef N, uint64_t V)
Chandler Carruth64c17c72015-06-29 21:35:48210 : Defined(DefinedAbsoluteKind, N), VA(V) {}
Rui Ueyama411c63602015-05-28 19:09:30211
Rui Ueyamaf52496e2017-11-03 21:21:47212 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30213 return S->kind() == DefinedAbsoluteKind;
214 }
215
Chandler Carruth64c17c72015-06-29 21:35:48216 uint64_t getRVA() { return VA - Config->ImageBase; }
Rui Ueyamacd3f99b2015-07-24 23:51:14217 void setVA(uint64_t V) { VA = V; }
Rui Ueyama411c63602015-05-28 19:09:30218
Rui Ueyamab3107472018-02-17 20:41:38219 // Section index relocations against absolute symbols resolve to
220 // this 16 bit number, and it is the largest valid section index
221 // plus one. This variable keeps it.
222 static uint16_t NumOutputSections;
Reid Kleckner84564112017-06-22 23:33:04223
Rui Ueyama411c63602015-05-28 19:09:30224private:
Rui Ueyamaccde19d2015-06-26 03:09:23225 uint64_t VA;
Rui Ueyama411c63602015-05-28 19:09:30226};
227
Reid Kleckner502d4ce2017-06-26 15:39:52228// This symbol is used for linker-synthesized symbols like __ImageBase and
229// __safe_se_handler_table.
230class DefinedSynthetic : public Defined {
Rui Ueyama3cb895c2015-07-24 22:58:44231public:
Reid Kleckner502d4ce2017-06-26 15:39:52232 explicit DefinedSynthetic(StringRef Name, Chunk *C)
233 : Defined(DefinedSyntheticKind, Name), C(C) {}
Rui Ueyama3cb895c2015-07-24 22:58:44234
Rui Ueyamaf52496e2017-11-03 21:21:47235 static bool classof(const Symbol *S) {
Reid Kleckner502d4ce2017-06-26 15:39:52236 return S->kind() == DefinedSyntheticKind;
Rui Ueyama3cb895c2015-07-24 22:58:44237 }
238
Reid Kleckner502d4ce2017-06-26 15:39:52239 // A null chunk indicates that this is __ImageBase. Otherwise, this is some
240 // other synthesized chunk, like SEHTableChunk.
Reid Klecknera1001b82017-06-28 17:06:35241 uint32_t getRVA() { return C ? C->getRVA() : 0; }
242 Chunk *getChunk() { return C; }
Rui Ueyama3cb895c2015-07-24 22:58:44243
244private:
Reid Kleckner502d4ce2017-06-26 15:39:52245 Chunk *C;
Rui Ueyama3cb895c2015-07-24 22:58:44246};
247
Rui Ueyama411c63602015-05-28 19:09:30248// This class represents a symbol defined in an archive file. It is
249// created from an archive file header, and it knows how to load an
250// object file from an archive to replace itself with a defined
251// symbol. If the resolver finds both Undefined and Lazy for
252// the same name, it will ask the Lazy to load a file.
Rui Ueyamaf52496e2017-11-03 21:21:47253class Lazy : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30254public:
255 Lazy(ArchiveFile *F, const Archive::Symbol S)
Rui Ueyamaf52496e2017-11-03 21:21:47256 : Symbol(LazyKind, S.getName()), File(F), Sym(S) {}
Rui Ueyama411c63602015-05-28 19:09:30257
Rui Ueyamaf52496e2017-11-03 21:21:47258 static bool classof(const Symbol *S) { return S->kind() == LazyKind; }
Rui Ueyama411c63602015-05-28 19:09:30259
Rui Ueyama411c63602015-05-28 19:09:30260 ArchiveFile *File;
Rui Ueyamaa45d45e2016-12-07 23:17:02261
262private:
Peter Collingbourne79a5e6b2016-12-09 21:55:24263 friend SymbolTable;
264
265private:
Rui Ueyama411c63602015-05-28 19:09:30266 const Archive::Symbol Sym;
267};
268
269// Undefined symbols.
Rui Ueyamaf52496e2017-11-03 21:21:47270class Undefined : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30271public:
Rui Ueyamaf52496e2017-11-03 21:21:47272 explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {}
Rui Ueyama411c63602015-05-28 19:09:30273
Rui Ueyamaf52496e2017-11-03 21:21:47274 static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }
Rui Ueyama411c63602015-05-28 19:09:30275
276 // An undefined symbol can have a fallback symbol which gives an
277 // undefined symbol a second chance if it would remain undefined.
278 // If it remains undefined, it'll be replaced with whatever the
279 // Alias pointer points to.
Rui Ueyamaf52496e2017-11-03 21:21:47280 Symbol *WeakAlias = nullptr;
Peter Collingbourne2612a322015-07-04 05:28:41281
282 // If this symbol is external weak, try to resolve it to a defined
283 // symbol by searching the chain of fallback symbols. Returns the symbol if
284 // successful, otherwise returns null.
285 Defined *getWeakAlias();
Rui Ueyama411c63602015-05-28 19:09:30286};
287
288// Windows-specific classes.
289
Rui Ueyama7c4fcdd2015-05-29 15:49:09290// This class represents a symbol imported from a DLL. This has two
291// names for internal use and external use. The former is used for
292// name resolution, and the latter is used for the import descriptor
293// table in an output. The former has "__imp_" prefix.
294class DefinedImportData : public Defined {
295public:
Peter Collingbourne79a5e6b2016-12-09 21:55:24296 DefinedImportData(StringRef N, ImportFile *F)
Rui Ueyamab6632d92017-05-22 06:01:37297 : Defined(DefinedImportDataKind, N), File(F) {
298 }
Rui Ueyama7c4fcdd2015-05-29 15:49:09299
Rui Ueyamaf52496e2017-11-03 21:21:47300 static bool classof(const Symbol *S) {
Rui Ueyama7c4fcdd2015-05-29 15:49:09301 return S->kind() == DefinedImportDataKind;
302 }
303
Peter Collingbourne79a5e6b2016-12-09 21:55:24304 uint64_t getRVA() { return File->Location->getRVA(); }
Reid Klecknera1001b82017-06-28 17:06:35305 Chunk *getChunk() { return File->Location; }
306 void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
307
Peter Collingbourne79a5e6b2016-12-09 21:55:24308 StringRef getDLLName() { return File->DLLName; }
309 StringRef getExternalName() { return File->ExternalName; }
Peter Collingbourne79a5e6b2016-12-09 21:55:24310 uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
Rui Ueyama7c4fcdd2015-05-29 15:49:09311
Peter Collingbourne79a5e6b2016-12-09 21:55:24312 ImportFile *File;
Rui Ueyama7c4fcdd2015-05-29 15:49:09313};
314
Rui Ueyama411c63602015-05-28 19:09:30315// This class represents a symbol for a jump table entry which jumps
316// to a function in a DLL. Linker are supposed to create such symbols
317// without "__imp_" prefix for all function symbols exported from
318// DLLs, so that you can call DLL functions as regular functions with
319// a regular name. A function pointer is given as a DefinedImportData.
320class DefinedImportThunk : public Defined {
321public:
Rui Ueyama5e706b32015-07-25 21:54:50322 DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine);
Rui Ueyama411c63602015-05-28 19:09:30323
Rui Ueyamaf52496e2017-11-03 21:21:47324 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30325 return S->kind() == DefinedImportThunkKind;
326 }
327
Rui Ueyama28df0422015-07-25 01:16:06328 uint64_t getRVA() { return Data->getRVA(); }
Peter Collingbournee50f4852016-12-12 18:42:09329 Chunk *getChunk() { return Data; }
Rui Ueyama411c63602015-05-28 19:09:30330
Rui Ueyama9aa82f72017-05-24 22:30:06331 DefinedImportData *WrappedSym;
332
Rui Ueyama411c63602015-05-28 19:09:30333private:
Peter Collingbournee50f4852016-12-12 18:42:09334 Chunk *Data;
Rui Ueyama411c63602015-05-28 19:09:30335};
336
Martin Storsjod9fd4a02018-08-07 06:42:53337// If you have a symbol "foo" in your object file, a symbol name
338// "__imp_foo" becomes automatically available as a pointer to "foo".
Rui Ueyama88e0f922015-06-25 03:31:47339// This class is for such automatically-created symbols.
340// Yes, this is an odd feature. We didn't intend to implement that.
341// This is here just for compatibility with MSVC.
342class DefinedLocalImport : public Defined {
343public:
344 DefinedLocalImport(StringRef N, Defined *S)
Rui Ueyamab6632d92017-05-22 06:01:37345 : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {}
Rui Ueyama88e0f922015-06-25 03:31:47346
Rui Ueyamaf52496e2017-11-03 21:21:47347 static bool classof(const Symbol *S) {
Rui Ueyama88e0f922015-06-25 03:31:47348 return S->kind() == DefinedLocalImportKind;
349 }
350
Peter Collingbourne79a5e6b2016-12-09 21:55:24351 uint64_t getRVA() { return Data->getRVA(); }
Peter Collingbournee50f4852016-12-12 18:42:09352 Chunk *getChunk() { return Data; }
Rui Ueyama88e0f922015-06-25 03:31:47353
354private:
Peter Collingbournee50f4852016-12-12 18:42:09355 LocalImportChunk *Data;
Rui Ueyama88e0f922015-06-25 03:31:47356};
357
Rui Ueyamacb71c722015-07-13 22:01:27358inline uint64_t Defined::getRVA() {
359 switch (kind()) {
360 case DefinedAbsoluteKind:
361 return cast<DefinedAbsolute>(this)->getRVA();
Reid Kleckner502d4ce2017-06-26 15:39:52362 case DefinedSyntheticKind:
363 return cast<DefinedSynthetic>(this)->getRVA();
Rui Ueyamacb71c722015-07-13 22:01:27364 case DefinedImportDataKind:
365 return cast<DefinedImportData>(this)->getRVA();
366 case DefinedImportThunkKind:
367 return cast<DefinedImportThunk>(this)->getRVA();
368 case DefinedLocalImportKind:
369 return cast<DefinedLocalImport>(this)->getRVA();
370 case DefinedCommonKind:
371 return cast<DefinedCommon>(this)->getRVA();
372 case DefinedRegularKind:
373 return cast<DefinedRegular>(this)->getRVA();
Rui Ueyamacb71c722015-07-13 22:01:27374 case LazyKind:
375 case UndefinedKind:
376 llvm_unreachable("Cannot get the address for an undefined symbol.");
377 }
378 llvm_unreachable("unknown symbol kind");
379}
380
Reid Klecknera1001b82017-06-28 17:06:35381inline Chunk *Defined::getChunk() {
382 switch (kind()) {
383 case DefinedRegularKind:
384 return cast<DefinedRegular>(this)->getChunk();
385 case DefinedAbsoluteKind:
386 return nullptr;
387 case DefinedSyntheticKind:
388 return cast<DefinedSynthetic>(this)->getChunk();
389 case DefinedImportDataKind:
390 return cast<DefinedImportData>(this)->getChunk();
391 case DefinedImportThunkKind:
392 return cast<DefinedImportThunk>(this)->getChunk();
393 case DefinedLocalImportKind:
394 return cast<DefinedLocalImport>(this)->getChunk();
395 case DefinedCommonKind:
396 return cast<DefinedCommon>(this)->getChunk();
397 case LazyKind:
398 case UndefinedKind:
399 llvm_unreachable("Cannot get the chunk of an undefined symbol.");
400 }
401 llvm_unreachable("unknown symbol kind");
402}
403
Rui Ueyamaf52496e2017-11-03 21:21:47404// A buffer class that is large enough to hold any Symbol-derived
Rui Ueyama616cd992017-10-31 16:10:24405// object. We allocate memory using this class and instantiate a symbol
406// using the placement new.
407union SymbolUnion {
Rui Ueyamaf78d0972017-10-31 17:07:47408 alignas(DefinedRegular) char A[sizeof(DefinedRegular)];
409 alignas(DefinedCommon) char B[sizeof(DefinedCommon)];
410 alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)];
411 alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)];
412 alignas(Lazy) char E[sizeof(Lazy)];
413 alignas(Undefined) char F[sizeof(Undefined)];
414 alignas(DefinedImportData) char G[sizeof(DefinedImportData)];
415 alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)];
416 alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)];
Peter Collingbourne79a5e6b2016-12-09 21:55:24417};
418
419template <typename T, typename... ArgT>
Rui Ueyamaf483da02017-11-03 22:48:47420void replaceSymbol(Symbol *S, ArgT &&... Arg) {
Sam Clegg38f52b22018-02-13 17:32:31421 static_assert(std::is_trivially_destructible<T>(),
422 "Symbol types must be trivially destructible");
Rui Ueyama616cd992017-10-31 16:10:24423 static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
424 static_assert(alignof(T) <= alignof(SymbolUnion),
425 "SymbolUnion not aligned enough");
Rui Ueyama38781a52018-02-14 22:43:43426 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
427 "Not a Symbol");
Rui Ueyama616cd992017-10-31 16:10:24428 new (S) T(std::forward<ArgT>(Arg)...);
Peter Collingbourne79a5e6b2016-12-09 21:55:24429}
Rui Ueyama411c63602015-05-28 19:09:30430} // namespace coff
Rui Ueyamace039262017-01-06 10:04:08431
Rui Ueyamaf52496e2017-11-03 21:21:47432std::string toString(coff::Symbol &B);
Rui Ueyama411c63602015-05-28 19:09:30433} // namespace lld
434
Rui Ueyama411c63602015-05-28 19:09:30435#endif