| //===- 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 ELFT> class ObjectFile; |
| template <class ELFT> class OutputSection; |
| template <class ELFT> class OutputSectionBase; |
| template <class ELFT> 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<Kind>(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 <class ELFT> 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 ELFT> class ELFSymbolBody : public SymbolBody { |
| protected: |
| typedef typename llvm::object::ELFFile<ELFT>::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 ELFT> class Defined : public ELFSymbolBody<ELFT> { |
| typedef ELFSymbolBody<ELFT> 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<ELFT>(K, N, Sym) {} |
| |
| static bool classof(const SymbolBody *S) { return S->isDefined(); } |
| }; |
| |
| template <class ELFT> class DefinedAbsolute : public Defined<ELFT> { |
| typedef ELFSymbolBody<ELFT> 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<ELFT>(Base::DefinedAbsoluteKind, N, Sym) {} |
| |
| static bool classof(const SymbolBody *S) { |
| return S->kind() == Base::DefinedAbsoluteKind; |
| } |
| }; |
| |
| template <class ELFT> |
| typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::IgnoreUndef; |
| |
| template <class ELFT> |
| typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::MipsGp; |
| |
| template <class ELFT> class DefinedCommon : public Defined<ELFT> { |
| typedef ELFSymbolBody<ELFT> Base; |
| typedef typename Base::Elf_Sym Elf_Sym; |
| |
| public: |
| typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; |
| DefinedCommon(StringRef N, const Elf_Sym &Sym) |
| : Defined<ELFT>(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 ELFT> class DefinedRegular : public Defined<ELFT> { |
| typedef Defined<ELFT> Base; |
| typedef typename Base::Elf_Sym Elf_Sym; |
| |
| public: |
| DefinedRegular(StringRef N, const Elf_Sym &Sym, |
| InputSectionBase<ELFT> &Section) |
| : Defined<ELFT>(Base::DefinedRegularKind, N, Sym), Section(Section) {} |
| |
| static bool classof(const SymbolBody *S) { |
| return S->kind() == Base::DefinedRegularKind; |
| } |
| |
| InputSectionBase<ELFT> &Section; |
| }; |
| |
| template <class ELFT> class DefinedSynthetic : public Defined<ELFT> { |
| typedef Defined<ELFT> Base; |
| |
| public: |
| typedef typename Base::Elf_Sym Elf_Sym; |
| DefinedSynthetic(StringRef N, const Elf_Sym &Sym, |
| OutputSectionBase<ELFT> &Section) |
| : Defined<ELFT>(Base::DefinedSyntheticKind, N, Sym), Section(Section) {} |
| |
| static bool classof(const SymbolBody *S) { |
| return S->kind() == Base::DefinedSyntheticKind; |
| } |
| |
| const OutputSectionBase<ELFT> &Section; |
| }; |
| |
| // Undefined symbol. |
| template <class ELFT> class Undefined : public ELFSymbolBody<ELFT> { |
| typedef ELFSymbolBody<ELFT> 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<ELFT>(Base::UndefinedKind, N, Sym) {} |
| |
| static bool classof(const SymbolBody *S) { |
| return S->kind() == Base::UndefinedKind; |
| } |
| |
| bool canKeepUndefined() const { return &this->Sym == &Optional; } |
| }; |
| |
| template <class ELFT> |
| typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Required; |
| template <class ELFT> |
| typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Optional; |
| |
| template <class ELFT> class SharedSymbol : public Defined<ELFT> { |
| typedef Defined<ELFT> Base; |
| typedef typename Base::Elf_Sym Elf_Sym; |
| typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; |
| |
| public: |
| static bool classof(const SymbolBody *S) { |
| return S->kind() == Base::SharedKind; |
| } |
| |
| SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym) |
| : Defined<ELFT>(Base::SharedKind, Name, Sym), File(F) {} |
| |
| SharedFile<ELFT> *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<InputFile> getMember(); |
| |
| void setWeak() { IsWeak = true; } |
| void setUsedInRegularObj() { IsUsedInRegularObj = true; } |
| |
| private: |
| ArchiveFile *File; |
| const llvm::object::Archive::Symbol Sym; |
| }; |
| |
| } // namespace elf2 |
| } // namespace lld |
| |
| #endif |