Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -275,7 +275,7 @@ 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 @@ 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); } } Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -35,7 +35,6 @@ 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. Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -807,6 +807,7 @@ return Out::Bss->getVA() + SS.OffsetInBSS; return 0; } + case SymbolBody::UndefinedElfKind: case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyKind: @@ -1329,6 +1330,16 @@ } template +static const typename llvm::object::ELFFile::Elf_Sym * +getElfSym(SymbolBody &Body) { + if (const auto *EBody = dyn_cast>(&Body)) + return &EBody->Sym; + if (const 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 // pointed by Buf. @@ -1355,6 +1366,7 @@ OutSec = Out::Bss; break; } + case SymbolBody::UndefinedElfKind: case SymbolBody::UndefinedKind: case SymbolBody::DefinedAbsoluteKind: case SymbolBody::LazyKind: @@ -1366,10 +1378,9 @@ 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 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; } Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -18,7 +18,7 @@ class Lazy; struct Symbol; template class OutputSectionBase; -template class Undefined; +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 @@ 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); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -80,14 +80,14 @@ 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 @@ 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 @@ 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 @@ 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. Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -62,6 +62,7 @@ DefinedSyntheticKind, SharedKind, DefinedLast = SharedKind, + UndefinedElfKind, UndefinedKind, LazyKind }; @@ -69,7 +70,9 @@ 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 @@ 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,27 +248,29 @@ }; // Undefined symbol. -template class Undefined : public ELFSymbolBody { - typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; +class Undefined : public SymbolBody { + typedef SymbolBody::Kind Kind; + bool CanKeepUndefined; -public: - static Elf_Sym Required; - static Elf_Sym Optional; +protected: + Undefined(Kind K, StringRef N, bool IsWeak, uint8_t Visibility, bool IsTls); - Undefined(StringRef N, const Elf_Sym &Sym) - : ELFSymbolBody(SymbolBody::UndefinedKind, N, Sym) {} +public: + Undefined(StringRef N, bool IsWeak, uint8_t Visibility, + bool CanKeepUndefined); - static bool classof(const SymbolBody *S) { - return S->kind() == SymbolBody::UndefinedKind; - } + static bool classof(const SymbolBody *S) { return S->isUndefined(); } - bool canKeepUndefined() const { return &this->Sym == &Optional; } + bool canKeepUndefined() const { return CanKeepUndefined; } }; -template -typename Undefined::Elf_Sym Undefined::Required; -template -typename Undefined::Elf_Sym Undefined::Optional; +template class UndefinedElf : public Undefined { + typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; + +public: + UndefinedElf(StringRef N, const Elf_Sym &Sym); + const Elf_Sym &Sym; +}; template class SharedSymbol : public Defined { typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -73,6 +73,23 @@ 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, 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 +105,6 @@ 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 +118,12 @@ template int SymbolBody::compare(SymbolBody *Other); template int SymbolBody::compare(SymbolBody *Other); template int SymbolBody::compare(SymbolBody *Other); + +namespace lld { +namespace elf2 { +template class UndefinedElf; +template class UndefinedElf; +template class UndefinedElf; +template class UndefinedElf; +} +} Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -745,7 +745,7 @@ 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);