10b57cec5SDimitry Andric //===- Symbols.h ------------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #ifndef LLD_COFF_SYMBOLS_H
100b57cec5SDimitry Andric #define LLD_COFF_SYMBOLS_H
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric #include "Chunks.h"
130b57cec5SDimitry Andric #include "Config.h"
140b57cec5SDimitry Andric #include "lld/Common/LLVM.h"
150b57cec5SDimitry Andric #include "lld/Common/Memory.h"
160b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
170b57cec5SDimitry Andric #include "llvm/Object/Archive.h"
180b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
190b57cec5SDimitry Andric #include <atomic>
200b57cec5SDimitry Andric #include <memory>
210b57cec5SDimitry Andric #include <vector>
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric namespace lld {
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric namespace coff {
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric using llvm::object::Archive;
280b57cec5SDimitry Andric using llvm::object::COFFSymbolRef;
290b57cec5SDimitry Andric using llvm::object::coff_import_header;
300b57cec5SDimitry Andric using llvm::object::coff_symbol_generic;
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric class ArchiveFile;
33bdd1243dSDimitry Andric class COFFLinkerContext;
340b57cec5SDimitry Andric class InputFile;
350b57cec5SDimitry Andric class ObjFile;
360b57cec5SDimitry Andric class SymbolTable;
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric // The base class for real symbol classes.
390b57cec5SDimitry Andric class Symbol {
400b57cec5SDimitry Andric public:
410b57cec5SDimitry Andric enum Kind {
420b57cec5SDimitry Andric // The order of these is significant. We start with the regular defined
430b57cec5SDimitry Andric // symbols as those are the most prevalent and the zero tag is the cheapest
440b57cec5SDimitry Andric // to set. Among the defined kinds, the lower the kind is preferred over
450b57cec5SDimitry Andric // the higher kind when testing whether one symbol should take precedence
460b57cec5SDimitry Andric // over another.
470b57cec5SDimitry Andric DefinedRegularKind = 0,
480b57cec5SDimitry Andric DefinedCommonKind,
490b57cec5SDimitry Andric DefinedLocalImportKind,
500b57cec5SDimitry Andric DefinedImportThunkKind,
510b57cec5SDimitry Andric DefinedImportDataKind,
520b57cec5SDimitry Andric DefinedAbsoluteKind,
530b57cec5SDimitry Andric DefinedSyntheticKind,
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric UndefinedKind,
5685868e8aSDimitry Andric LazyArchiveKind,
5785868e8aSDimitry Andric LazyObjectKind,
58fe6060f1SDimitry Andric LazyDLLSymbolKind,
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric LastDefinedCOFFKind = DefinedCommonKind,
610b57cec5SDimitry Andric LastDefinedKind = DefinedSyntheticKind,
620b57cec5SDimitry Andric };
630b57cec5SDimitry Andric
kind()640b57cec5SDimitry Andric Kind kind() const { return static_cast<Kind>(symbolKind); }
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric // Returns the symbol name.
getName()675ffd83dbSDimitry Andric StringRef getName() {
685ffd83dbSDimitry Andric // COFF symbol names are read lazily for a performance reason.
695ffd83dbSDimitry Andric // Non-external symbol names are never used by the linker except for logging
705ffd83dbSDimitry Andric // or debugging. Their internal references are resolved not by name but by
715ffd83dbSDimitry Andric // symbol index. And because they are not external, no one can refer them by
725ffd83dbSDimitry Andric // name. Object files contain lots of non-external symbols, and creating
735ffd83dbSDimitry Andric // StringRefs for them (which involves lots of strlen() on the string table)
745ffd83dbSDimitry Andric // is a waste of time.
755ffd83dbSDimitry Andric if (nameData == nullptr)
765ffd83dbSDimitry Andric computeName();
775ffd83dbSDimitry Andric return StringRef(nameData, nameSize);
785ffd83dbSDimitry Andric }
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric void replaceKeepingName(Symbol *other, size_t size);
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric // Returns the file from which this symbol was created.
830b57cec5SDimitry Andric InputFile *getFile();
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric // Indicates that this symbol will be included in the final image. Only valid
860b57cec5SDimitry Andric // after calling markLive.
870b57cec5SDimitry Andric bool isLive() const;
880b57cec5SDimitry Andric
isLazy()8985868e8aSDimitry Andric bool isLazy() const {
90fe6060f1SDimitry Andric return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind ||
91fe6060f1SDimitry Andric symbolKind == LazyDLLSymbolKind;
9285868e8aSDimitry Andric }
9385868e8aSDimitry Andric
945ffd83dbSDimitry Andric private:
955ffd83dbSDimitry Andric void computeName();
965ffd83dbSDimitry Andric
970b57cec5SDimitry Andric protected:
980b57cec5SDimitry Andric friend SymbolTable;
990b57cec5SDimitry Andric explicit Symbol(Kind k, StringRef n = "")
symbolKind(k)1000b57cec5SDimitry Andric : symbolKind(k), isExternal(true), isCOMDAT(false),
101*0fca6ea1SDimitry Andric writtenToSymtab(false), isUsedInRegularObj(false),
102*0fca6ea1SDimitry Andric pendingArchiveLoad(false), isGCRoot(false), isRuntimePseudoReloc(false),
103*0fca6ea1SDimitry Andric deferUndefined(false), canInline(true), isWeak(false),
104*0fca6ea1SDimitry Andric nameSize(n.size()), nameData(n.empty() ? nullptr : n.data()) {
1056246ae0bSDimitry Andric assert((!n.empty() || k <= LastDefinedCOFFKind) &&
1066246ae0bSDimitry Andric "If the name is empty, the Symbol must be a DefinedCOFF.");
1076246ae0bSDimitry Andric }
1080b57cec5SDimitry Andric
109*0fca6ea1SDimitry Andric unsigned symbolKind : 8;
1100b57cec5SDimitry Andric unsigned isExternal : 1;
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric public:
1130b57cec5SDimitry Andric // This bit is used by the \c DefinedRegular subclass.
1140b57cec5SDimitry Andric unsigned isCOMDAT : 1;
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric // This bit is used by Writer::createSymbolAndStringTable() to prevent
1170b57cec5SDimitry Andric // symbols from being written to the symbol table more than once.
1180b57cec5SDimitry Andric unsigned writtenToSymtab : 1;
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric // True if this symbol was referenced by a regular (non-bitcode) object.
1210b57cec5SDimitry Andric unsigned isUsedInRegularObj : 1;
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric // True if we've seen both a lazy and an undefined symbol with this symbol
1240b57cec5SDimitry Andric // name, which means that we have enqueued an archive member load and should
1250b57cec5SDimitry Andric // not load any more archive members to resolve the same symbol.
1260b57cec5SDimitry Andric unsigned pendingArchiveLoad : 1;
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric /// True if we've already added this symbol to the list of GC roots.
1290b57cec5SDimitry Andric unsigned isGCRoot : 1;
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric unsigned isRuntimePseudoReloc : 1;
1320b57cec5SDimitry Andric
133e8d8bef9SDimitry Andric // True if we want to allow this symbol to be undefined in the early
134e8d8bef9SDimitry Andric // undefined check pass in SymbolTable::reportUnresolvable(), as it
135e8d8bef9SDimitry Andric // might be fixed up later.
136e8d8bef9SDimitry Andric unsigned deferUndefined : 1;
137e8d8bef9SDimitry Andric
138e8d8bef9SDimitry Andric // False if LTO shouldn't inline whatever this symbol points to. If a symbol
139e8d8bef9SDimitry Andric // is overwritten after LTO, LTO shouldn't inline the symbol because it
140e8d8bef9SDimitry Andric // doesn't know the final contents of the symbol.
141e8d8bef9SDimitry Andric unsigned canInline : 1;
142e8d8bef9SDimitry Andric
143bdd1243dSDimitry Andric // True if the symbol is weak. This is only tracked for bitcode/LTO symbols.
144bdd1243dSDimitry Andric // This information isn't written to the output; rather, it's used for
145bdd1243dSDimitry Andric // managing weak symbol overrides.
146bdd1243dSDimitry Andric unsigned isWeak : 1;
147bdd1243dSDimitry Andric
1480b57cec5SDimitry Andric protected:
1490b57cec5SDimitry Andric // Symbol name length. Assume symbol lengths fit in a 32-bit integer.
1500b57cec5SDimitry Andric uint32_t nameSize;
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric const char *nameData;
1530b57cec5SDimitry Andric };
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric // The base class for any defined symbols, including absolute symbols,
1560b57cec5SDimitry Andric // etc.
1570b57cec5SDimitry Andric class Defined : public Symbol {
1580b57cec5SDimitry Andric public:
Defined(Kind k,StringRef n)1590b57cec5SDimitry Andric Defined(Kind k, StringRef n) : Symbol(k, n) {}
1600b57cec5SDimitry Andric
classof(const Symbol * s)1610b57cec5SDimitry Andric static bool classof(const Symbol *s) { return s->kind() <= LastDefinedKind; }
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric // Returns the RVA (relative virtual address) of this symbol. The
1640b57cec5SDimitry Andric // writer sets and uses RVAs.
1650b57cec5SDimitry Andric uint64_t getRVA();
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
1680b57cec5SDimitry Andric // do not have chunks, so this may return null.
1690b57cec5SDimitry Andric Chunk *getChunk();
1700b57cec5SDimitry Andric };
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric // Symbols defined via a COFF object file or bitcode file. For COFF files, this
1730b57cec5SDimitry Andric // stores a coff_symbol_generic*, and names of internal symbols are lazily
1740b57cec5SDimitry Andric // loaded through that. For bitcode files, Sym is nullptr and the name is stored
1750b57cec5SDimitry Andric // as a decomposed StringRef.
1760b57cec5SDimitry Andric class DefinedCOFF : public Defined {
1770b57cec5SDimitry Andric friend Symbol;
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric public:
DefinedCOFF(Kind k,InputFile * f,StringRef n,const coff_symbol_generic * s)1800b57cec5SDimitry Andric DefinedCOFF(Kind k, InputFile *f, StringRef n, const coff_symbol_generic *s)
1810b57cec5SDimitry Andric : Defined(k, n), file(f), sym(s) {}
1820b57cec5SDimitry Andric
classof(const Symbol * s)1830b57cec5SDimitry Andric static bool classof(const Symbol *s) {
1840b57cec5SDimitry Andric return s->kind() <= LastDefinedCOFFKind;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
getFile()1870b57cec5SDimitry Andric InputFile *getFile() { return file; }
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric COFFSymbolRef getCOFFSymbol();
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric InputFile *file;
1920b57cec5SDimitry Andric
1930b57cec5SDimitry Andric protected:
1940b57cec5SDimitry Andric const coff_symbol_generic *sym;
1950b57cec5SDimitry Andric };
1960b57cec5SDimitry Andric
1970b57cec5SDimitry Andric // Regular defined symbols read from object file symbol tables.
1980b57cec5SDimitry Andric class DefinedRegular : public DefinedCOFF {
1990b57cec5SDimitry Andric public:
2000b57cec5SDimitry Andric DefinedRegular(InputFile *f, StringRef n, bool isCOMDAT,
2010b57cec5SDimitry Andric bool isExternal = false,
2020b57cec5SDimitry Andric const coff_symbol_generic *s = nullptr,
203bdd1243dSDimitry Andric SectionChunk *c = nullptr, bool isWeak = false)
DefinedCOFF(DefinedRegularKind,f,n,s)2040b57cec5SDimitry Andric : DefinedCOFF(DefinedRegularKind, f, n, s), data(c ? &c->repl : nullptr) {
2050b57cec5SDimitry Andric this->isExternal = isExternal;
2060b57cec5SDimitry Andric this->isCOMDAT = isCOMDAT;
207bdd1243dSDimitry Andric this->isWeak = isWeak;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric
classof(const Symbol * s)2100b57cec5SDimitry Andric static bool classof(const Symbol *s) {
2110b57cec5SDimitry Andric return s->kind() == DefinedRegularKind;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric
getRVA()2140b57cec5SDimitry Andric uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; }
getChunk()2150b57cec5SDimitry Andric SectionChunk *getChunk() const { return *data; }
getValue()2160b57cec5SDimitry Andric uint32_t getValue() const { return sym->Value; }
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andric SectionChunk **data;
2190b57cec5SDimitry Andric };
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric class DefinedCommon : public DefinedCOFF {
2220b57cec5SDimitry Andric public:
2230b57cec5SDimitry Andric DefinedCommon(InputFile *f, StringRef n, uint64_t size,
2240b57cec5SDimitry Andric const coff_symbol_generic *s = nullptr,
2250b57cec5SDimitry Andric CommonChunk *c = nullptr)
DefinedCOFF(DefinedCommonKind,f,n,s)2260b57cec5SDimitry Andric : DefinedCOFF(DefinedCommonKind, f, n, s), data(c), size(size) {
2270b57cec5SDimitry Andric this->isExternal = true;
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric
classof(const Symbol * s)2300b57cec5SDimitry Andric static bool classof(const Symbol *s) {
2310b57cec5SDimitry Andric return s->kind() == DefinedCommonKind;
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric
getRVA()2340b57cec5SDimitry Andric uint64_t getRVA() { return data->getRVA(); }
getChunk()2350b57cec5SDimitry Andric CommonChunk *getChunk() { return data; }
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric private:
2380b57cec5SDimitry Andric friend SymbolTable;
getSize()2390b57cec5SDimitry Andric uint64_t getSize() const { return size; }
2400b57cec5SDimitry Andric CommonChunk *data;
2410b57cec5SDimitry Andric uint64_t size;
2420b57cec5SDimitry Andric };
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric // Absolute symbols.
2450b57cec5SDimitry Andric class DefinedAbsolute : public Defined {
2460b57cec5SDimitry Andric public:
DefinedAbsolute(const COFFLinkerContext & c,StringRef n,COFFSymbolRef s)247bdd1243dSDimitry Andric DefinedAbsolute(const COFFLinkerContext &c, StringRef n, COFFSymbolRef s)
248bdd1243dSDimitry Andric : Defined(DefinedAbsoluteKind, n), va(s.getValue()), ctx(c) {
2490b57cec5SDimitry Andric isExternal = s.isExternal();
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
DefinedAbsolute(const COFFLinkerContext & c,StringRef n,uint64_t v)252bdd1243dSDimitry Andric DefinedAbsolute(const COFFLinkerContext &c, StringRef n, uint64_t v)
253bdd1243dSDimitry Andric : Defined(DefinedAbsoluteKind, n), va(v), ctx(c) {}
2540b57cec5SDimitry Andric
classof(const Symbol * s)2550b57cec5SDimitry Andric static bool classof(const Symbol *s) {
2560b57cec5SDimitry Andric return s->kind() == DefinedAbsoluteKind;
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric
259bdd1243dSDimitry Andric uint64_t getRVA();
setVA(uint64_t v)2600b57cec5SDimitry Andric void setVA(uint64_t v) { va = v; }
getVA()261480093f4SDimitry Andric uint64_t getVA() const { return va; }
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric private:
2640b57cec5SDimitry Andric uint64_t va;
265bdd1243dSDimitry Andric const COFFLinkerContext &ctx;
2660b57cec5SDimitry Andric };
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric // This symbol is used for linker-synthesized symbols like __ImageBase and
2690b57cec5SDimitry Andric // __safe_se_handler_table.
2700b57cec5SDimitry Andric class DefinedSynthetic : public Defined {
2710b57cec5SDimitry Andric public:
2725f757f3fSDimitry Andric explicit DefinedSynthetic(StringRef name, Chunk *c, uint32_t offset = 0)
Defined(DefinedSyntheticKind,name)2735f757f3fSDimitry Andric : Defined(DefinedSyntheticKind, name), c(c), offset(offset) {}
2740b57cec5SDimitry Andric
classof(const Symbol * s)2750b57cec5SDimitry Andric static bool classof(const Symbol *s) {
2760b57cec5SDimitry Andric return s->kind() == DefinedSyntheticKind;
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric
2790b57cec5SDimitry Andric // A null chunk indicates that this is __ImageBase. Otherwise, this is some
2800b57cec5SDimitry Andric // other synthesized chunk, like SEHTableChunk.
getRVA()2815f757f3fSDimitry Andric uint32_t getRVA() { return c ? c->getRVA() + offset : 0; }
getChunk()2820b57cec5SDimitry Andric Chunk *getChunk() { return c; }
2830b57cec5SDimitry Andric
2840b57cec5SDimitry Andric private:
2850b57cec5SDimitry Andric Chunk *c;
2865f757f3fSDimitry Andric uint32_t offset;
2870b57cec5SDimitry Andric };
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric // This class represents a symbol defined in an archive file. It is
2900b57cec5SDimitry Andric // created from an archive file header, and it knows how to load an
2910b57cec5SDimitry Andric // object file from an archive to replace itself with a defined
29285868e8aSDimitry Andric // symbol. If the resolver finds both Undefined and LazyArchive for
29385868e8aSDimitry Andric // the same name, it will ask the LazyArchive to load a file.
29485868e8aSDimitry Andric class LazyArchive : public Symbol {
2950b57cec5SDimitry Andric public:
LazyArchive(ArchiveFile * f,const Archive::Symbol s)29685868e8aSDimitry Andric LazyArchive(ArchiveFile *f, const Archive::Symbol s)
29785868e8aSDimitry Andric : Symbol(LazyArchiveKind, s.getName()), file(f), sym(s) {}
2980b57cec5SDimitry Andric
classof(const Symbol * s)29985868e8aSDimitry Andric static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; }
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric MemoryBufferRef getMemberBuffer();
3020b57cec5SDimitry Andric
3030b57cec5SDimitry Andric ArchiveFile *file;
3040b57cec5SDimitry Andric const Archive::Symbol sym;
3050b57cec5SDimitry Andric };
3060b57cec5SDimitry Andric
30785868e8aSDimitry Andric class LazyObject : public Symbol {
30885868e8aSDimitry Andric public:
LazyObject(InputFile * f,StringRef n)30904eeddc0SDimitry Andric LazyObject(InputFile *f, StringRef n) : Symbol(LazyObjectKind, n), file(f) {}
classof(const Symbol * s)31085868e8aSDimitry Andric static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; }
31104eeddc0SDimitry Andric InputFile *file;
31285868e8aSDimitry Andric };
31385868e8aSDimitry Andric
314fe6060f1SDimitry Andric // MinGW only.
315fe6060f1SDimitry Andric class LazyDLLSymbol : public Symbol {
316fe6060f1SDimitry Andric public:
LazyDLLSymbol(DLLFile * f,DLLFile::Symbol * s,StringRef n)317fe6060f1SDimitry Andric LazyDLLSymbol(DLLFile *f, DLLFile::Symbol *s, StringRef n)
318fe6060f1SDimitry Andric : Symbol(LazyDLLSymbolKind, n), file(f), sym(s) {}
classof(const Symbol * s)319fe6060f1SDimitry Andric static bool classof(const Symbol *s) {
320fe6060f1SDimitry Andric return s->kind() == LazyDLLSymbolKind;
321fe6060f1SDimitry Andric }
322fe6060f1SDimitry Andric
323fe6060f1SDimitry Andric DLLFile *file;
324fe6060f1SDimitry Andric DLLFile::Symbol *sym;
325fe6060f1SDimitry Andric };
326fe6060f1SDimitry Andric
3270b57cec5SDimitry Andric // Undefined symbols.
3280b57cec5SDimitry Andric class Undefined : public Symbol {
3290b57cec5SDimitry Andric public:
Undefined(StringRef n)3300b57cec5SDimitry Andric explicit Undefined(StringRef n) : Symbol(UndefinedKind, n) {}
3310b57cec5SDimitry Andric
classof(const Symbol * s)3320b57cec5SDimitry Andric static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric // An undefined symbol can have a fallback symbol which gives an
3350b57cec5SDimitry Andric // undefined symbol a second chance if it would remain undefined.
3360b57cec5SDimitry Andric // If it remains undefined, it'll be replaced with whatever the
3370b57cec5SDimitry Andric // Alias pointer points to.
3380b57cec5SDimitry Andric Symbol *weakAlias = nullptr;
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric // If this symbol is external weak, try to resolve it to a defined
3410b57cec5SDimitry Andric // symbol by searching the chain of fallback symbols. Returns the symbol if
3420b57cec5SDimitry Andric // successful, otherwise returns null.
3430b57cec5SDimitry Andric Defined *getWeakAlias();
3440b57cec5SDimitry Andric };
3450b57cec5SDimitry Andric
3460b57cec5SDimitry Andric // Windows-specific classes.
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric // This class represents a symbol imported from a DLL. This has two
3490b57cec5SDimitry Andric // names for internal use and external use. The former is used for
3500b57cec5SDimitry Andric // name resolution, and the latter is used for the import descriptor
3510b57cec5SDimitry Andric // table in an output. The former has "__imp_" prefix.
3520b57cec5SDimitry Andric class DefinedImportData : public Defined {
3530b57cec5SDimitry Andric public:
DefinedImportData(StringRef n,ImportFile * f)3540b57cec5SDimitry Andric DefinedImportData(StringRef n, ImportFile *f)
3550b57cec5SDimitry Andric : Defined(DefinedImportDataKind, n), file(f) {
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric
classof(const Symbol * s)3580b57cec5SDimitry Andric static bool classof(const Symbol *s) {
3590b57cec5SDimitry Andric return s->kind() == DefinedImportDataKind;
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric
getRVA()3620b57cec5SDimitry Andric uint64_t getRVA() { return file->location->getRVA(); }
getChunk()3630b57cec5SDimitry Andric Chunk *getChunk() { return file->location; }
setLocation(Chunk * addressTable)3640b57cec5SDimitry Andric void setLocation(Chunk *addressTable) { file->location = addressTable; }
3650b57cec5SDimitry Andric
getDLLName()3660b57cec5SDimitry Andric StringRef getDLLName() { return file->dllName; }
getExternalName()3670b57cec5SDimitry Andric StringRef getExternalName() { return file->externalName; }
getOrdinal()3680b57cec5SDimitry Andric uint16_t getOrdinal() { return file->hdr->OrdinalHint; }
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric ImportFile *file;
371e8d8bef9SDimitry Andric
372e8d8bef9SDimitry Andric // This is a pointer to the synthetic symbol associated with the load thunk
373e8d8bef9SDimitry Andric // for this symbol that will be called if the DLL is delay-loaded. This is
374e8d8bef9SDimitry Andric // needed for Control Flow Guard because if this DefinedImportData symbol is a
375e8d8bef9SDimitry Andric // valid call target, the corresponding load thunk must also be marked as a
376e8d8bef9SDimitry Andric // valid call target.
377e8d8bef9SDimitry Andric DefinedSynthetic *loadThunkSym = nullptr;
3780b57cec5SDimitry Andric };
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric // This class represents a symbol for a jump table entry which jumps
3810b57cec5SDimitry Andric // to a function in a DLL. Linker are supposed to create such symbols
3820b57cec5SDimitry Andric // without "__imp_" prefix for all function symbols exported from
3830b57cec5SDimitry Andric // DLLs, so that you can call DLL functions as regular functions with
3840b57cec5SDimitry Andric // a regular name. A function pointer is given as a DefinedImportData.
3850b57cec5SDimitry Andric class DefinedImportThunk : public Defined {
3860b57cec5SDimitry Andric public:
387bdd1243dSDimitry Andric DefinedImportThunk(COFFLinkerContext &ctx, StringRef name,
388bdd1243dSDimitry Andric DefinedImportData *s, uint16_t machine);
3890b57cec5SDimitry Andric
classof(const Symbol * s)3900b57cec5SDimitry Andric static bool classof(const Symbol *s) {
3910b57cec5SDimitry Andric return s->kind() == DefinedImportThunkKind;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric
getRVA()3940b57cec5SDimitry Andric uint64_t getRVA() { return data->getRVA(); }
getChunk()3950b57cec5SDimitry Andric Chunk *getChunk() { return data; }
3960b57cec5SDimitry Andric
3970b57cec5SDimitry Andric DefinedImportData *wrappedSym;
3980b57cec5SDimitry Andric
3990b57cec5SDimitry Andric private:
4000b57cec5SDimitry Andric Chunk *data;
4010b57cec5SDimitry Andric };
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric // If you have a symbol "foo" in your object file, a symbol name
4040b57cec5SDimitry Andric // "__imp_foo" becomes automatically available as a pointer to "foo".
4050b57cec5SDimitry Andric // This class is for such automatically-created symbols.
4060b57cec5SDimitry Andric // Yes, this is an odd feature. We didn't intend to implement that.
4070b57cec5SDimitry Andric // This is here just for compatibility with MSVC.
4080b57cec5SDimitry Andric class DefinedLocalImport : public Defined {
4090b57cec5SDimitry Andric public:
DefinedLocalImport(COFFLinkerContext & ctx,StringRef n,Defined * s)410bdd1243dSDimitry Andric DefinedLocalImport(COFFLinkerContext &ctx, StringRef n, Defined *s)
411bdd1243dSDimitry Andric : Defined(DefinedLocalImportKind, n),
412bdd1243dSDimitry Andric data(make<LocalImportChunk>(ctx, s)) {}
4130b57cec5SDimitry Andric
classof(const Symbol * s)4140b57cec5SDimitry Andric static bool classof(const Symbol *s) {
4150b57cec5SDimitry Andric return s->kind() == DefinedLocalImportKind;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric
getRVA()4180b57cec5SDimitry Andric uint64_t getRVA() { return data->getRVA(); }
getChunk()4190b57cec5SDimitry Andric Chunk *getChunk() { return data; }
4200b57cec5SDimitry Andric
4210b57cec5SDimitry Andric private:
4220b57cec5SDimitry Andric LocalImportChunk *data;
4230b57cec5SDimitry Andric };
4240b57cec5SDimitry Andric
getRVA()4250b57cec5SDimitry Andric inline uint64_t Defined::getRVA() {
4260b57cec5SDimitry Andric switch (kind()) {
4270b57cec5SDimitry Andric case DefinedAbsoluteKind:
4280b57cec5SDimitry Andric return cast<DefinedAbsolute>(this)->getRVA();
4290b57cec5SDimitry Andric case DefinedSyntheticKind:
4300b57cec5SDimitry Andric return cast<DefinedSynthetic>(this)->getRVA();
4310b57cec5SDimitry Andric case DefinedImportDataKind:
4320b57cec5SDimitry Andric return cast<DefinedImportData>(this)->getRVA();
4330b57cec5SDimitry Andric case DefinedImportThunkKind:
4340b57cec5SDimitry Andric return cast<DefinedImportThunk>(this)->getRVA();
4350b57cec5SDimitry Andric case DefinedLocalImportKind:
4360b57cec5SDimitry Andric return cast<DefinedLocalImport>(this)->getRVA();
4370b57cec5SDimitry Andric case DefinedCommonKind:
4380b57cec5SDimitry Andric return cast<DefinedCommon>(this)->getRVA();
4390b57cec5SDimitry Andric case DefinedRegularKind:
4400b57cec5SDimitry Andric return cast<DefinedRegular>(this)->getRVA();
44185868e8aSDimitry Andric case LazyArchiveKind:
44285868e8aSDimitry Andric case LazyObjectKind:
443fe6060f1SDimitry Andric case LazyDLLSymbolKind:
4440b57cec5SDimitry Andric case UndefinedKind:
4450b57cec5SDimitry Andric llvm_unreachable("Cannot get the address for an undefined symbol.");
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric llvm_unreachable("unknown symbol kind");
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric
getChunk()4500b57cec5SDimitry Andric inline Chunk *Defined::getChunk() {
4510b57cec5SDimitry Andric switch (kind()) {
4520b57cec5SDimitry Andric case DefinedRegularKind:
4530b57cec5SDimitry Andric return cast<DefinedRegular>(this)->getChunk();
4540b57cec5SDimitry Andric case DefinedAbsoluteKind:
4550b57cec5SDimitry Andric return nullptr;
4560b57cec5SDimitry Andric case DefinedSyntheticKind:
4570b57cec5SDimitry Andric return cast<DefinedSynthetic>(this)->getChunk();
4580b57cec5SDimitry Andric case DefinedImportDataKind:
4590b57cec5SDimitry Andric return cast<DefinedImportData>(this)->getChunk();
4600b57cec5SDimitry Andric case DefinedImportThunkKind:
4610b57cec5SDimitry Andric return cast<DefinedImportThunk>(this)->getChunk();
4620b57cec5SDimitry Andric case DefinedLocalImportKind:
4630b57cec5SDimitry Andric return cast<DefinedLocalImport>(this)->getChunk();
4640b57cec5SDimitry Andric case DefinedCommonKind:
4650b57cec5SDimitry Andric return cast<DefinedCommon>(this)->getChunk();
46685868e8aSDimitry Andric case LazyArchiveKind:
46785868e8aSDimitry Andric case LazyObjectKind:
468fe6060f1SDimitry Andric case LazyDLLSymbolKind:
4690b57cec5SDimitry Andric case UndefinedKind:
4700b57cec5SDimitry Andric llvm_unreachable("Cannot get the chunk of an undefined symbol.");
4710b57cec5SDimitry Andric }
4720b57cec5SDimitry Andric llvm_unreachable("unknown symbol kind");
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric // A buffer class that is large enough to hold any Symbol-derived
4760b57cec5SDimitry Andric // object. We allocate memory using this class and instantiate a symbol
4770b57cec5SDimitry Andric // using the placement new.
4780b57cec5SDimitry Andric union SymbolUnion {
4790b57cec5SDimitry Andric alignas(DefinedRegular) char a[sizeof(DefinedRegular)];
4800b57cec5SDimitry Andric alignas(DefinedCommon) char b[sizeof(DefinedCommon)];
4810b57cec5SDimitry Andric alignas(DefinedAbsolute) char c[sizeof(DefinedAbsolute)];
4820b57cec5SDimitry Andric alignas(DefinedSynthetic) char d[sizeof(DefinedSynthetic)];
48385868e8aSDimitry Andric alignas(LazyArchive) char e[sizeof(LazyArchive)];
4840b57cec5SDimitry Andric alignas(Undefined) char f[sizeof(Undefined)];
4850b57cec5SDimitry Andric alignas(DefinedImportData) char g[sizeof(DefinedImportData)];
4860b57cec5SDimitry Andric alignas(DefinedImportThunk) char h[sizeof(DefinedImportThunk)];
4870b57cec5SDimitry Andric alignas(DefinedLocalImport) char i[sizeof(DefinedLocalImport)];
48885868e8aSDimitry Andric alignas(LazyObject) char j[sizeof(LazyObject)];
489fe6060f1SDimitry Andric alignas(LazyDLLSymbol) char k[sizeof(LazyDLLSymbol)];
4900b57cec5SDimitry Andric };
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric template <typename T, typename... ArgT>
replaceSymbol(Symbol * s,ArgT &&...arg)4930b57cec5SDimitry Andric void replaceSymbol(Symbol *s, ArgT &&... arg) {
4940b57cec5SDimitry Andric static_assert(std::is_trivially_destructible<T>(),
4950b57cec5SDimitry Andric "Symbol types must be trivially destructible");
4960b57cec5SDimitry Andric static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
4970b57cec5SDimitry Andric static_assert(alignof(T) <= alignof(SymbolUnion),
4980b57cec5SDimitry Andric "SymbolUnion not aligned enough");
4990b57cec5SDimitry Andric assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
5000b57cec5SDimitry Andric "Not a Symbol");
501e8d8bef9SDimitry Andric bool canInline = s->canInline;
502*0fca6ea1SDimitry Andric bool isUsedInRegularObj = s->isUsedInRegularObj;
5030b57cec5SDimitry Andric new (s) T(std::forward<ArgT>(arg)...);
504e8d8bef9SDimitry Andric s->canInline = canInline;
505*0fca6ea1SDimitry Andric s->isUsedInRegularObj = isUsedInRegularObj;
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric } // namespace coff
5080b57cec5SDimitry Andric
509bdd1243dSDimitry Andric std::string toString(const coff::COFFLinkerContext &ctx, coff::Symbol &b);
510bdd1243dSDimitry Andric std::string toCOFFString(const coff::COFFLinkerContext &ctx,
511bdd1243dSDimitry Andric const llvm::object::Archive::Symbol &b);
512bdd1243dSDimitry Andric
5130b57cec5SDimitry Andric } // namespace lld
5140b57cec5SDimitry Andric
5150b57cec5SDimitry Andric #endif
516