diff options
Diffstat (limited to 'ELF/Symbols.h')
-rw-r--r-- | ELF/Symbols.h | 153 |
1 files changed, 67 insertions, 86 deletions
diff --git a/ELF/Symbols.h b/ELF/Symbols.h index aa9a87d3b4f7..c95241a5293e 100644 --- a/ELF/Symbols.h +++ b/ELF/Symbols.h @@ -16,11 +16,11 @@ #define LLD_ELF_SYMBOLS_H #include "InputSection.h" +#include "Strings.h" #include "lld/Core/LLVM.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" -#include "llvm/Support/AlignOf.h" namespace lld { namespace elf { @@ -29,10 +29,9 @@ class ArchiveFile; class BitcodeFile; class InputFile; class LazyObjectFile; -class SymbolBody; template <class ELFT> class ObjectFile; template <class ELFT> class OutputSection; -template <class ELFT> class OutputSectionBase; +class OutputSectionBase; template <class ELFT> class SharedFile; struct Symbol; @@ -45,7 +44,6 @@ public: DefinedRegularKind = DefinedFirst, SharedKind, DefinedCommonKind, - DefinedBitcodeKind, DefinedSyntheticKind, DefinedLast = DefinedSyntheticKind, UndefinedKind, @@ -71,22 +69,10 @@ public: bool isShared() const { return SymbolKind == SharedKind; } bool isLocal() const { return IsLocal; } bool isPreemptible() const; - - StringRef getName() const; - void setName(StringRef S); - - uint32_t getNameOffset() const { - assert(isLocal()); - return NameOffset; - } - + StringRef getName() const { return Name; } uint8_t getVisibility() const { return StOther & 0x3; } + void parseSymbolVersion(); - unsigned DynsymIndex = 0; - uint32_t GotIndex = -1; - uint32_t GotPltIndex = -1; - uint32_t PltIndex = -1; - uint32_t GlobalDynIndex = -1; bool isInGot() const { return GotIndex != -1U; } bool isInPlt() const { return PltIndex != -1U; } template <class ELFT> bool hasThunk() const; @@ -105,10 +91,15 @@ public: // The file from which this symbol was created. InputFile *File = nullptr; -protected: - SymbolBody(Kind K, StringRef Name, uint8_t StOther, uint8_t Type); + uint32_t DynsymIndex = 0; + uint32_t GotIndex = -1; + uint32_t GotPltIndex = -1; + uint32_t PltIndex = -1; + uint32_t GlobalDynIndex = -1; - SymbolBody(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type); +protected: + SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, + uint8_t Type); const unsigned SymbolKind : 8; @@ -123,6 +114,15 @@ public: // True if this symbol has an entry in the global part of MIPS GOT. unsigned IsInGlobalMipsGot : 1; + // True if this symbol is referenced by 32-bit GOT relocations. + unsigned Is32BitMipsGot : 1; + + // True if this symbol is in the Iplt sub-section of the Plt. + unsigned IsInIplt : 1; + + // True if this symbol is in the Igot sub-section of the .got.plt or .got. + unsigned IsInIgot : 1; + // The following fields have the same meaning as the ELF symbol attributes. uint8_t Type; // symbol type uint8_t StOther; // st_other field value @@ -142,32 +142,16 @@ public: bool isFile() const { return Type == llvm::ELF::STT_FILE; } protected: - struct Str { - const char *S; - size_t Len; - }; - union { - Str Name; - uint32_t NameOffset; - }; + StringRefZ Name; }; // The base class for any defined symbols. class Defined : public SymbolBody { public: - Defined(Kind K, StringRef Name, uint8_t StOther, uint8_t Type); - Defined(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type); + Defined(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type); static bool classof(const SymbolBody *S) { return S->isDefined(); } }; -// The defined symbol in LLVM bitcode files. -class DefinedBitcode : public Defined { -public: - DefinedBitcode(StringRef Name, uint8_t StOther, uint8_t Type, BitcodeFile *F); - static bool classof(const SymbolBody *S); - BitcodeFile *file() { return (BitcodeFile *)this->File; } -}; - class DefinedCommon : public Defined { public: DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, uint8_t StOther, @@ -179,7 +163,7 @@ public: // The output offset of this common symbol in the output bss. Computed by the // writer. - uint64_t OffsetInBss; + uint64_t Offset; // The maximum alignment we have seen for this symbol. uint64_t Alignment; @@ -193,30 +177,17 @@ template <class ELFT> class DefinedRegular : public Defined { typedef typename ELFT::uint uintX_t; public: - DefinedRegular(StringRef Name, const Elf_Sym &Sym, - InputSectionBase<ELFT> *Section) - : Defined(SymbolBody::DefinedRegularKind, Name, Sym.st_other, - Sym.getType()), - Value(Sym.st_value), Size(Sym.st_size), + DefinedRegular(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, + uintX_t Value, uintX_t Size, InputSectionBase<ELFT> *Section, + InputFile *File) + : Defined(SymbolBody::DefinedRegularKind, Name, IsLocal, StOther, Type), + Value(Value), Size(Size), Section(Section ? Section->Repl : NullInputSection) { - if (Section) - this->File = Section->getFile(); + this->File = File; } - DefinedRegular(const Elf_Sym &Sym, InputSectionBase<ELFT> *Section) - : Defined(SymbolBody::DefinedRegularKind, Sym.st_name, Sym.st_other, - Sym.getType()), - Value(Sym.st_value), Size(Sym.st_size), - Section(Section ? Section->Repl : NullInputSection) { - assert(isLocal()); - if (Section) - this->File = Section->getFile(); - } - - DefinedRegular(StringRef Name, uint8_t StOther) - : Defined(SymbolBody::DefinedRegularKind, Name, StOther, - llvm::ELF::STT_NOTYPE), - Value(0), Size(0), Section(NullInputSection) {} + // Return true if the symbol is a PIC function. + bool isMipsPIC() const; static bool classof(const SymbolBody *S) { return S->kind() == SymbolBody::DefinedRegularKind; @@ -249,28 +220,26 @@ InputSectionBase<ELFT> *DefinedRegular<ELFT>::NullInputSection; // don't belong to any input files or sections. Thus, its constructor // takes an output section to calculate output VA, etc. // If Section is null, this symbol is relative to the image base. -template <class ELFT> class DefinedSynthetic : public Defined { +class DefinedSynthetic : public Defined { public: - typedef typename ELFT::uint uintX_t; - DefinedSynthetic(StringRef N, uintX_t Value, - OutputSectionBase<ELFT> *Section); + DefinedSynthetic(StringRef Name, uint64_t Value, + const OutputSectionBase *Section) + : Defined(SymbolBody::DefinedSyntheticKind, Name, /*IsLocal=*/false, + llvm::ELF::STV_HIDDEN, 0 /* Type */), + Value(Value), Section(Section) {} static bool classof(const SymbolBody *S) { return S->kind() == SymbolBody::DefinedSyntheticKind; } - // Special value designates that the symbol 'points' - // to the end of the section. - static const uintX_t SectionEnd = uintX_t(-1); - - uintX_t Value; - const OutputSectionBase<ELFT> *Section; + uint64_t Value; + const OutputSectionBase *Section; }; class Undefined : public SymbolBody { public: - Undefined(StringRef Name, uint8_t StOther, uint8_t Type, InputFile *F); - Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type, InputFile *F); + Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, + InputFile *F); static bool classof(const SymbolBody *S) { return S->kind() == UndefinedKind; @@ -291,7 +260,8 @@ public: SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym, const Elf_Verdef *Verdef) - : Defined(SymbolBody::SharedKind, Name, Sym.st_other, Sym.getType()), + : Defined(SymbolBody::SharedKind, Name, /*IsLocal=*/false, Sym.st_other, + Sym.getType()), Sym(Sym), Verdef(Verdef) { // IFuncs defined in DSOs are treated as functions by the static linker. if (isGnuIFunc()) @@ -326,11 +296,11 @@ public: // Returns an object file for this symbol, or a nullptr if the file // was already returned. - std::unique_ptr<InputFile> fetch(); + InputFile *fetch(); protected: Lazy(SymbolBody::Kind K, StringRef Name, uint8_t Type) - : SymbolBody(K, Name, llvm::ELF::STV_DEFAULT, Type) {} + : SymbolBody(K, Name, /*IsLocal=*/false, llvm::ELF::STV_DEFAULT, Type) {} }; // LazyArchive symbols represents symbols in archive files. @@ -344,7 +314,7 @@ public: } ArchiveFile *file() { return (ArchiveFile *)this->File; } - std::unique_ptr<InputFile> fetch(); + InputFile *fetch(); private: const llvm::object::Archive::Symbol Sym; @@ -361,12 +331,15 @@ public: } LazyObjectFile *file() { return (LazyObjectFile *)this->File; } - std::unique_ptr<InputFile> fetch(); + InputFile *fetch(); }; // Some linker-generated symbols need to be created as // DefinedRegular symbols. template <class ELFT> struct ElfSym { + // The content for __ehdr_start symbol. + static DefinedRegular<ELFT> *EhdrStart; + // The content for _etext and etext symbols. static DefinedRegular<ELFT> *Etext; static DefinedRegular<ELFT> *Etext2; @@ -379,17 +352,22 @@ template <class ELFT> struct ElfSym { static DefinedRegular<ELFT> *End; static DefinedRegular<ELFT> *End2; - // The content for _gp_disp symbol for MIPS target. - static SymbolBody *MipsGpDisp; + // The content for _gp_disp/__gnu_local_gp symbols for MIPS target. + static DefinedRegular<ELFT> *MipsGpDisp; + static DefinedRegular<ELFT> *MipsLocalGp; + static DefinedRegular<ELFT> *MipsGp; }; +template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::EhdrStart; template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext; template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext2; template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata; template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata2; template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End; template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End2; -template <class ELFT> SymbolBody *ElfSym<ELFT>::MipsGpDisp; +template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsGpDisp; +template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsLocalGp; +template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsGp; // 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 @@ -425,6 +403,9 @@ struct Symbol { // True if this symbol is specified by --trace-symbol option. unsigned Traced : 1; + // This symbol version was found in a version script. + unsigned InVersionScript : 1; + bool includeInDynsym() const; bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } @@ -434,9 +415,8 @@ struct Symbol { // assume that the size and alignment of ELF64LE symbols is sufficient for any // ELFT, and we verify this with the static_asserts in replaceBody. llvm::AlignedCharArrayUnion< - DefinedBitcode, DefinedCommon, DefinedRegular<llvm::object::ELF64LE>, - DefinedSynthetic<llvm::object::ELF64LE>, Undefined, - SharedSymbol<llvm::object::ELF64LE>, LazyArchive, LazyObject> + DefinedCommon, DefinedRegular<llvm::object::ELF64LE>, DefinedSynthetic, + Undefined, SharedSymbol<llvm::object::ELF64LE>, LazyArchive, LazyObject> Body; SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); } @@ -448,8 +428,7 @@ void printTraceSymbol(Symbol *Sym); template <typename T, typename... ArgT> void replaceBody(Symbol *S, ArgT &&... Arg) { static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); - static_assert(llvm::AlignOf<T>::Alignment <= - llvm::AlignOf<decltype(S->Body)>::Alignment, + static_assert(alignof(T) <= alignof(decltype(S->Body)), "Body not aligned enough"); assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr && "Not a SymbolBody"); @@ -468,6 +447,8 @@ inline Symbol *SymbolBody::symbol() { offsetof(Symbol, Body)); } +std::string toString(const SymbolBody &B); + } // namespace elf } // namespace lld |