Split Undefined and UndefinedElf.

I am working on adding LTO support to the new ELF lld.

In order to do that, it will be necessary to represent defined and
undefined symbols that are not from ELF files. One way to do it is to
change the symbol hierarchy to look like

Defined : SymbolBody
Undefined : SymbolBody

DefinedElf<ELFT> : Defined
UndefinedElf<ELFT> : Undefined

Another option would be to use bogus Elf_Sym, but I think that is
getting a bit too hackish.

This patch does the Undefined/UndefinedElf. Split. The next one
will do the Defined/DefinedElf split.

llvm-svn: 256289
This commit is contained in:
Rafael Espindola 2015-12-22 23:00:50 +00:00
parent b10423ad49
commit 5d7593bc59
8 changed files with 81 additions and 70 deletions

View File

@ -275,7 +275,7 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
case SHN_ABS:
return new (this->Alloc) DefinedAbsolute<ELFT>(Name, *Sym);
case SHN_UNDEF:
return new (this->Alloc) Undefined<ELFT>(Name, *Sym);
return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
case SHN_COMMON:
return new (this->Alloc) DefinedCommon<ELFT>(Name, *Sym);
}
@ -288,7 +288,7 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
case STB_GNU_UNIQUE: {
InputSectionBase<ELFT> *Sec = getSection(*Sym);
if (Sec == &InputSection<ELFT>::Discarded)
return new (this->Alloc) Undefined<ELFT>(Name, *Sym);
return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
return new (this->Alloc) DefinedRegular<ELFT>(Name, *Sym, *Sec);
}
}

View File

@ -807,6 +807,7 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
return Out<ELFT>::Bss->getVA() + SS.OffsetInBSS;
return 0;
}
case SymbolBody::UndefinedElfKind:
case SymbolBody::UndefinedKind:
return 0;
case SymbolBody::LazyKind:
@ -1328,6 +1329,16 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
}
}
template <class ELFT>
static const typename llvm::object::ELFFile<ELFT>::Elf_Sym *
getElfSym(SymbolBody &Body) {
if (auto *EBody = dyn_cast<Defined<ELFT>>(&Body))
return &EBody->Sym;
if (auto *EBody = dyn_cast<UndefinedElf<ELFT>>(&Body))
return &EBody->Sym;
return nullptr;
}
template <class ELFT>
void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
// Write the internal symbol table contents to the output symbol table
@ -1355,6 +1366,7 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
OutSec = Out<ELFT>::Bss;
break;
}
case SymbolBody::UndefinedElfKind:
case SymbolBody::UndefinedKind:
case SymbolBody::DefinedAbsoluteKind:
case SymbolBody::LazyKind:
@ -1366,10 +1378,9 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
unsigned char Type = STT_NOTYPE;
uintX_t Size = 0;
if (const auto *EBody = dyn_cast<ELFSymbolBody<ELFT>>(Body)) {
const Elf_Sym &InputSym = EBody->Sym;
Type = InputSym.getType();
Size = InputSym.st_size;
if (const Elf_Sym *InputSym = getElfSym<ELFT>(*Body)) {
Type = InputSym->getType();
Size = InputSym->st_size;
}
ESym->setBindingAndType(getSymbolBinding(Body), Type);
@ -1391,8 +1402,8 @@ uint8_t SymbolTableSection<ELFT>::getSymbolBinding(SymbolBody *Body) {
uint8_t Visibility = Body->getVisibility();
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
return STB_LOCAL;
if (const auto *EBody = dyn_cast<ELFSymbolBody<ELFT>>(Body))
return EBody->Sym.getBinding();
if (const Elf_Sym *ESym = getElfSym<ELFT>(*Body))
return ESym->getBinding();
return Body->isWeak() ? STB_WEAK : STB_GLOBAL;
}

View File

@ -35,7 +35,6 @@ template <class ELFT> class MipsReginfoInputSection;
template <class ELFT> class OutputSection;
template <class ELFT> class ObjectFile;
template <class ELFT> class DefinedRegular;
template <class ELFT> class ELFSymbolBody;
// Flag to force GOT to be in output if we have relocations
// that relies on its address.

View File

@ -80,14 +80,14 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addUndefined(StringRef Name) {
auto *Sym = new (Alloc) Undefined<ELFT>(Name, Undefined<ELFT>::Required);
auto *Sym = new (Alloc) Undefined(Name, false, STV_DEFAULT, false);
resolve(Sym);
return Sym;
}
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
auto *Sym = new (Alloc) Undefined<ELFT>(Name, Undefined<ELFT>::Optional);
auto *Sym = new (Alloc) Undefined(Name, false, STV_HIDDEN, true);
resolve(Sym);
return Sym;
}
@ -130,13 +130,9 @@ template <class ELFT>
ELFFileBase<ELFT> *
elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles,
const SymbolBody *B) {
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
const Elf_Sym *Sym = &cast<ELFSymbolBody<ELFT>>(*B).Sym;
for (const std::unique_ptr<ObjectFile<ELFT>> &F : ObjectFiles) {
Elf_Sym_Range R = F->getObj().symbols(F->getSymbolTable());
if (R.begin() <= Sym && Sym < R.end())
ArrayRef<SymbolBody *> Syms = F->getSymbols();
if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
return F.get();
}
return nullptr;
@ -163,7 +159,7 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
SymbolBody *Existing = Sym->Body;
if (Lazy *L = dyn_cast<Lazy>(Existing)) {
if (auto *Undef = dyn_cast<Undefined<ELFT>>(New)) {
if (auto *Undef = dyn_cast<Undefined>(New)) {
addMemberFile(Undef, L);
return;
}
@ -211,14 +207,14 @@ template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *L) {
Symbol *Sym = insert(L);
if (Sym->Body == L)
return;
if (auto *Undef = dyn_cast<Undefined<ELFT>>(Sym->Body)) {
if (auto *Undef = dyn_cast<Undefined>(Sym->Body)) {
Sym->Body = L;
addMemberFile(Undef, L);
}
}
template <class ELFT>
void SymbolTable<ELFT>::addMemberFile(Undefined<ELFT> *Undef, Lazy *L) {
void SymbolTable<ELFT>::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.

View File

@ -16,9 +16,9 @@
namespace lld {
namespace elf2 {
class Lazy;
struct Symbol;
template <class ELFT> class OutputSectionBase;
template <class ELFT> 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<ELFT> *Undef, Lazy *L);
void addMemberFile(Undefined *Undef, Lazy *L);
void resolve(SymbolBody *Body);
std::string conflictMsg(SymbolBody *Old, SymbolBody *New);

View File

@ -73,6 +73,24 @@ template <class ELFT> 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 <typename ELFT>
UndefinedElf<ELFT>::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<InputFile> Lazy::getMember() {
MemoryBufferRef MBRef = File->getMember(&Sym);
@ -88,7 +106,6 @@ template <class ELFT> static void doInitSymbols() {
DefinedAbsolute<ELFT>::End.setBinding(STB_GLOBAL);
DefinedAbsolute<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
DefinedAbsolute<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
Undefined<ELFT>::Optional.setVisibility(STV_HIDDEN);
}
void lld::elf2::initSymbols() {
@ -102,3 +119,8 @@ template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
template class lld::elf2::UndefinedElf<ELF32LE>;
template class lld::elf2::UndefinedElf<ELF32BE>;
template class lld::elf2::UndefinedElf<ELF64LE>;
template class lld::elf2::UndefinedElf<ELF64BE>;

View File

@ -62,6 +62,7 @@ public:
DefinedSyntheticKind,
SharedKind,
DefinedLast = SharedKind,
UndefinedElfKind,
UndefinedKind,
LazyKind
};
@ -69,7 +70,9 @@ public:
Kind kind() const { return static_cast<Kind>(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 ELFT> class ELFSymbolBody : public SymbolBody {
protected:
typedef typename llvm::object::ELFFile<ELFT>::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 ELFT> class Defined : public ELFSymbolBody<ELFT> {
template <class ELFT> class Defined : public SymbolBody {
protected:
typedef typename SymbolBody::Kind Kind;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
public:
Defined(Kind K, StringRef N, const Elf_Sym &Sym)
: ELFSymbolBody<ELFT>(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 ELFT> class Undefined : public ELFSymbolBody<ELFT> {
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 ELFT> class UndefinedElf : public Undefined {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
public:
static Elf_Sym Required;
static Elf_Sym Optional;
Undefined(StringRef N, const Elf_Sym &Sym)
: ELFSymbolBody<ELFT>(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 <class ELFT>
typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Required;
template <class ELFT>
typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Optional;
template <class ELFT> class SharedSymbol : public Defined<ELFT> {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;

View File

@ -745,7 +745,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
for (auto &P : Symtab.getSymbols()) {
SymbolBody *Body = P.second->Body;
if (auto *U = dyn_cast<Undefined<ELFT>>(Body))
if (auto *U = dyn_cast<Undefined>(Body))
if (!U->isWeak() && !U->canKeepUndefined())
reportUndefined<ELFT>(Symtab, *Body);