forked from OSchip/llvm-project
ELF: Also record the type of undefined symbols.
Tested with a weak undefined. Testing with a plain undefined will have to wait for support for -shared. llvm-svn: 245069
This commit is contained in:
parent
a57d015154
commit
1bd885aba4
|
@ -86,11 +86,11 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
|
|||
error("unexpected binding");
|
||||
case STB_GLOBAL:
|
||||
if (Sym->isUndefined())
|
||||
return new (Alloc) Undefined(Name);
|
||||
return new (Alloc) Undefined<ELFT>(Name, *Sym);
|
||||
return new (Alloc) DefinedRegular<ELFT>(Name, *Sym);
|
||||
case STB_WEAK:
|
||||
if (Sym->isUndefined())
|
||||
return new (Alloc) UndefinedWeak(Name);
|
||||
return new (Alloc) UndefinedWeak<ELFT>(Name, *Sym);
|
||||
return new (Alloc) DefinedWeak<ELFT>(Name, *Sym);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<InputFile> 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<Undefined>(Sym->Body))
|
||||
error(Twine("undefined symbol: ") + Undef->getName());
|
||||
SymbolBody *Body = I.second->Body;
|
||||
if (Body->isStrongUndefined())
|
||||
error(Twine("undefined symbol: ") + Body->getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ int SymbolBody::compare(SymbolBody *Other) {
|
|||
case DefinedWeakKind:
|
||||
case UndefinedKind:
|
||||
case UndefinedWeakKind:
|
||||
case UndefinedSyntheticKind:
|
||||
return 1;
|
||||
}
|
||||
llvm_unreachable("unknown symbol kind");
|
||||
|
|
|
@ -40,11 +40,16 @@ public:
|
|||
DefinedWeakKind = 1,
|
||||
DefinedLast = 1,
|
||||
UndefinedWeakKind = 2,
|
||||
UndefinedKind = 3
|
||||
UndefinedKind = 3,
|
||||
UndefinedSyntheticKind = 4
|
||||
};
|
||||
|
||||
Kind kind() const { return static_cast<Kind>(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 ELFT> 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 ELFT> class ELFSymbolBody : public SymbolBody {
|
||||
protected:
|
||||
typedef typename llvm::object::ELFFile<ELFT>::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 ELFT> class Defined : public ELFSymbolBody<ELFT> {
|
||||
typedef ELFSymbolBody<ELFT> 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<ELFT>(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 ELFT> class Undefined : public ELFSymbolBody<ELFT> {
|
||||
typedef ELFSymbolBody<ELFT> 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<ELFT>(Base::UndefinedKind, N, Sym) {}
|
||||
|
||||
static bool classof(const SymbolBody *S) {
|
||||
return S->kind() == UndefinedWeakKind;
|
||||
return S->kind() == Base::UndefinedKind;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ELFT> class UndefinedWeak : public ELFSymbolBody<ELFT> {
|
||||
typedef ELFSymbolBody<ELFT> Base;
|
||||
typedef typename Base::Elf_Sym Elf_Sym;
|
||||
|
||||
public:
|
||||
explicit UndefinedWeak(StringRef N, const Elf_Sym &Sym)
|
||||
: ELFSymbolBody<ELFT>(Base::UndefinedWeakKind, N, Sym) {}
|
||||
|
||||
static bool classof(const SymbolBody *S) {
|
||||
return S->kind() == Base::UndefinedWeakKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -224,16 +224,16 @@ template <class ELFT> void SymbolTableSection<ELFT>::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<DefinedRegular<ELFT>>(Body)->Sym.getType();
|
||||
break;
|
||||
case SymbolBody::DefinedWeakKind:
|
||||
Type = cast<DefinedWeak<ELFT>>(Body)->Sym.getType();
|
||||
// Fallthrough
|
||||
case SymbolBody::UndefinedWeakKind:
|
||||
Binding = STB_WEAK;
|
||||
Type = cast<ELFSymbolBody<ELFT>>(Body)->Sym.getType();
|
||||
break;
|
||||
}
|
||||
ESym->setBindingAndType(Binding, Type);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue