1ece8a530Spatrick //===- Symbols.h ------------------------------------------------*- C++ -*-===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===----------------------------------------------------------------------===//
8ece8a530Spatrick
9ece8a530Spatrick #ifndef LLD_COFF_SYMBOLS_H
10ece8a530Spatrick #define LLD_COFF_SYMBOLS_H
11ece8a530Spatrick
12ece8a530Spatrick #include "Chunks.h"
13ece8a530Spatrick #include "Config.h"
14ece8a530Spatrick #include "lld/Common/LLVM.h"
15ece8a530Spatrick #include "lld/Common/Memory.h"
16ece8a530Spatrick #include "llvm/ADT/ArrayRef.h"
17ece8a530Spatrick #include "llvm/Object/Archive.h"
18ece8a530Spatrick #include "llvm/Object/COFF.h"
19ece8a530Spatrick #include <atomic>
20ece8a530Spatrick #include <memory>
21ece8a530Spatrick #include <vector>
22ece8a530Spatrick
23ece8a530Spatrick namespace lld {
24ece8a530Spatrick
25ece8a530Spatrick namespace coff {
26ece8a530Spatrick
27ece8a530Spatrick using llvm::object::Archive;
28ece8a530Spatrick using llvm::object::COFFSymbolRef;
29ece8a530Spatrick using llvm::object::coff_import_header;
30ece8a530Spatrick using llvm::object::coff_symbol_generic;
31ece8a530Spatrick
32ece8a530Spatrick class ArchiveFile;
33*dfe94b16Srobert class COFFLinkerContext;
34ece8a530Spatrick class InputFile;
35ece8a530Spatrick class ObjFile;
36ece8a530Spatrick class SymbolTable;
37ece8a530Spatrick
38ece8a530Spatrick // The base class for real symbol classes.
39ece8a530Spatrick class Symbol {
40ece8a530Spatrick public:
41ece8a530Spatrick enum Kind {
42ece8a530Spatrick // The order of these is significant. We start with the regular defined
43ece8a530Spatrick // symbols as those are the most prevalent and the zero tag is the cheapest
44ece8a530Spatrick // to set. Among the defined kinds, the lower the kind is preferred over
45ece8a530Spatrick // the higher kind when testing whether one symbol should take precedence
46ece8a530Spatrick // over another.
47ece8a530Spatrick DefinedRegularKind = 0,
48ece8a530Spatrick DefinedCommonKind,
49ece8a530Spatrick DefinedLocalImportKind,
50ece8a530Spatrick DefinedImportThunkKind,
51ece8a530Spatrick DefinedImportDataKind,
52ece8a530Spatrick DefinedAbsoluteKind,
53ece8a530Spatrick DefinedSyntheticKind,
54ece8a530Spatrick
55ece8a530Spatrick UndefinedKind,
56ece8a530Spatrick LazyArchiveKind,
57ece8a530Spatrick LazyObjectKind,
581cf9926bSpatrick LazyDLLSymbolKind,
59ece8a530Spatrick
60ece8a530Spatrick LastDefinedCOFFKind = DefinedCommonKind,
61ece8a530Spatrick LastDefinedKind = DefinedSyntheticKind,
62ece8a530Spatrick };
63ece8a530Spatrick
kind()64ece8a530Spatrick Kind kind() const { return static_cast<Kind>(symbolKind); }
65ece8a530Spatrick
66ece8a530Spatrick // Returns the symbol name.
getName()67bb684c34Spatrick StringRef getName() {
68bb684c34Spatrick // COFF symbol names are read lazily for a performance reason.
69bb684c34Spatrick // Non-external symbol names are never used by the linker except for logging
70bb684c34Spatrick // or debugging. Their internal references are resolved not by name but by
71bb684c34Spatrick // symbol index. And because they are not external, no one can refer them by
72bb684c34Spatrick // name. Object files contain lots of non-external symbols, and creating
73bb684c34Spatrick // StringRefs for them (which involves lots of strlen() on the string table)
74bb684c34Spatrick // is a waste of time.
75bb684c34Spatrick if (nameData == nullptr)
76bb684c34Spatrick computeName();
77bb684c34Spatrick return StringRef(nameData, nameSize);
78bb684c34Spatrick }
79ece8a530Spatrick
80ece8a530Spatrick void replaceKeepingName(Symbol *other, size_t size);
81ece8a530Spatrick
82ece8a530Spatrick // Returns the file from which this symbol was created.
83ece8a530Spatrick InputFile *getFile();
84ece8a530Spatrick
85ece8a530Spatrick // Indicates that this symbol will be included in the final image. Only valid
86ece8a530Spatrick // after calling markLive.
87ece8a530Spatrick bool isLive() const;
88ece8a530Spatrick
isLazy()89ece8a530Spatrick bool isLazy() const {
901cf9926bSpatrick return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind ||
911cf9926bSpatrick symbolKind == LazyDLLSymbolKind;
92ece8a530Spatrick }
93ece8a530Spatrick
94bb684c34Spatrick private:
95bb684c34Spatrick void computeName();
96bb684c34Spatrick
97ece8a530Spatrick protected:
98ece8a530Spatrick friend SymbolTable;
99ece8a530Spatrick explicit Symbol(Kind k, StringRef n = "")
symbolKind(k)100ece8a530Spatrick : symbolKind(k), isExternal(true), isCOMDAT(false),
101ece8a530Spatrick writtenToSymtab(false), pendingArchiveLoad(false), isGCRoot(false),
1021cf9926bSpatrick isRuntimePseudoReloc(false), deferUndefined(false), canInline(true),
103*dfe94b16Srobert isWeak(false), nameSize(n.size()),
104*dfe94b16Srobert nameData(n.empty() ? nullptr : n.data()) {
105*dfe94b16Srobert assert((!n.empty() || k <= LastDefinedCOFFKind) &&
106*dfe94b16Srobert "If the name is empty, the Symbol must be a DefinedCOFF.");
107*dfe94b16Srobert }
108ece8a530Spatrick
109ece8a530Spatrick const unsigned symbolKind : 8;
110ece8a530Spatrick unsigned isExternal : 1;
111ece8a530Spatrick
112ece8a530Spatrick public:
113ece8a530Spatrick // This bit is used by the \c DefinedRegular subclass.
114ece8a530Spatrick unsigned isCOMDAT : 1;
115ece8a530Spatrick
116ece8a530Spatrick // This bit is used by Writer::createSymbolAndStringTable() to prevent
117ece8a530Spatrick // symbols from being written to the symbol table more than once.
118ece8a530Spatrick unsigned writtenToSymtab : 1;
119ece8a530Spatrick
120ece8a530Spatrick // True if this symbol was referenced by a regular (non-bitcode) object.
121ece8a530Spatrick unsigned isUsedInRegularObj : 1;
122ece8a530Spatrick
123ece8a530Spatrick // True if we've seen both a lazy and an undefined symbol with this symbol
124ece8a530Spatrick // name, which means that we have enqueued an archive member load and should
125ece8a530Spatrick // not load any more archive members to resolve the same symbol.
126ece8a530Spatrick unsigned pendingArchiveLoad : 1;
127ece8a530Spatrick
128ece8a530Spatrick /// True if we've already added this symbol to the list of GC roots.
129ece8a530Spatrick unsigned isGCRoot : 1;
130ece8a530Spatrick
131ece8a530Spatrick unsigned isRuntimePseudoReloc : 1;
132ece8a530Spatrick
1331cf9926bSpatrick // True if we want to allow this symbol to be undefined in the early
1341cf9926bSpatrick // undefined check pass in SymbolTable::reportUnresolvable(), as it
1351cf9926bSpatrick // might be fixed up later.
1361cf9926bSpatrick unsigned deferUndefined : 1;
1371cf9926bSpatrick
1381cf9926bSpatrick // False if LTO shouldn't inline whatever this symbol points to. If a symbol
1391cf9926bSpatrick // is overwritten after LTO, LTO shouldn't inline the symbol because it
1401cf9926bSpatrick // doesn't know the final contents of the symbol.
1411cf9926bSpatrick unsigned canInline : 1;
1421cf9926bSpatrick
143*dfe94b16Srobert // True if the symbol is weak. This is only tracked for bitcode/LTO symbols.
144*dfe94b16Srobert // This information isn't written to the output; rather, it's used for
145*dfe94b16Srobert // managing weak symbol overrides.
146*dfe94b16Srobert unsigned isWeak : 1;
147*dfe94b16Srobert
148ece8a530Spatrick protected:
149ece8a530Spatrick // Symbol name length. Assume symbol lengths fit in a 32-bit integer.
150ece8a530Spatrick uint32_t nameSize;
151ece8a530Spatrick
152ece8a530Spatrick const char *nameData;
153ece8a530Spatrick };
154ece8a530Spatrick
155ece8a530Spatrick // The base class for any defined symbols, including absolute symbols,
156ece8a530Spatrick // etc.
157ece8a530Spatrick class Defined : public Symbol {
158ece8a530Spatrick public:
Defined(Kind k,StringRef n)159ece8a530Spatrick Defined(Kind k, StringRef n) : Symbol(k, n) {}
160ece8a530Spatrick
classof(const Symbol * s)161ece8a530Spatrick static bool classof(const Symbol *s) { return s->kind() <= LastDefinedKind; }
162ece8a530Spatrick
163ece8a530Spatrick // Returns the RVA (relative virtual address) of this symbol. The
164ece8a530Spatrick // writer sets and uses RVAs.
165ece8a530Spatrick uint64_t getRVA();
166ece8a530Spatrick
167ece8a530Spatrick // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
168ece8a530Spatrick // do not have chunks, so this may return null.
169ece8a530Spatrick Chunk *getChunk();
170ece8a530Spatrick };
171ece8a530Spatrick
172ece8a530Spatrick // Symbols defined via a COFF object file or bitcode file. For COFF files, this
173ece8a530Spatrick // stores a coff_symbol_generic*, and names of internal symbols are lazily
174ece8a530Spatrick // loaded through that. For bitcode files, Sym is nullptr and the name is stored
175ece8a530Spatrick // as a decomposed StringRef.
176ece8a530Spatrick class DefinedCOFF : public Defined {
177ece8a530Spatrick friend Symbol;
178ece8a530Spatrick
179ece8a530Spatrick public:
DefinedCOFF(Kind k,InputFile * f,StringRef n,const coff_symbol_generic * s)180ece8a530Spatrick DefinedCOFF(Kind k, InputFile *f, StringRef n, const coff_symbol_generic *s)
181ece8a530Spatrick : Defined(k, n), file(f), sym(s) {}
182ece8a530Spatrick
classof(const Symbol * s)183ece8a530Spatrick static bool classof(const Symbol *s) {
184ece8a530Spatrick return s->kind() <= LastDefinedCOFFKind;
185ece8a530Spatrick }
186ece8a530Spatrick
getFile()187ece8a530Spatrick InputFile *getFile() { return file; }
188ece8a530Spatrick
189ece8a530Spatrick COFFSymbolRef getCOFFSymbol();
190ece8a530Spatrick
191ece8a530Spatrick InputFile *file;
192ece8a530Spatrick
193ece8a530Spatrick protected:
194ece8a530Spatrick const coff_symbol_generic *sym;
195ece8a530Spatrick };
196ece8a530Spatrick
197ece8a530Spatrick // Regular defined symbols read from object file symbol tables.
198ece8a530Spatrick class DefinedRegular : public DefinedCOFF {
199ece8a530Spatrick public:
200ece8a530Spatrick DefinedRegular(InputFile *f, StringRef n, bool isCOMDAT,
201ece8a530Spatrick bool isExternal = false,
202ece8a530Spatrick const coff_symbol_generic *s = nullptr,
203*dfe94b16Srobert SectionChunk *c = nullptr, bool isWeak = false)
DefinedCOFF(DefinedRegularKind,f,n,s)204ece8a530Spatrick : DefinedCOFF(DefinedRegularKind, f, n, s), data(c ? &c->repl : nullptr) {
205ece8a530Spatrick this->isExternal = isExternal;
206ece8a530Spatrick this->isCOMDAT = isCOMDAT;
207*dfe94b16Srobert this->isWeak = isWeak;
208ece8a530Spatrick }
209ece8a530Spatrick
classof(const Symbol * s)210ece8a530Spatrick static bool classof(const Symbol *s) {
211ece8a530Spatrick return s->kind() == DefinedRegularKind;
212ece8a530Spatrick }
213ece8a530Spatrick
getRVA()214ece8a530Spatrick uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; }
getChunk()215ece8a530Spatrick SectionChunk *getChunk() const { return *data; }
getValue()216ece8a530Spatrick uint32_t getValue() const { return sym->Value; }
217ece8a530Spatrick
218ece8a530Spatrick SectionChunk **data;
219ece8a530Spatrick };
220ece8a530Spatrick
221ece8a530Spatrick class DefinedCommon : public DefinedCOFF {
222ece8a530Spatrick public:
223ece8a530Spatrick DefinedCommon(InputFile *f, StringRef n, uint64_t size,
224ece8a530Spatrick const coff_symbol_generic *s = nullptr,
225ece8a530Spatrick CommonChunk *c = nullptr)
DefinedCOFF(DefinedCommonKind,f,n,s)226ece8a530Spatrick : DefinedCOFF(DefinedCommonKind, f, n, s), data(c), size(size) {
227ece8a530Spatrick this->isExternal = true;
228ece8a530Spatrick }
229ece8a530Spatrick
classof(const Symbol * s)230ece8a530Spatrick static bool classof(const Symbol *s) {
231ece8a530Spatrick return s->kind() == DefinedCommonKind;
232ece8a530Spatrick }
233ece8a530Spatrick
getRVA()234ece8a530Spatrick uint64_t getRVA() { return data->getRVA(); }
getChunk()235ece8a530Spatrick CommonChunk *getChunk() { return data; }
236ece8a530Spatrick
237ece8a530Spatrick private:
238ece8a530Spatrick friend SymbolTable;
getSize()239ece8a530Spatrick uint64_t getSize() const { return size; }
240ece8a530Spatrick CommonChunk *data;
241ece8a530Spatrick uint64_t size;
242ece8a530Spatrick };
243ece8a530Spatrick
244ece8a530Spatrick // Absolute symbols.
245ece8a530Spatrick class DefinedAbsolute : public Defined {
246ece8a530Spatrick public:
DefinedAbsolute(const COFFLinkerContext & c,StringRef n,COFFSymbolRef s)247*dfe94b16Srobert DefinedAbsolute(const COFFLinkerContext &c, StringRef n, COFFSymbolRef s)
248*dfe94b16Srobert : Defined(DefinedAbsoluteKind, n), va(s.getValue()), ctx(c) {
249ece8a530Spatrick isExternal = s.isExternal();
250ece8a530Spatrick }
251ece8a530Spatrick
DefinedAbsolute(const COFFLinkerContext & c,StringRef n,uint64_t v)252*dfe94b16Srobert DefinedAbsolute(const COFFLinkerContext &c, StringRef n, uint64_t v)
253*dfe94b16Srobert : Defined(DefinedAbsoluteKind, n), va(v), ctx(c) {}
254ece8a530Spatrick
classof(const Symbol * s)255ece8a530Spatrick static bool classof(const Symbol *s) {
256ece8a530Spatrick return s->kind() == DefinedAbsoluteKind;
257ece8a530Spatrick }
258ece8a530Spatrick
259*dfe94b16Srobert uint64_t getRVA();
setVA(uint64_t v)260ece8a530Spatrick void setVA(uint64_t v) { va = v; }
getVA()261ece8a530Spatrick uint64_t getVA() const { return va; }
262ece8a530Spatrick
263ece8a530Spatrick private:
264ece8a530Spatrick uint64_t va;
265*dfe94b16Srobert const COFFLinkerContext &ctx;
266ece8a530Spatrick };
267ece8a530Spatrick
268ece8a530Spatrick // This symbol is used for linker-synthesized symbols like __ImageBase and
269ece8a530Spatrick // __safe_se_handler_table.
270ece8a530Spatrick class DefinedSynthetic : public Defined {
271ece8a530Spatrick public:
DefinedSynthetic(StringRef name,Chunk * c)272ece8a530Spatrick explicit DefinedSynthetic(StringRef name, Chunk *c)
273ece8a530Spatrick : Defined(DefinedSyntheticKind, name), c(c) {}
274ece8a530Spatrick
classof(const Symbol * s)275ece8a530Spatrick static bool classof(const Symbol *s) {
276ece8a530Spatrick return s->kind() == DefinedSyntheticKind;
277ece8a530Spatrick }
278ece8a530Spatrick
279ece8a530Spatrick // A null chunk indicates that this is __ImageBase. Otherwise, this is some
280ece8a530Spatrick // other synthesized chunk, like SEHTableChunk.
getRVA()281ece8a530Spatrick uint32_t getRVA() { return c ? c->getRVA() : 0; }
getChunk()282ece8a530Spatrick Chunk *getChunk() { return c; }
283ece8a530Spatrick
284ece8a530Spatrick private:
285ece8a530Spatrick Chunk *c;
286ece8a530Spatrick };
287ece8a530Spatrick
288ece8a530Spatrick // This class represents a symbol defined in an archive file. It is
289ece8a530Spatrick // created from an archive file header, and it knows how to load an
290ece8a530Spatrick // object file from an archive to replace itself with a defined
291ece8a530Spatrick // symbol. If the resolver finds both Undefined and LazyArchive for
292ece8a530Spatrick // the same name, it will ask the LazyArchive to load a file.
293ece8a530Spatrick class LazyArchive : public Symbol {
294ece8a530Spatrick public:
LazyArchive(ArchiveFile * f,const Archive::Symbol s)295ece8a530Spatrick LazyArchive(ArchiveFile *f, const Archive::Symbol s)
296ece8a530Spatrick : Symbol(LazyArchiveKind, s.getName()), file(f), sym(s) {}
297ece8a530Spatrick
classof(const Symbol * s)298ece8a530Spatrick static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; }
299ece8a530Spatrick
300ece8a530Spatrick MemoryBufferRef getMemberBuffer();
301ece8a530Spatrick
302ece8a530Spatrick ArchiveFile *file;
303ece8a530Spatrick const Archive::Symbol sym;
304ece8a530Spatrick };
305ece8a530Spatrick
306ece8a530Spatrick class LazyObject : public Symbol {
307ece8a530Spatrick public:
LazyObject(InputFile * f,StringRef n)308*dfe94b16Srobert LazyObject(InputFile *f, StringRef n) : Symbol(LazyObjectKind, n), file(f) {}
classof(const Symbol * s)309ece8a530Spatrick static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; }
310*dfe94b16Srobert InputFile *file;
311ece8a530Spatrick };
312ece8a530Spatrick
3131cf9926bSpatrick // MinGW only.
3141cf9926bSpatrick class LazyDLLSymbol : public Symbol {
3151cf9926bSpatrick public:
LazyDLLSymbol(DLLFile * f,DLLFile::Symbol * s,StringRef n)3161cf9926bSpatrick LazyDLLSymbol(DLLFile *f, DLLFile::Symbol *s, StringRef n)
3171cf9926bSpatrick : Symbol(LazyDLLSymbolKind, n), file(f), sym(s) {}
classof(const Symbol * s)3181cf9926bSpatrick static bool classof(const Symbol *s) {
3191cf9926bSpatrick return s->kind() == LazyDLLSymbolKind;
3201cf9926bSpatrick }
3211cf9926bSpatrick
3221cf9926bSpatrick DLLFile *file;
3231cf9926bSpatrick DLLFile::Symbol *sym;
3241cf9926bSpatrick };
3251cf9926bSpatrick
326ece8a530Spatrick // Undefined symbols.
327ece8a530Spatrick class Undefined : public Symbol {
328ece8a530Spatrick public:
Undefined(StringRef n)329ece8a530Spatrick explicit Undefined(StringRef n) : Symbol(UndefinedKind, n) {}
330ece8a530Spatrick
classof(const Symbol * s)331ece8a530Spatrick static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
332ece8a530Spatrick
333ece8a530Spatrick // An undefined symbol can have a fallback symbol which gives an
334ece8a530Spatrick // undefined symbol a second chance if it would remain undefined.
335ece8a530Spatrick // If it remains undefined, it'll be replaced with whatever the
336ece8a530Spatrick // Alias pointer points to.
337ece8a530Spatrick Symbol *weakAlias = nullptr;
338ece8a530Spatrick
339ece8a530Spatrick // If this symbol is external weak, try to resolve it to a defined
340ece8a530Spatrick // symbol by searching the chain of fallback symbols. Returns the symbol if
341ece8a530Spatrick // successful, otherwise returns null.
342ece8a530Spatrick Defined *getWeakAlias();
343ece8a530Spatrick };
344ece8a530Spatrick
345ece8a530Spatrick // Windows-specific classes.
346ece8a530Spatrick
347ece8a530Spatrick // This class represents a symbol imported from a DLL. This has two
348ece8a530Spatrick // names for internal use and external use. The former is used for
349ece8a530Spatrick // name resolution, and the latter is used for the import descriptor
350ece8a530Spatrick // table in an output. The former has "__imp_" prefix.
351ece8a530Spatrick class DefinedImportData : public Defined {
352ece8a530Spatrick public:
DefinedImportData(StringRef n,ImportFile * f)353ece8a530Spatrick DefinedImportData(StringRef n, ImportFile *f)
354ece8a530Spatrick : Defined(DefinedImportDataKind, n), file(f) {
355ece8a530Spatrick }
356ece8a530Spatrick
classof(const Symbol * s)357ece8a530Spatrick static bool classof(const Symbol *s) {
358ece8a530Spatrick return s->kind() == DefinedImportDataKind;
359ece8a530Spatrick }
360ece8a530Spatrick
getRVA()361ece8a530Spatrick uint64_t getRVA() { return file->location->getRVA(); }
getChunk()362ece8a530Spatrick Chunk *getChunk() { return file->location; }
setLocation(Chunk * addressTable)363ece8a530Spatrick void setLocation(Chunk *addressTable) { file->location = addressTable; }
364ece8a530Spatrick
getDLLName()365ece8a530Spatrick StringRef getDLLName() { return file->dllName; }
getExternalName()366ece8a530Spatrick StringRef getExternalName() { return file->externalName; }
getOrdinal()367ece8a530Spatrick uint16_t getOrdinal() { return file->hdr->OrdinalHint; }
368ece8a530Spatrick
369ece8a530Spatrick ImportFile *file;
3701cf9926bSpatrick
3711cf9926bSpatrick // This is a pointer to the synthetic symbol associated with the load thunk
3721cf9926bSpatrick // for this symbol that will be called if the DLL is delay-loaded. This is
3731cf9926bSpatrick // needed for Control Flow Guard because if this DefinedImportData symbol is a
3741cf9926bSpatrick // valid call target, the corresponding load thunk must also be marked as a
3751cf9926bSpatrick // valid call target.
3761cf9926bSpatrick DefinedSynthetic *loadThunkSym = nullptr;
377ece8a530Spatrick };
378ece8a530Spatrick
379ece8a530Spatrick // This class represents a symbol for a jump table entry which jumps
380ece8a530Spatrick // to a function in a DLL. Linker are supposed to create such symbols
381ece8a530Spatrick // without "__imp_" prefix for all function symbols exported from
382ece8a530Spatrick // DLLs, so that you can call DLL functions as regular functions with
383ece8a530Spatrick // a regular name. A function pointer is given as a DefinedImportData.
384ece8a530Spatrick class DefinedImportThunk : public Defined {
385ece8a530Spatrick public:
386*dfe94b16Srobert DefinedImportThunk(COFFLinkerContext &ctx, StringRef name,
387*dfe94b16Srobert DefinedImportData *s, uint16_t machine);
388ece8a530Spatrick
classof(const Symbol * s)389ece8a530Spatrick static bool classof(const Symbol *s) {
390ece8a530Spatrick return s->kind() == DefinedImportThunkKind;
391ece8a530Spatrick }
392ece8a530Spatrick
getRVA()393ece8a530Spatrick uint64_t getRVA() { return data->getRVA(); }
getChunk()394ece8a530Spatrick Chunk *getChunk() { return data; }
395ece8a530Spatrick
396ece8a530Spatrick DefinedImportData *wrappedSym;
397ece8a530Spatrick
398ece8a530Spatrick private:
399ece8a530Spatrick Chunk *data;
400ece8a530Spatrick };
401ece8a530Spatrick
402ece8a530Spatrick // If you have a symbol "foo" in your object file, a symbol name
403ece8a530Spatrick // "__imp_foo" becomes automatically available as a pointer to "foo".
404ece8a530Spatrick // This class is for such automatically-created symbols.
405ece8a530Spatrick // Yes, this is an odd feature. We didn't intend to implement that.
406ece8a530Spatrick // This is here just for compatibility with MSVC.
407ece8a530Spatrick class DefinedLocalImport : public Defined {
408ece8a530Spatrick public:
DefinedLocalImport(COFFLinkerContext & ctx,StringRef n,Defined * s)409*dfe94b16Srobert DefinedLocalImport(COFFLinkerContext &ctx, StringRef n, Defined *s)
410*dfe94b16Srobert : Defined(DefinedLocalImportKind, n),
411*dfe94b16Srobert data(make<LocalImportChunk>(ctx, s)) {}
412ece8a530Spatrick
classof(const Symbol * s)413ece8a530Spatrick static bool classof(const Symbol *s) {
414ece8a530Spatrick return s->kind() == DefinedLocalImportKind;
415ece8a530Spatrick }
416ece8a530Spatrick
getRVA()417ece8a530Spatrick uint64_t getRVA() { return data->getRVA(); }
getChunk()418ece8a530Spatrick Chunk *getChunk() { return data; }
419ece8a530Spatrick
420ece8a530Spatrick private:
421ece8a530Spatrick LocalImportChunk *data;
422ece8a530Spatrick };
423ece8a530Spatrick
getRVA()424ece8a530Spatrick inline uint64_t Defined::getRVA() {
425ece8a530Spatrick switch (kind()) {
426ece8a530Spatrick case DefinedAbsoluteKind:
427ece8a530Spatrick return cast<DefinedAbsolute>(this)->getRVA();
428ece8a530Spatrick case DefinedSyntheticKind:
429ece8a530Spatrick return cast<DefinedSynthetic>(this)->getRVA();
430ece8a530Spatrick case DefinedImportDataKind:
431ece8a530Spatrick return cast<DefinedImportData>(this)->getRVA();
432ece8a530Spatrick case DefinedImportThunkKind:
433ece8a530Spatrick return cast<DefinedImportThunk>(this)->getRVA();
434ece8a530Spatrick case DefinedLocalImportKind:
435ece8a530Spatrick return cast<DefinedLocalImport>(this)->getRVA();
436ece8a530Spatrick case DefinedCommonKind:
437ece8a530Spatrick return cast<DefinedCommon>(this)->getRVA();
438ece8a530Spatrick case DefinedRegularKind:
439ece8a530Spatrick return cast<DefinedRegular>(this)->getRVA();
440ece8a530Spatrick case LazyArchiveKind:
441ece8a530Spatrick case LazyObjectKind:
4421cf9926bSpatrick case LazyDLLSymbolKind:
443ece8a530Spatrick case UndefinedKind:
444ece8a530Spatrick llvm_unreachable("Cannot get the address for an undefined symbol.");
445ece8a530Spatrick }
446ece8a530Spatrick llvm_unreachable("unknown symbol kind");
447ece8a530Spatrick }
448ece8a530Spatrick
getChunk()449ece8a530Spatrick inline Chunk *Defined::getChunk() {
450ece8a530Spatrick switch (kind()) {
451ece8a530Spatrick case DefinedRegularKind:
452ece8a530Spatrick return cast<DefinedRegular>(this)->getChunk();
453ece8a530Spatrick case DefinedAbsoluteKind:
454ece8a530Spatrick return nullptr;
455ece8a530Spatrick case DefinedSyntheticKind:
456ece8a530Spatrick return cast<DefinedSynthetic>(this)->getChunk();
457ece8a530Spatrick case DefinedImportDataKind:
458ece8a530Spatrick return cast<DefinedImportData>(this)->getChunk();
459ece8a530Spatrick case DefinedImportThunkKind:
460ece8a530Spatrick return cast<DefinedImportThunk>(this)->getChunk();
461ece8a530Spatrick case DefinedLocalImportKind:
462ece8a530Spatrick return cast<DefinedLocalImport>(this)->getChunk();
463ece8a530Spatrick case DefinedCommonKind:
464ece8a530Spatrick return cast<DefinedCommon>(this)->getChunk();
465ece8a530Spatrick case LazyArchiveKind:
466ece8a530Spatrick case LazyObjectKind:
4671cf9926bSpatrick case LazyDLLSymbolKind:
468ece8a530Spatrick case UndefinedKind:
469ece8a530Spatrick llvm_unreachable("Cannot get the chunk of an undefined symbol.");
470ece8a530Spatrick }
471ece8a530Spatrick llvm_unreachable("unknown symbol kind");
472ece8a530Spatrick }
473ece8a530Spatrick
474ece8a530Spatrick // A buffer class that is large enough to hold any Symbol-derived
475ece8a530Spatrick // object. We allocate memory using this class and instantiate a symbol
476ece8a530Spatrick // using the placement new.
477ece8a530Spatrick union SymbolUnion {
478ece8a530Spatrick alignas(DefinedRegular) char a[sizeof(DefinedRegular)];
479ece8a530Spatrick alignas(DefinedCommon) char b[sizeof(DefinedCommon)];
480ece8a530Spatrick alignas(DefinedAbsolute) char c[sizeof(DefinedAbsolute)];
481ece8a530Spatrick alignas(DefinedSynthetic) char d[sizeof(DefinedSynthetic)];
482ece8a530Spatrick alignas(LazyArchive) char e[sizeof(LazyArchive)];
483ece8a530Spatrick alignas(Undefined) char f[sizeof(Undefined)];
484ece8a530Spatrick alignas(DefinedImportData) char g[sizeof(DefinedImportData)];
485ece8a530Spatrick alignas(DefinedImportThunk) char h[sizeof(DefinedImportThunk)];
486ece8a530Spatrick alignas(DefinedLocalImport) char i[sizeof(DefinedLocalImport)];
487ece8a530Spatrick alignas(LazyObject) char j[sizeof(LazyObject)];
4881cf9926bSpatrick alignas(LazyDLLSymbol) char k[sizeof(LazyDLLSymbol)];
489ece8a530Spatrick };
490ece8a530Spatrick
491ece8a530Spatrick template <typename T, typename... ArgT>
replaceSymbol(Symbol * s,ArgT &&...arg)492ece8a530Spatrick void replaceSymbol(Symbol *s, ArgT &&... arg) {
493ece8a530Spatrick static_assert(std::is_trivially_destructible<T>(),
494ece8a530Spatrick "Symbol types must be trivially destructible");
495ece8a530Spatrick static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
496ece8a530Spatrick static_assert(alignof(T) <= alignof(SymbolUnion),
497ece8a530Spatrick "SymbolUnion not aligned enough");
498ece8a530Spatrick assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
499ece8a530Spatrick "Not a Symbol");
5001cf9926bSpatrick bool canInline = s->canInline;
501ece8a530Spatrick new (s) T(std::forward<ArgT>(arg)...);
5021cf9926bSpatrick s->canInline = canInline;
503ece8a530Spatrick }
504ece8a530Spatrick } // namespace coff
505ece8a530Spatrick
506*dfe94b16Srobert std::string toString(const coff::COFFLinkerContext &ctx, coff::Symbol &b);
507*dfe94b16Srobert std::string toCOFFString(const coff::COFFLinkerContext &ctx,
508*dfe94b16Srobert const llvm::object::Archive::Symbol &b);
509*dfe94b16Srobert
510ece8a530Spatrick } // namespace lld
511ece8a530Spatrick
512ece8a530Spatrick #endif
513