//===- Symbols.h ------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // All symbols are handled as SymbolBodies regardless of their types. // This file defines various types of SymbolBodies. // // File-scope symbols in ELF objects are the only exception of SymbolBody // instantiation. We will never create SymbolBodies for them for performance // reason. They are often represented as nullptrs. This is fine for symbol // resolution because the symbol table naturally cares only about // externally-visible symbols. For relocations, you have to deal with both // local and non-local functions, and we have two different functions // where we need them. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_SYMBOLS_H #define LLD_ELF_SYMBOLS_H #include "InputSection.h" #include "lld/Core/LLVM.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" namespace lld { namespace elf2 { class ArchiveFile; class InputFile; class SymbolBody; template class ObjectFile; template class OutputSection; template class OutputSectionBase; template class SharedFile; // Initializes global objects defined in this file. // Called at the beginning of main(). void initSymbols(); // A real symbol object, SymbolBody, is usually accessed indirectly // through a Symbol. There's always one Symbol for each symbol name. // The resolver updates SymbolBody pointers as it resolves symbols. struct Symbol { explicit Symbol(SymbolBody *P) : Body(P) {} SymbolBody *Body; }; // The base class for real symbol classes. class SymbolBody { public: enum Kind { DefinedFirst, DefinedRegularKind = DefinedFirst, DefinedAbsoluteKind, DefinedCommonKind, DefinedSyntheticKind, SharedKind, DefinedLast = SharedKind, UndefinedKind, LazyKind }; Kind kind() const { return static_cast(SymbolKind); } bool isWeak() const { return IsWeak; } bool isUndefined() const { return SymbolKind == UndefinedKind; } bool isDefined() const { return SymbolKind <= DefinedLast; } bool isCommon() const { return SymbolKind == DefinedCommonKind; } bool isLazy() const { return SymbolKind == LazyKind; } bool isShared() const { return SymbolKind == SharedKind; } bool isUsedInRegularObj() const { return IsUsedInRegularObj; } bool isUsedInDynamicReloc() const { return IsUsedInDynamicReloc; } void setUsedInDynamicReloc() { IsUsedInDynamicReloc = true; } bool isTLS() const { return IsTLS; } // Returns the symbol name. StringRef getName() const { return Name; } uint8_t getVisibility() const { return Visibility; } unsigned getDynamicSymbolTableIndex() const { return DynamicSymbolTableIndex; } void setDynamicSymbolTableIndex(unsigned V) { DynamicSymbolTableIndex = V; } uint32_t GotIndex = -1; uint32_t GotPltIndex = -1; uint32_t PltIndex = -1; bool isInGot() const { return GotIndex != -1U; } bool isInGotPlt() const { return GotPltIndex != -1U; } bool isInPlt() const { return PltIndex != -1U; } // A SymbolBody has a backreference to a Symbol. Originally they are // doubly-linked. A backreference will never change. But the pointer // in the Symbol may be mutated by the resolver. If you have a // pointer P to a SymbolBody and are not sure whether the resolver // has chosen the object among other objects having the same name, // you can access P->Backref->Body to get the resolver's result. void setBackref(Symbol *P) { Backref = P; } SymbolBody *repl() { return Backref ? Backref->Body : this; } // Decides which symbol should "win" in the symbol table, this or // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if // they are duplicate (conflicting) symbols. template int compare(SymbolBody *Other); protected: SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility, bool IsTLS) : SymbolKind(K), IsWeak(IsWeak), Visibility(Visibility), IsTLS(IsTLS), Name(Name) { IsUsedInRegularObj = K != SharedKind && K != LazyKind; IsUsedInDynamicReloc = 0; } const unsigned SymbolKind : 8; unsigned IsWeak : 1; unsigned Visibility : 2; unsigned IsUsedInRegularObj : 1; unsigned IsUsedInDynamicReloc : 1; unsigned IsTLS : 1; unsigned DynamicSymbolTableIndex = 0; StringRef Name; Symbol *Backref = nullptr; }; // This is for symbols created from elf files and not from the command line. // Since they come from object files, they have a Elf_Sym. // // FIXME: Another alternative is to give every symbol an Elf_Sym. To do that // we have to delay creating the symbol table until the output format is // known and some of its methods will be templated. We should experiment with // that once we have a bit more code. template class ELFSymbolBody : public SymbolBody { protected: typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; ELFSymbolBody(Kind K, StringRef Name, const Elf_Sym &Sym) : SymbolBody(K, Name, Sym.getBinding() == llvm::ELF::STB_WEAK, Sym.getVisibility(), Sym.getType() == llvm::ELF::STT_TLS), Sym(Sym) {} public: const Elf_Sym &Sym; static bool classof(const SymbolBody *S) { Kind K = S->kind(); return K >= DefinedFirst && K <= UndefinedKind; } }; // The base class for any defined symbols, including absolute symbols, etc. template class Defined : public ELFSymbolBody { typedef ELFSymbolBody Base; protected: typedef typename Base::Kind Kind; typedef typename Base::Elf_Sym Elf_Sym; public: Defined(Kind K, StringRef N, const Elf_Sym &Sym) : ELFSymbolBody(K, N, Sym) {} static bool classof(const SymbolBody *S) { return S->isDefined(); } }; template class DefinedAbsolute : public Defined { typedef ELFSymbolBody Base; typedef typename Base::Elf_Sym Elf_Sym; public: static Elf_Sym IgnoreUndef; // The content for _gp symbol for MIPS target. // The symbol has to be added early to reserve a place in symbol tables. // The value of the symbol is computed later by Writer. static Elf_Sym MipsGp; DefinedAbsolute(StringRef N, const Elf_Sym &Sym) : Defined(Base::DefinedAbsoluteKind, N, Sym) {} static bool classof(const SymbolBody *S) { return S->kind() == Base::DefinedAbsoluteKind; } }; template typename DefinedAbsolute::Elf_Sym DefinedAbsolute::IgnoreUndef; template typename DefinedAbsolute::Elf_Sym DefinedAbsolute::MipsGp; template class DefinedCommon : public Defined { typedef ELFSymbolBody Base; typedef typename Base::Elf_Sym Elf_Sym; public: typedef typename llvm::object::ELFFile::uintX_t uintX_t; DefinedCommon(StringRef N, const Elf_Sym &Sym) : Defined(Base::DefinedCommonKind, N, Sym) { MaxAlignment = Sym.st_value; } static bool classof(const SymbolBody *S) { return S->kind() == Base::DefinedCommonKind; } // The output offset of this common symbol in the output bss. Computed by the // writer. uintX_t OffsetInBSS; // The maximum alignment we have seen for this symbol. uintX_t MaxAlignment; }; // Regular defined symbols read from object file symbol tables. template class DefinedRegular : public Defined { typedef Defined Base; typedef typename Base::Elf_Sym Elf_Sym; public: DefinedRegular(StringRef N, const Elf_Sym &Sym, InputSectionBase &Section) : Defined(Base::DefinedRegularKind, N, Sym), Section(Section) {} static bool classof(const SymbolBody *S) { return S->kind() == Base::DefinedRegularKind; } InputSectionBase &Section; }; template class DefinedSynthetic : public Defined { typedef Defined Base; public: typedef typename Base::Elf_Sym Elf_Sym; DefinedSynthetic(StringRef N, const Elf_Sym &Sym, OutputSectionBase &Section) : Defined(Base::DefinedSyntheticKind, N, Sym), Section(Section) {} static bool classof(const SymbolBody *S) { return S->kind() == Base::DefinedSyntheticKind; } const OutputSectionBase &Section; }; // Undefined symbol. template class Undefined : public ELFSymbolBody { typedef ELFSymbolBody Base; typedef typename Base::Elf_Sym Elf_Sym; public: static Elf_Sym Required; static Elf_Sym Optional; Undefined(StringRef N, const Elf_Sym &Sym) : ELFSymbolBody(Base::UndefinedKind, N, Sym) {} static bool classof(const SymbolBody *S) { return S->kind() == Base::UndefinedKind; } bool canKeepUndefined() const { return &this->Sym == &Optional; } }; template typename Undefined::Elf_Sym Undefined::Required; template typename Undefined::Elf_Sym Undefined::Optional; template class SharedSymbol : public Defined { typedef Defined Base; typedef typename Base::Elf_Sym Elf_Sym; typedef typename llvm::object::ELFFile::uintX_t uintX_t; public: static bool classof(const SymbolBody *S) { return S->kind() == Base::SharedKind; } SharedSymbol(SharedFile *F, StringRef Name, const Elf_Sym &Sym) : Defined(Base::SharedKind, Name, Sym), File(F) {} SharedFile *File; // Can have offset if requires copy relocation. uintX_t OffsetInBSS = -1; bool needsCopy() const { return OffsetInBSS != (uintX_t)-1; } }; // This class represents a symbol defined in an archive file. It is // created from an archive file header, and it knows how to load an // 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 { public: Lazy(ArchiveFile *F, const llvm::object::Archive::Symbol S) : SymbolBody(LazyKind, S.getName(), false, llvm::ELF::STV_DEFAULT, false), File(F), Sym(S) {} static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; } // Returns an object file for this symbol, or a nullptr if the file // was already returned. std::unique_ptr getMember(); void setWeak() { IsWeak = true; } void setUsedInRegularObj() { IsUsedInRegularObj = true; } private: ArchiveFile *File; const llvm::object::Archive::Symbol Sym; }; } // namespace elf2 } // namespace lld #endif