xref: /freebsd/contrib/llvm-project/lld/COFF/Symbols.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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