diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index e177b9b4cec6..62d9e671ef83 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -275,7 +275,7 @@ SymbolBody *elf2::ObjectFile::createSymbolBody(StringRef StringTable, case SHN_ABS: return new (this->Alloc) DefinedAbsolute(Name, *Sym); case SHN_UNDEF: - return new (this->Alloc) Undefined(Name, *Sym); + return new (this->Alloc) UndefinedElf(Name, *Sym); case SHN_COMMON: return new (this->Alloc) DefinedCommon(Name, *Sym); } @@ -288,7 +288,7 @@ SymbolBody *elf2::ObjectFile::createSymbolBody(StringRef StringTable, case STB_GNU_UNIQUE: { InputSectionBase *Sec = getSection(*Sym); if (Sec == &InputSection::Discarded) - return new (this->Alloc) Undefined(Name, *Sym); + return new (this->Alloc) UndefinedElf(Name, *Sym); return new (this->Alloc) DefinedRegular(Name, *Sym, *Sec); } } diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 8b8026ae5e59..ee834c8bf8a5 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -807,6 +807,7 @@ typename ELFFile::uintX_t lld::elf2::getSymVA(const SymbolBody &S) { return Out::Bss->getVA() + SS.OffsetInBSS; return 0; } + case SymbolBody::UndefinedElfKind: case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyKind: @@ -1328,6 +1329,16 @@ void SymbolTableSection::writeLocalSymbols(uint8_t *&Buf) { } } +template +static const typename llvm::object::ELFFile::Elf_Sym * +getElfSym(SymbolBody &Body) { + if (auto *EBody = dyn_cast>(&Body)) + return &EBody->Sym; + if (auto *EBody = dyn_cast>(&Body)) + return &EBody->Sym; + return nullptr; +} + template void SymbolTableSection::writeGlobalSymbols(uint8_t *Buf) { // Write the internal symbol table contents to the output symbol table @@ -1355,6 +1366,7 @@ void SymbolTableSection::writeGlobalSymbols(uint8_t *Buf) { OutSec = Out::Bss; break; } + case SymbolBody::UndefinedElfKind: case SymbolBody::UndefinedKind: case SymbolBody::DefinedAbsoluteKind: case SymbolBody::LazyKind: @@ -1366,10 +1378,9 @@ void SymbolTableSection::writeGlobalSymbols(uint8_t *Buf) { unsigned char Type = STT_NOTYPE; uintX_t Size = 0; - if (const auto *EBody = dyn_cast>(Body)) { - const Elf_Sym &InputSym = EBody->Sym; - Type = InputSym.getType(); - Size = InputSym.st_size; + if (const Elf_Sym *InputSym = getElfSym(*Body)) { + Type = InputSym->getType(); + Size = InputSym->st_size; } ESym->setBindingAndType(getSymbolBinding(Body), Type); @@ -1391,8 +1402,8 @@ uint8_t SymbolTableSection::getSymbolBinding(SymbolBody *Body) { uint8_t Visibility = Body->getVisibility(); if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) return STB_LOCAL; - if (const auto *EBody = dyn_cast>(Body)) - return EBody->Sym.getBinding(); + if (const Elf_Sym *ESym = getElfSym(*Body)) + return ESym->getBinding(); return Body->isWeak() ? STB_WEAK : STB_GLOBAL; } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 45d9fd181ed0..669057dca1ff 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -35,7 +35,6 @@ template class MipsReginfoInputSection; template class OutputSection; template class ObjectFile; template class DefinedRegular; -template class ELFSymbolBody; // Flag to force GOT to be in output if we have relocations // that relies on its address. diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 5fb41a26bd50..7934aaa403b9 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -80,14 +80,14 @@ void SymbolTable::addFile(std::unique_ptr File) { template SymbolBody *SymbolTable::addUndefined(StringRef Name) { - auto *Sym = new (Alloc) Undefined(Name, Undefined::Required); + auto *Sym = new (Alloc) Undefined(Name, false, STV_DEFAULT, false); resolve(Sym); return Sym; } template SymbolBody *SymbolTable::addUndefinedOpt(StringRef Name) { - auto *Sym = new (Alloc) Undefined(Name, Undefined::Optional); + auto *Sym = new (Alloc) Undefined(Name, false, STV_HIDDEN, true); resolve(Sym); return Sym; } @@ -130,13 +130,9 @@ template ELFFileBase * elf2::findFile(ArrayRef>> ObjectFiles, const SymbolBody *B) { - typedef typename ELFFile::Elf_Sym Elf_Sym; - typedef typename ELFFile::Elf_Sym_Range Elf_Sym_Range; - - const Elf_Sym *Sym = &cast>(*B).Sym; for (const std::unique_ptr> &F : ObjectFiles) { - Elf_Sym_Range R = F->getObj().symbols(F->getSymbolTable()); - if (R.begin() <= Sym && Sym < R.end()) + ArrayRef Syms = F->getSymbols(); + if (std::find(Syms.begin(), Syms.end(), B) != Syms.end()) return F.get(); } return nullptr; @@ -163,7 +159,7 @@ template void SymbolTable::resolve(SymbolBody *New) { SymbolBody *Existing = Sym->Body; if (Lazy *L = dyn_cast(Existing)) { - if (auto *Undef = dyn_cast>(New)) { + if (auto *Undef = dyn_cast(New)) { addMemberFile(Undef, L); return; } @@ -211,14 +207,14 @@ template void SymbolTable::addLazy(Lazy *L) { Symbol *Sym = insert(L); if (Sym->Body == L) return; - if (auto *Undef = dyn_cast>(Sym->Body)) { + if (auto *Undef = dyn_cast(Sym->Body)) { Sym->Body = L; addMemberFile(Undef, L); } } template -void SymbolTable::addMemberFile(Undefined *Undef, Lazy *L) { +void SymbolTable::addMemberFile(Undefined *Undef, Lazy *L) { // Weak undefined symbols should not fetch members from archives. // If we were to keep old symbol we would not know that an archive member was // available if a strong undefined symbol shows up afterwards in the link. diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 1f50f1a21e35..c9f18bfc092f 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -16,9 +16,9 @@ namespace lld { namespace elf2 { class Lazy; -struct Symbol; template class OutputSectionBase; -template class Undefined; +struct Symbol; +class Undefined; // SymbolTable is a bucket of all known symbols, including defined, // undefined, or lazy symbols (the last one is symbols in archive @@ -62,7 +62,7 @@ public: private: Symbol *insert(SymbolBody *New); void addLazy(Lazy *New); - void addMemberFile(Undefined *Undef, Lazy *L); + void addMemberFile(Undefined *Undef, Lazy *L); void resolve(SymbolBody *Body); std::string conflictMsg(SymbolBody *Old, SymbolBody *New); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index d9eb5a528e6c..6f8d575758df 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -73,6 +73,24 @@ template int SymbolBody::compare(SymbolBody *Other) { return 0; } +Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak, + uint8_t Visibility, bool IsTls) + : SymbolBody(K, N, IsWeak, Visibility, IsTls), CanKeepUndefined(false) {} + +Undefined::Undefined(StringRef N, bool IsWeak, uint8_t Visibility, + bool CanKeepUndefined) + : Undefined(SymbolBody::UndefinedKind, N, IsWeak, Visibility, + /*IsTls*/ false) { + this->CanKeepUndefined = CanKeepUndefined; +} + +template +UndefinedElf::UndefinedElf(StringRef N, const Elf_Sym &Sym) + : Undefined(SymbolBody::UndefinedElfKind, N, + Sym.getBinding() == llvm::ELF::STB_WEAK, Sym.getVisibility(), + Sym.getType() == llvm::ELF::STT_TLS), + Sym(Sym) {} + std::unique_ptr Lazy::getMember() { MemoryBufferRef MBRef = File->getMember(&Sym); @@ -88,7 +106,6 @@ template static void doInitSymbols() { DefinedAbsolute::End.setBinding(STB_GLOBAL); DefinedAbsolute::IgnoreUndef.setBinding(STB_WEAK); DefinedAbsolute::IgnoreUndef.setVisibility(STV_HIDDEN); - Undefined::Optional.setVisibility(STV_HIDDEN); } void lld::elf2::initSymbols() { @@ -102,3 +119,8 @@ template int SymbolBody::compare(SymbolBody *Other); template int SymbolBody::compare(SymbolBody *Other); template int SymbolBody::compare(SymbolBody *Other); template int SymbolBody::compare(SymbolBody *Other); + +template class lld::elf2::UndefinedElf; +template class lld::elf2::UndefinedElf; +template class lld::elf2::UndefinedElf; +template class lld::elf2::UndefinedElf; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index b388bcf246ab..b60e4a29f631 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -62,6 +62,7 @@ public: DefinedSyntheticKind, SharedKind, DefinedLast = SharedKind, + UndefinedElfKind, UndefinedKind, LazyKind }; @@ -69,7 +70,9 @@ public: Kind kind() const { return static_cast(SymbolKind); } bool isWeak() const { return IsWeak; } - bool isUndefined() const { return SymbolKind == UndefinedKind; } + bool isUndefined() const { + return SymbolKind == UndefinedKind || SymbolKind == UndefinedElfKind; + } bool isDefined() const { return SymbolKind <= DefinedLast; } bool isCommon() const { return SymbolKind == DefinedCommonKind; } bool isLazy() const { return SymbolKind == LazyKind; } @@ -127,40 +130,18 @@ protected: 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 { +template class Defined : public SymbolBody { protected: - typedef typename SymbolBody::Kind Kind; typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; public: Defined(Kind K, StringRef N, const Elf_Sym &Sym) - : ELFSymbolBody(K, N, Sym) {} + : SymbolBody(K, N, Sym.getBinding() == llvm::ELF::STB_WEAK, + Sym.getVisibility(), Sym.getType() == llvm::ELF::STT_TLS), + Sym(Sym) {} + const Elf_Sym &Sym; static bool classof(const SymbolBody *S) { return S->isDefined(); } }; @@ -267,28 +248,30 @@ public: }; // Undefined symbol. -template class Undefined : public ELFSymbolBody { +class Undefined : public SymbolBody { + typedef SymbolBody::Kind Kind; + bool CanKeepUndefined; + +protected: + Undefined(Kind K, StringRef N, bool IsWeak, uint8_t Visibility, bool IsTls); + +public: + Undefined(StringRef N, bool IsWeak, uint8_t Visibility, + bool CanKeepUndefined); + + static bool classof(const SymbolBody *S) { return S->isUndefined(); } + + bool canKeepUndefined() const { return CanKeepUndefined; } +}; + +template class UndefinedElf : public Undefined { typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; public: - static Elf_Sym Required; - static Elf_Sym Optional; - - Undefined(StringRef N, const Elf_Sym &Sym) - : ELFSymbolBody(SymbolBody::UndefinedKind, N, Sym) {} - - static bool classof(const SymbolBody *S) { - return S->kind() == SymbolBody::UndefinedKind; - } - - bool canKeepUndefined() const { return &this->Sym == &Optional; } + UndefinedElf(StringRef N, const Elf_Sym &Sym); + const Elf_Sym &Sym; }; -template -typename Undefined::Elf_Sym Undefined::Required; -template -typename Undefined::Elf_Sym Undefined::Optional; - template class SharedSymbol : public Defined { typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; typedef typename llvm::object::ELFFile::uintX_t uintX_t; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index db12ccb299af..2440f1a55d50 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -745,7 +745,7 @@ template void Writer::createSections() { std::vector *> SharedCopySymbols; for (auto &P : Symtab.getSymbols()) { SymbolBody *Body = P.second->Body; - if (auto *U = dyn_cast>(Body)) + if (auto *U = dyn_cast(Body)) if (!U->isWeak() && !U->canKeepUndefined()) reportUndefined(Symtab, *Body);