diff options
Diffstat (limited to 'COFF/Symbols.h')
-rw-r--r-- | COFF/Symbols.h | 146 |
1 files changed, 67 insertions, 79 deletions
diff --git a/COFF/Symbols.h b/COFF/Symbols.h index a12ae1c01e07e..d8a030705e271 100644 --- a/COFF/Symbols.h +++ b/COFF/Symbols.h @@ -12,8 +12,8 @@ #include "Chunks.h" #include "Config.h" -#include "Memory.h" -#include "lld/Core/LLVM.h" +#include "lld/Common/LLVM.h" +#include "lld/Common/Memory.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" @@ -31,12 +31,11 @@ using llvm::object::coff_symbol_generic; class ArchiveFile; class InputFile; -class ObjectFile; -struct Symbol; +class ObjFile; class SymbolTable; // The base class for real symbol classes. -class SymbolBody { +class Symbol { public: enum Kind { // The order of these is significant. We start with the regular defined @@ -70,16 +69,16 @@ public: // Returns the file from which this symbol was created. InputFile *getFile(); - Symbol *symbol(); - const Symbol *symbol() const { - return const_cast<SymbolBody *>(this)->symbol(); - } + // Indicates that this symbol will be included in the final image. Only valid + // after calling markLive. + bool isLive() const; protected: friend SymbolTable; - explicit SymbolBody(Kind K, StringRef N = "") + explicit Symbol(Kind K, StringRef N = "") : SymbolKind(K), IsExternal(true), IsCOMDAT(false), - WrittenToSymtab(false), Name(N) {} + WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false), + Name(N) {} const unsigned SymbolKind : 8; unsigned IsExternal : 1; @@ -92,19 +91,28 @@ public: // symbols from being written to the symbol table more than once. unsigned WrittenToSymtab : 1; + // True if this symbol was referenced by a regular (non-bitcode) object. + unsigned IsUsedInRegularObj : 1; + + // True if we've seen both a lazy and an undefined symbol with this symbol + // name, which means that we have enqueued an archive member load and should + // not load any more archive members to resolve the same symbol. + unsigned PendingArchiveLoad : 1; + + /// True if we've already added this symbol to the list of GC roots. + unsigned IsGCRoot : 1; + protected: StringRef Name; }; // The base class for any defined symbols, including absolute symbols, // etc. -class Defined : public SymbolBody { +class Defined : public Symbol { public: - Defined(Kind K, StringRef N) : SymbolBody(K, N) {} + Defined(Kind K, StringRef N) : Symbol(K, N) {} - static bool classof(const SymbolBody *S) { - return S->kind() <= LastDefinedKind; - } + static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; } // Returns the RVA (relative virtual address) of this symbol. The // writer sets and uses RVAs. @@ -120,12 +128,13 @@ public: // loaded through that. For bitcode files, Sym is nullptr and the name is stored // as a StringRef. class DefinedCOFF : public Defined { - friend SymbolBody; + friend Symbol; + public: DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S) : Defined(K, N), File(F), Sym(S) {} - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() <= LastDefinedCOFFKind; } @@ -151,16 +160,15 @@ public: this->IsCOMDAT = IsCOMDAT; } - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() == DefinedRegularKind; } - uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; } - bool isCOMDAT() { return IsCOMDAT; } - SectionChunk *getChunk() { return *Data; } - uint32_t getValue() { return Sym->Value; } + uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; } + bool isCOMDAT() const { return IsCOMDAT; } + SectionChunk *getChunk() const { return *Data; } + uint32_t getValue() const { return Sym->Value; } -private: SectionChunk **Data; }; @@ -173,12 +181,12 @@ public: this->IsExternal = true; } - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() == DefinedCommonKind; } uint64_t getRVA() { return Data->getRVA(); } - Chunk *getChunk() { return Data; } + CommonChunk *getChunk() { return Data; } private: friend SymbolTable; @@ -198,7 +206,7 @@ public: DefinedAbsolute(StringRef N, uint64_t V) : Defined(DefinedAbsoluteKind, N), VA(V) {} - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() == DefinedAbsoluteKind; } @@ -222,7 +230,7 @@ public: explicit DefinedSynthetic(StringRef Name, Chunk *C) : Defined(DefinedSyntheticKind, Name), C(C) {} - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() == DefinedSyntheticKind; } @@ -240,12 +248,12 @@ private: // object file from an archive to replace itself with a defined // symbol. If the resolver finds both Undefined and Lazy for // the same name, it will ask the Lazy to load a file. -class Lazy : public SymbolBody { +class Lazy : public Symbol { public: Lazy(ArchiveFile *F, const Archive::Symbol S) - : SymbolBody(LazyKind, S.getName()), File(F), Sym(S) {} + : Symbol(LazyKind, S.getName()), File(F), Sym(S) {} - static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; } + static bool classof(const Symbol *S) { return S->kind() == LazyKind; } ArchiveFile *File; @@ -257,19 +265,17 @@ private: }; // Undefined symbols. -class Undefined : public SymbolBody { +class Undefined : public Symbol { public: - explicit Undefined(StringRef N) : SymbolBody(UndefinedKind, N) {} + explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {} - static bool classof(const SymbolBody *S) { - return S->kind() == UndefinedKind; - } + static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; } // An undefined symbol can have a fallback symbol which gives an // undefined symbol a second chance if it would remain undefined. // If it remains undefined, it'll be replaced with whatever the // Alias pointer points to. - SymbolBody *WeakAlias = nullptr; + Symbol *WeakAlias = nullptr; // If this symbol is external weak, try to resolve it to a defined // symbol by searching the chain of fallback symbols. Returns the symbol if @@ -289,7 +295,7 @@ public: : Defined(DefinedImportDataKind, N), File(F) { } - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() == DefinedImportDataKind; } @@ -313,7 +319,7 @@ class DefinedImportThunk : public Defined { public: DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine); - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() == DefinedImportThunkKind; } @@ -336,7 +342,7 @@ public: DefinedLocalImport(StringRef N, Defined *S) : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {} - static bool classof(const SymbolBody *S) { + static bool classof(const Symbol *S) { return S->kind() == DefinedLocalImportKind; } @@ -393,51 +399,33 @@ inline Chunk *Defined::getChunk() { llvm_unreachable("unknown symbol kind"); } -// A real symbol object, SymbolBody, is usually stored within a Symbol. There's -// always one Symbol for each symbol name. The resolver updates the SymbolBody -// stored in the Body field of this object as it resolves symbols. Symbol also -// holds computed properties of symbol names. -struct Symbol { - // True if this symbol was referenced by a regular (non-bitcode) object. - unsigned IsUsedInRegularObj : 1; - - // True if we've seen both a lazy and an undefined symbol with this symbol - // name, which means that we have enqueued an archive member load and should - // not load any more archive members to resolve the same symbol. - unsigned PendingArchiveLoad : 1; - - // This field is used to store the Symbol's SymbolBody. This instantiation of - // AlignedCharArrayUnion gives us a struct with a char array field that is - // large and aligned enough to store any derived class of SymbolBody. - llvm::AlignedCharArrayUnion< - DefinedRegular, DefinedCommon, DefinedAbsolute, DefinedSynthetic, Lazy, - Undefined, DefinedImportData, DefinedImportThunk, DefinedLocalImport> - Body; - - SymbolBody *body() { - return reinterpret_cast<SymbolBody *>(Body.buffer); - } - const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); } +// A buffer class that is large enough to hold any Symbol-derived +// object. We allocate memory using this class and instantiate a symbol +// using the placement new. +union SymbolUnion { + alignas(DefinedRegular) char A[sizeof(DefinedRegular)]; + alignas(DefinedCommon) char B[sizeof(DefinedCommon)]; + alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)]; + alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)]; + alignas(Lazy) char E[sizeof(Lazy)]; + alignas(Undefined) char F[sizeof(Undefined)]; + alignas(DefinedImportData) char G[sizeof(DefinedImportData)]; + alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)]; + alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)]; }; template <typename T, typename... ArgT> -void replaceBody(Symbol *S, ArgT &&... Arg) { - static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); - static_assert(alignof(T) <= alignof(decltype(S->Body)), - "Body not aligned enough"); - assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr && - "Not a SymbolBody"); - new (S->Body.buffer) T(std::forward<ArgT>(Arg)...); -} - -inline Symbol *SymbolBody::symbol() { - assert(isExternal()); - return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) - - offsetof(Symbol, Body)); +void replaceSymbol(Symbol *S, ArgT &&... Arg) { + static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small"); + static_assert(alignof(T) <= alignof(SymbolUnion), + "SymbolUnion not aligned enough"); + assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && + "Not a Symbol"); + new (S) T(std::forward<ArgT>(Arg)...); } } // namespace coff -std::string toString(coff::SymbolBody &B); +std::string toString(coff::Symbol &B); } // namespace lld #endif |