diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 17ae02e6eeee..5e7d4d10478d 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -86,11 +86,11 @@ SymbolBody *elf2::ObjectFile::createSymbolBody(StringRef StringTable, error("unexpected binding"); case STB_GLOBAL: if (Sym->isUndefined()) - return new (Alloc) Undefined(Name); + return new (Alloc) Undefined(Name, *Sym); return new (Alloc) DefinedRegular(Name, *Sym); case STB_WEAK: if (Sym->isUndefined()) - return new (Alloc) UndefinedWeak(Name); + return new (Alloc) UndefinedWeak(Name, *Sym); return new (Alloc) DefinedWeak(Name, *Sym); } } diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 6884988d5542..d39b6cd4c581 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -16,7 +16,9 @@ using namespace llvm; using namespace lld; using namespace lld::elf2; -SymbolTable::SymbolTable() { resolve(new (Alloc) Undefined("_start")); } +SymbolTable::SymbolTable() { + resolve(new (Alloc) SyntheticUndefined("_start")); +} void SymbolTable::addFile(std::unique_ptr File) { File->parse(); @@ -39,9 +41,9 @@ void SymbolTable::addObject(ObjectFileBase *File) { void SymbolTable::reportRemainingUndefines() { for (auto &I : Symtab) { - Symbol *Sym = I.second; - if (auto *Undef = dyn_cast(Sym->Body)) - error(Twine("undefined symbol: ") + Undef->getName()); + SymbolBody *Body = I.second->Body; + if (Body->isStrongUndefined()) + error(Twine("undefined symbol: ") + Body->getName()); } } diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index ecf6d235ab5c..095940c284c9 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -38,6 +38,7 @@ int SymbolBody::compare(SymbolBody *Other) { case DefinedWeakKind: case UndefinedKind: case UndefinedWeakKind: + case UndefinedSyntheticKind: return 1; } llvm_unreachable("unknown symbol kind"); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index c33f28e9245d..82bf354dee74 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -40,11 +40,16 @@ public: DefinedWeakKind = 1, DefinedLast = 1, UndefinedWeakKind = 2, - UndefinedKind = 3 + UndefinedKind = 3, + UndefinedSyntheticKind = 4 }; Kind kind() const { return static_cast(SymbolKind); } + bool isStrongUndefined() { + return SymbolKind == UndefinedKind || SymbolKind == UndefinedSyntheticKind; + } + // Returns the symbol name. StringRef getName() const { return Name; } @@ -70,19 +75,43 @@ protected: Symbol *Backref = nullptr; }; -// The base class for any defined symbols, including absolute symbols, -// etc. -template class Defined : public SymbolBody { -public: +// 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; - const Elf_Sym &Sym; + ELFSymbolBody(Kind K, StringRef Name, const Elf_Sym &Sym) + : SymbolBody(K, Name), Sym(Sym) {} - explicit Defined(Kind K, StringRef N, const Elf_Sym &Sym) - : SymbolBody(K, N), Sym(Sym) {} +public: + const Elf_Sym &Sym; static bool classof(const SymbolBody *S) { Kind K = S->kind(); - return DefinedFirst <= K && K <= DefinedLast; + return K >= DefinedFirst && K <= UndefinedKind; + } +}; + +// The base class for any defined symbols, including absolute symbols, +// etc. +template class Defined : public ELFSymbolBody { + typedef ELFSymbolBody Base; + typedef typename Base::Kind Kind; + +public: + typedef typename Base::Elf_Sym Elf_Sym; + + explicit Defined(Kind K, StringRef N, const Elf_Sym &Sym) + : ELFSymbolBody(K, N, Sym) {} + + static bool classof(const SymbolBody *S) { + Kind K = S->kind(); + return Base::DefinedFirst <= K && K <= Base::DefinedLast; } }; @@ -114,21 +143,38 @@ public: }; // Undefined symbols. -class Undefined : public SymbolBody { +class SyntheticUndefined : public SymbolBody { public: - explicit Undefined(StringRef N) : SymbolBody(UndefinedKind, N) {} + explicit SyntheticUndefined(StringRef N) : SymbolBody(UndefinedKind, N) {} static bool classof(const SymbolBody *S) { return S->kind() == UndefinedKind; } }; -class UndefinedWeak : public SymbolBody { +template class Undefined : public ELFSymbolBody { + typedef ELFSymbolBody Base; + typedef typename Base::Elf_Sym Elf_Sym; + public: - explicit UndefinedWeak(StringRef N) : SymbolBody(UndefinedWeakKind, N) {} + explicit Undefined(StringRef N, const Elf_Sym &Sym) + : ELFSymbolBody(Base::UndefinedKind, N, Sym) {} static bool classof(const SymbolBody *S) { - return S->kind() == UndefinedWeakKind; + return S->kind() == Base::UndefinedKind; + } +}; + +template class UndefinedWeak : public ELFSymbolBody { + typedef ELFSymbolBody Base; + typedef typename Base::Elf_Sym Elf_Sym; + +public: + explicit UndefinedWeak(StringRef N, const Elf_Sym &Sym) + : ELFSymbolBody(Base::UndefinedWeakKind, N, Sym) {} + + static bool classof(const SymbolBody *S) { + return S->kind() == Base::UndefinedWeakKind; } }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 687ea580cdc3..9eb4b9aa11ec 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -224,16 +224,16 @@ template void SymbolTableSection::writeTo(uint8_t *Buf) { uint8_t Type = 0; switch (Body->kind()) { case SymbolBody::UndefinedKind: + case SymbolBody::UndefinedSyntheticKind: llvm_unreachable("Should be defined by now"); case SymbolBody::DefinedRegularKind: Binding = STB_GLOBAL; Type = cast>(Body)->Sym.getType(); break; case SymbolBody::DefinedWeakKind: - Type = cast>(Body)->Sym.getType(); - // Fallthrough case SymbolBody::UndefinedWeakKind: Binding = STB_WEAK; + Type = cast>(Body)->Sym.getType(); break; } ESym->setBindingAndType(Binding, Type); diff --git a/lld/test/elf2/symbols.s b/lld/test/elf2/symbols.s index 8edc68404503..21d1d39afc18 100644 --- a/lld/test/elf2/symbols.s +++ b/lld/test/elf2/symbols.s @@ -11,6 +11,10 @@ _start: .weak foo foo: +.type bar, @object +.weak bar +.long bar + // CHECK: Symbols [ // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: (0) @@ -31,6 +35,15 @@ foo: // CHECK-NEXT: Section: Undefined (0x0) // CHECK-NEXT: } // CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: bar +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Weak (0x2) +// CHECK-NEXT: Type: Object (0x1) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Undefined (0x0) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { // CHECK-NEXT: Name: foo // CHECK-NEXT: Value: 0x0 // CHECK-NEXT: Size: 0