blob: ee0c0e7b05858c55dbcddbbbcbaccf1c92d2f54e [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
62 // Returns true if this is an external symbol.
Chandler Carruth64c17c72015-06-29 21:35:4863 bool isExternal() { return IsExternal; }
Rui Ueyama411c63602015-05-28 19:09:3064
65 // Returns the symbol name.
Chandler Carruth64c17c72015-06-29 21:35:4866 StringRef getName();
Rui Ueyama411c63602015-05-28 19:09:3067
Martin Storsjoeac1b052018-08-27 08:43:3168 void replaceKeepingName(Symbol *Other, size_t Size);
69
Rui Ueyamaa45d45e2016-12-07 23:17:0270 // Returns the file from which this symbol was created.
71 InputFile *getFile();
72
Reid Klecknereacdf042017-07-27 18:25:5973 // Indicates that this symbol will be included in the final image. Only valid
74 // after calling markLive.
75 bool isLive() const;
76
Rui Ueyama411c63602015-05-28 19:09:3077protected:
Peter Collingbourne79a5e6b2016-12-09 21:55:2478 friend SymbolTable;
Rui Ueyamaf52496e2017-11-03 21:21:4779 explicit Symbol(Kind K, StringRef N = "")
Chandler Carruth64c17c72015-06-29 21:35:4880 : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
Peter Collingbournef874bd62017-11-21 01:14:1481 WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false),
Reid Klecknera30920c2019-04-19 22:51:4982 IsRuntimePseudoReloc(false), NameSize(N.size()),
83 NameData(N.empty() ? nullptr : N.data()) {}
Rui Ueyama411c63602015-05-28 19:09:3084
Chandler Carruth64c17c72015-06-29 21:35:4885 const unsigned SymbolKind : 8;
86 unsigned IsExternal : 1;
87
88 // This bit is used by the \c DefinedRegular subclass.
89 unsigned IsCOMDAT : 1;
90
Peter Collingbourne99111282016-12-11 22:15:2091public:
Peter Collingbournef874bd62017-11-21 01:14:1492 // This bit is used by Writer::createSymbolAndStringTable() to prevent
93 // symbols from being written to the symbol table more than once.
94 unsigned WrittenToSymtab : 1;
95
Rui Ueyama616cd992017-10-31 16:10:2496 // True if this symbol was referenced by a regular (non-bitcode) object.
97 unsigned IsUsedInRegularObj : 1;
98
99 // True if we've seen both a lazy and an undefined symbol with this symbol
100 // name, which means that we have enqueued an archive member load and should
101 // not load any more archive members to resolve the same symbol.
102 unsigned PendingArchiveLoad : 1;
103
Reid Kleckner58839892017-11-13 18:38:53104 /// True if we've already added this symbol to the list of GC roots.
105 unsigned IsGCRoot : 1;
106
Martin Storsjo2bfa1252018-09-26 06:13:39107 unsigned IsRuntimePseudoReloc : 1;
108
Peter Collingbourne99111282016-12-11 22:15:20109protected:
Reid Klecknera30920c2019-04-19 22:51:49110 // Symbol name length. Assume symbol lengths fit in a 32-bit integer.
111 uint32_t NameSize;
112
113 const char *NameData;
Rui Ueyama411c63602015-05-28 19:09:30114};
115
116// The base class for any defined symbols, including absolute symbols,
117// etc.
Rui Ueyamaf52496e2017-11-03 21:21:47118class Defined : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30119public:
Rui Ueyamaf52496e2017-11-03 21:21:47120 Defined(Kind K, StringRef N) : Symbol(K, N) {}
Rui Ueyama411c63602015-05-28 19:09:30121
Rui Ueyamaf52496e2017-11-03 21:21:47122 static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; }
Rui Ueyama411c63602015-05-28 19:09:30123
124 // Returns the RVA (relative virtual address) of this symbol. The
125 // writer sets and uses RVAs.
Chandler Carruth64c17c72015-06-29 21:35:48126 uint64_t getRVA();
Rui Ueyama411c63602015-05-28 19:09:30127
Reid Klecknera1001b82017-06-28 17:06:35128 // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
129 // do not have chunks, so this may return null.
130 Chunk *getChunk();
Chandler Carruth64c17c72015-06-29 21:35:48131};
Rui Ueyama411c63602015-05-28 19:09:30132
Bob Haarmancde5e5b2017-02-02 23:58:14133// Symbols defined via a COFF object file or bitcode file. For COFF files, this
134// stores a coff_symbol_generic*, and names of internal symbols are lazily
135// loaded through that. For bitcode files, Sym is nullptr and the name is stored
Reid Klecknera30920c2019-04-19 22:51:49136// as a decomposed StringRef.
Chandler Carruth64c17c72015-06-29 21:35:48137class DefinedCOFF : public Defined {
Rui Ueyamaf52496e2017-11-03 21:21:47138 friend Symbol;
139
Chandler Carruth64c17c72015-06-29 21:35:48140public:
Bob Haarmancde5e5b2017-02-02 23:58:14141 DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S)
142 : Defined(K, N), File(F), Sym(S) {}
Chandler Carruth64c17c72015-06-29 21:35:48143
Rui Ueyamaf52496e2017-11-03 21:21:47144 static bool classof(const Symbol *S) {
Chandler Carruth64c17c72015-06-29 21:35:48145 return S->kind() <= LastDefinedCOFFKind;
146 }
147
Bob Haarmancde5e5b2017-02-02 23:58:14148 InputFile *getFile() { return File; }
Rui Ueyama65813ed2015-07-02 20:33:48149
David Majnemer3a62d3d2015-07-09 17:43:50150 COFFSymbolRef getCOFFSymbol();
151
Bob Haarmancde5e5b2017-02-02 23:58:14152 InputFile *File;
Rui Ueyamaa45d45e2016-12-07 23:17:02153
154protected:
Rui Ueyamac15139b2015-06-30 00:10:54155 const coff_symbol_generic *Sym;
Rui Ueyama411c63602015-05-28 19:09:30156};
157
158// Regular defined symbols read from object file symbol tables.
Chandler Carruth64c17c72015-06-29 21:35:48159class DefinedRegular : public DefinedCOFF {
Rui Ueyama411c63602015-05-28 19:09:30160public:
Bob Haarmancde5e5b2017-02-02 23:58:14161 DefinedRegular(InputFile *F, StringRef N, bool IsCOMDAT,
162 bool IsExternal = false,
163 const coff_symbol_generic *S = nullptr,
164 SectionChunk *C = nullptr)
Bob Haarmancd7197f2017-02-03 23:05:17165 : DefinedCOFF(DefinedRegularKind, F, N, S), Data(C ? &C->Repl : nullptr) {
Bob Haarmancde5e5b2017-02-02 23:58:14166 this->IsExternal = IsExternal;
167 this->IsCOMDAT = IsCOMDAT;
Chandler Carruth64c17c72015-06-29 21:35:48168 }
Rui Ueyama411c63602015-05-28 19:09:30169
Rui Ueyamaf52496e2017-11-03 21:21:47170 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30171 return S->kind() == DefinedRegularKind;
172 }
173
Reid Klecknereacdf042017-07-27 18:25:59174 uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; }
175 bool isCOMDAT() const { return IsCOMDAT; }
176 SectionChunk *getChunk() const { return *Data; }
177 uint32_t getValue() const { return Sym->Value; }
Rui Ueyama411c63602015-05-28 19:09:30178
Rui Ueyama9b921e52015-06-25 22:00:42179 SectionChunk **Data;
Rui Ueyamaefb7e1a2015-06-20 07:21:57180};
181
Chandler Carruth64c17c72015-06-29 21:35:48182class DefinedCommon : public DefinedCOFF {
Rui Ueyamaefb7e1a2015-06-20 07:21:57183public:
Bob Haarmancde5e5b2017-02-02 23:58:14184 DefinedCommon(InputFile *F, StringRef N, uint64_t Size,
185 const coff_symbol_generic *S = nullptr,
186 CommonChunk *C = nullptr)
187 : DefinedCOFF(DefinedCommonKind, F, N, S), Data(C), Size(Size) {
188 this->IsExternal = true;
Chandler Carruth64c17c72015-06-29 21:35:48189 }
Rui Ueyamaefb7e1a2015-06-20 07:21:57190
Rui Ueyamaf52496e2017-11-03 21:21:47191 static bool classof(const Symbol *S) {
Rui Ueyamaefb7e1a2015-06-20 07:21:57192 return S->kind() == DefinedCommonKind;
193 }
194
Chandler Carruth64c17c72015-06-29 21:35:48195 uint64_t getRVA() { return Data->getRVA(); }
Martin Storsjod2752aa2017-08-14 19:07:27196 CommonChunk *getChunk() { return Data; }
Rui Ueyama411c63602015-05-28 19:09:30197
198private:
Peter Collingbourne79a5e6b2016-12-09 21:55:24199 friend SymbolTable;
Bob Haarmancde5e5b2017-02-02 23:58:14200 uint64_t getSize() const { return Size; }
Rui Ueyamafc510f42015-06-25 19:10:58201 CommonChunk *Data;
Bob Haarmancde5e5b2017-02-02 23:58:14202 uint64_t Size;
Rui Ueyama411c63602015-05-28 19:09:30203};
204
205// Absolute symbols.
206class DefinedAbsolute : public Defined {
207public:
Rui Ueyamaccde19d2015-06-26 03:09:23208 DefinedAbsolute(StringRef N, COFFSymbolRef S)
Chandler Carruth64c17c72015-06-29 21:35:48209 : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) {
210 IsExternal = S.isExternal();
211 }
Rui Ueyamaccde19d2015-06-26 03:09:23212
213 DefinedAbsolute(StringRef N, uint64_t V)
Chandler Carruth64c17c72015-06-29 21:35:48214 : Defined(DefinedAbsoluteKind, N), VA(V) {}
Rui Ueyama411c63602015-05-28 19:09:30215
Rui Ueyamaf52496e2017-11-03 21:21:47216 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30217 return S->kind() == DefinedAbsoluteKind;
218 }
219
Chandler Carruth64c17c72015-06-29 21:35:48220 uint64_t getRVA() { return VA - Config->ImageBase; }
Rui Ueyamacd3f99b2015-07-24 23:51:14221 void setVA(uint64_t V) { VA = V; }
Rui Ueyama411c63602015-05-28 19:09:30222
Rui Ueyamab3107472018-02-17 20:41:38223 // Section index relocations against absolute symbols resolve to
224 // this 16 bit number, and it is the largest valid section index
225 // plus one. This variable keeps it.
226 static uint16_t NumOutputSections;
Reid Kleckner84564112017-06-22 23:33:04227
Rui Ueyama411c63602015-05-28 19:09:30228private:
Rui Ueyamaccde19d2015-06-26 03:09:23229 uint64_t VA;
Rui Ueyama411c63602015-05-28 19:09:30230};
231
Reid Kleckner502d4ce2017-06-26 15:39:52232// This symbol is used for linker-synthesized symbols like __ImageBase and
233// __safe_se_handler_table.
234class DefinedSynthetic : public Defined {
Rui Ueyama3cb895c2015-07-24 22:58:44235public:
Reid Kleckner502d4ce2017-06-26 15:39:52236 explicit DefinedSynthetic(StringRef Name, Chunk *C)
237 : Defined(DefinedSyntheticKind, Name), C(C) {}
Rui Ueyama3cb895c2015-07-24 22:58:44238
Rui Ueyamaf52496e2017-11-03 21:21:47239 static bool classof(const Symbol *S) {
Reid Kleckner502d4ce2017-06-26 15:39:52240 return S->kind() == DefinedSyntheticKind;
Rui Ueyama3cb895c2015-07-24 22:58:44241 }
242
Reid Kleckner502d4ce2017-06-26 15:39:52243 // A null chunk indicates that this is __ImageBase. Otherwise, this is some
244 // other synthesized chunk, like SEHTableChunk.
Reid Klecknera1001b82017-06-28 17:06:35245 uint32_t getRVA() { return C ? C->getRVA() : 0; }
246 Chunk *getChunk() { return C; }
Rui Ueyama3cb895c2015-07-24 22:58:44247
248private:
Reid Kleckner502d4ce2017-06-26 15:39:52249 Chunk *C;
Rui Ueyama3cb895c2015-07-24 22:58:44250};
251
Rui Ueyama411c63602015-05-28 19:09:30252// This class represents a symbol defined in an archive file. It is
253// created from an archive file header, and it knows how to load an
254// object file from an archive to replace itself with a defined
255// symbol. If the resolver finds both Undefined and Lazy for
256// the same name, it will ask the Lazy to load a file.
Rui Ueyamaf52496e2017-11-03 21:21:47257class Lazy : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30258public:
259 Lazy(ArchiveFile *F, const Archive::Symbol S)
Rui Ueyamaf52496e2017-11-03 21:21:47260 : Symbol(LazyKind, S.getName()), File(F), Sym(S) {}
Rui Ueyama411c63602015-05-28 19:09:30261
Rui Ueyamaf52496e2017-11-03 21:21:47262 static bool classof(const Symbol *S) { return S->kind() == LazyKind; }
Rui Ueyama411c63602015-05-28 19:09:30263
Rui Ueyama411c63602015-05-28 19:09:30264 ArchiveFile *File;
Rui Ueyamaa45d45e2016-12-07 23:17:02265
266private:
Peter Collingbourne79a5e6b2016-12-09 21:55:24267 friend SymbolTable;
268
269private:
Rui Ueyama411c63602015-05-28 19:09:30270 const Archive::Symbol Sym;
271};
272
273// Undefined symbols.
Rui Ueyamaf52496e2017-11-03 21:21:47274class Undefined : public Symbol {
Rui Ueyama411c63602015-05-28 19:09:30275public:
Rui Ueyamaf52496e2017-11-03 21:21:47276 explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {}
Rui Ueyama411c63602015-05-28 19:09:30277
Rui Ueyamaf52496e2017-11-03 21:21:47278 static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }
Rui Ueyama411c63602015-05-28 19:09:30279
280 // An undefined symbol can have a fallback symbol which gives an
281 // undefined symbol a second chance if it would remain undefined.
282 // If it remains undefined, it'll be replaced with whatever the
283 // Alias pointer points to.
Rui Ueyamaf52496e2017-11-03 21:21:47284 Symbol *WeakAlias = nullptr;
Peter Collingbourne2612a322015-07-04 05:28:41285
286 // If this symbol is external weak, try to resolve it to a defined
287 // symbol by searching the chain of fallback symbols. Returns the symbol if
288 // successful, otherwise returns null.
289 Defined *getWeakAlias();
Rui Ueyama411c63602015-05-28 19:09:30290};
291
292// Windows-specific classes.
293
Rui Ueyama7c4fcdd2015-05-29 15:49:09294// This class represents a symbol imported from a DLL. This has two
295// names for internal use and external use. The former is used for
296// name resolution, and the latter is used for the import descriptor
297// table in an output. The former has "__imp_" prefix.
298class DefinedImportData : public Defined {
299public:
Peter Collingbourne79a5e6b2016-12-09 21:55:24300 DefinedImportData(StringRef N, ImportFile *F)
Rui Ueyamab6632d92017-05-22 06:01:37301 : Defined(DefinedImportDataKind, N), File(F) {
302 }
Rui Ueyama7c4fcdd2015-05-29 15:49:09303
Rui Ueyamaf52496e2017-11-03 21:21:47304 static bool classof(const Symbol *S) {
Rui Ueyama7c4fcdd2015-05-29 15:49:09305 return S->kind() == DefinedImportDataKind;
306 }
307
Peter Collingbourne79a5e6b2016-12-09 21:55:24308 uint64_t getRVA() { return File->Location->getRVA(); }
Reid Klecknera1001b82017-06-28 17:06:35309 Chunk *getChunk() { return File->Location; }
310 void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
311
Peter Collingbourne79a5e6b2016-12-09 21:55:24312 StringRef getDLLName() { return File->DLLName; }
313 StringRef getExternalName() { return File->ExternalName; }
Peter Collingbourne79a5e6b2016-12-09 21:55:24314 uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
Rui Ueyama7c4fcdd2015-05-29 15:49:09315
Peter Collingbourne79a5e6b2016-12-09 21:55:24316 ImportFile *File;
Rui Ueyama7c4fcdd2015-05-29 15:49:09317};
318
Rui Ueyama411c63602015-05-28 19:09:30319// This class represents a symbol for a jump table entry which jumps
320// to a function in a DLL. Linker are supposed to create such symbols
321// without "__imp_" prefix for all function symbols exported from
322// DLLs, so that you can call DLL functions as regular functions with
323// a regular name. A function pointer is given as a DefinedImportData.
324class DefinedImportThunk : public Defined {
325public:
Rui Ueyama5e706b32015-07-25 21:54:50326 DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine);
Rui Ueyama411c63602015-05-28 19:09:30327
Rui Ueyamaf52496e2017-11-03 21:21:47328 static bool classof(const Symbol *S) {
Rui Ueyama411c63602015-05-28 19:09:30329 return S->kind() == DefinedImportThunkKind;
330 }
331
Rui Ueyama28df0422015-07-25 01:16:06332 uint64_t getRVA() { return Data->getRVA(); }
Peter Collingbournee50f4852016-12-12 18:42:09333 Chunk *getChunk() { return Data; }
Rui Ueyama411c63602015-05-28 19:09:30334
Rui Ueyama9aa82f72017-05-24 22:30:06335 DefinedImportData *WrappedSym;
336
Rui Ueyama411c63602015-05-28 19:09:30337private:
Peter Collingbournee50f4852016-12-12 18:42:09338 Chunk *Data;
Rui Ueyama411c63602015-05-28 19:09:30339};
340
Martin Storsjod9fd4a02018-08-07 06:42:53341// If you have a symbol "foo" in your object file, a symbol name
342// "__imp_foo" becomes automatically available as a pointer to "foo".
Rui Ueyama88e0f922015-06-25 03:31:47343// This class is for such automatically-created symbols.
344// Yes, this is an odd feature. We didn't intend to implement that.
345// This is here just for compatibility with MSVC.
346class DefinedLocalImport : public Defined {
347public:
348 DefinedLocalImport(StringRef N, Defined *S)
Rui Ueyamab6632d92017-05-22 06:01:37349 : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {}
Rui Ueyama88e0f922015-06-25 03:31:47350
Rui Ueyamaf52496e2017-11-03 21:21:47351 static bool classof(const Symbol *S) {
Rui Ueyama88e0f922015-06-25 03:31:47352 return S->kind() == DefinedLocalImportKind;
353 }
354
Peter Collingbourne79a5e6b2016-12-09 21:55:24355 uint64_t getRVA() { return Data->getRVA(); }
Peter Collingbournee50f4852016-12-12 18:42:09356 Chunk *getChunk() { return Data; }
Rui Ueyama88e0f922015-06-25 03:31:47357
358private:
Peter Collingbournee50f4852016-12-12 18:42:09359 LocalImportChunk *Data;
Rui Ueyama88e0f922015-06-25 03:31:47360};
361
Rui Ueyamacb71c722015-07-13 22:01:27362inline uint64_t Defined::getRVA() {
363 switch (kind()) {
364 case DefinedAbsoluteKind:
365 return cast<DefinedAbsolute>(this)->getRVA();
Reid Kleckner502d4ce2017-06-26 15:39:52366 case DefinedSyntheticKind:
367 return cast<DefinedSynthetic>(this)->getRVA();
Rui Ueyamacb71c722015-07-13 22:01:27368 case DefinedImportDataKind:
369 return cast<DefinedImportData>(this)->getRVA();
370 case DefinedImportThunkKind:
371 return cast<DefinedImportThunk>(this)->getRVA();
372 case DefinedLocalImportKind:
373 return cast<DefinedLocalImport>(this)->getRVA();
374 case DefinedCommonKind:
375 return cast<DefinedCommon>(this)->getRVA();
376 case DefinedRegularKind:
377 return cast<DefinedRegular>(this)->getRVA();
Rui Ueyamacb71c722015-07-13 22:01:27378 case LazyKind:
379 case UndefinedKind:
380 llvm_unreachable("Cannot get the address for an undefined symbol.");
381 }
382 llvm_unreachable("unknown symbol kind");
383}
384
Reid Klecknera1001b82017-06-28 17:06:35385inline Chunk *Defined::getChunk() {
386 switch (kind()) {
387 case DefinedRegularKind:
388 return cast<DefinedRegular>(this)->getChunk();
389 case DefinedAbsoluteKind:
390 return nullptr;
391 case DefinedSyntheticKind:
392 return cast<DefinedSynthetic>(this)->getChunk();
393 case DefinedImportDataKind:
394 return cast<DefinedImportData>(this)->getChunk();
395 case DefinedImportThunkKind:
396 return cast<DefinedImportThunk>(this)->getChunk();
397 case DefinedLocalImportKind:
398 return cast<DefinedLocalImport>(this)->getChunk();
399 case DefinedCommonKind:
400 return cast<DefinedCommon>(this)->getChunk();
401 case LazyKind:
402 case UndefinedKind:
403 llvm_unreachable("Cannot get the chunk of an undefined symbol.");
404 }
405 llvm_unreachable("unknown symbol kind");
406}
407
Rui Ueyamaf52496e2017-11-03 21:21:47408// A buffer class that is large enough to hold any Symbol-derived
Rui Ueyama616cd992017-10-31 16:10:24409// object. We allocate memory using this class and instantiate a symbol
410// using the placement new.
411union SymbolUnion {
Rui Ueyamaf78d0972017-10-31 17:07:47412 alignas(DefinedRegular) char A[sizeof(DefinedRegular)];
413 alignas(DefinedCommon) char B[sizeof(DefinedCommon)];
414 alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)];
415 alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)];
416 alignas(Lazy) char E[sizeof(Lazy)];
417 alignas(Undefined) char F[sizeof(Undefined)];
418 alignas(DefinedImportData) char G[sizeof(DefinedImportData)];
419 alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)];
420 alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)];
Peter Collingbourne79a5e6b2016-12-09 21:55:24421};
422
423template <typename T, typename... ArgT>
Rui Ueyamaf483da02017-11-03 22:48:47424void replaceSymbol(Symbol *S, ArgT &&... Arg) {
Sam Clegg38f52b22018-02-13 17:32:31425 static_assert(std::is_trivially_destructible<T>(),
426 "Symbol types must be trivially destructible");
Rui Ueyama616cd992017-10-31 16:10:24427 static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
428 static_assert(alignof(T) <= alignof(SymbolUnion),
429 "SymbolUnion not aligned enough");
Rui Ueyama38781a52018-02-14 22:43:43430 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
431 "Not a Symbol");
Rui Ueyama616cd992017-10-31 16:10:24432 new (S) T(std::forward<ArgT>(Arg)...);
Peter Collingbourne79a5e6b2016-12-09 21:55:24433}
Rui Ueyama411c63602015-05-28 19:09:30434} // namespace coff
Rui Ueyamace039262017-01-06 10:04:08435
Rui Ueyamaf52496e2017-11-03 21:21:47436std::string toString(coff::Symbol &B);
Rui Ueyama411c63602015-05-28 19:09:30437} // namespace lld
438
Rui Ueyama411c63602015-05-28 19:09:30439#endif