Add a pointer to a source file to SymbolBody.

Previously, each subclass of SymbolBody had a pointer to a source
file from which it was created. So, there was no single way to get
a source file for a symbol. We had getSourceFile<ELFT>(), but the
function was a bit inconvenient as it's a template.

This patch makes SymbolBody have a pointer to a source file.
If a symbol is not created from a file, the pointer has a nullptr.

llvm-svn: 275701
This commit is contained in:
Rui Ueyama 2016-07-17 03:11:46 +00:00
parent 7a7a96e199
commit 434b56179e
8 changed files with 76 additions and 74 deletions

View File

@ -352,7 +352,7 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
if (Binding == STB_LOCAL) {
if (Sym->st_shndx == SHN_UNDEF)
return new (this->Alloc)
Undefined(Sym->st_name, Sym->st_other, Sym->getType());
Undefined(Sym->st_name, Sym->st_other, Sym->getType(), this);
return new (this->Alloc) DefinedRegular<ELFT>(*Sym, Sec);
}

View File

@ -147,7 +147,8 @@ BitcodeCompiler::BitcodeCompiler()
: Combined(new Module("ld-temp.o", Driver->Context)) {}
static void undefine(Symbol *S) {
replaceBody<Undefined>(S, S->body()->getName(), STV_DEFAULT, S->body()->Type);
replaceBody<Undefined>(S, S->body()->getName(), STV_DEFAULT, S->body()->Type,
nullptr);
}
static void handleUndefinedAsmRefs(const BasicSymbolRef &Sym, GlobalValue *GV,
@ -198,7 +199,7 @@ void BitcodeCompiler::add(BitcodeFile &F) {
continue;
}
auto *B = dyn_cast<DefinedBitcode>(S->body());
if (!B || B->File != &F)
if (!B || B->file() != &F)
continue;
// We collect the set of symbols we want to internalize here

View File

@ -1570,7 +1570,7 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
SS->symbol()->VersionId = VER_NDX_GLOBAL;
return;
}
SharedFile<ELFT> *F = SS->File;
SharedFile<ELFT> *F = SS->file();
// If we don't already know that we need an Elf_Verneed for this DSO, prepare
// to create one by adding it to our needed list and creating a dynstr entry
// for the soname.
@ -1582,7 +1582,7 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
// dynstr entry for the version name.
if (NV.Index == 0) {
NV.StrTab = Out<ELFT>::DynStrTab->addString(
SS->File->getStringTable().data() + SS->Verdef->getAux()->vda_name);
SS->file()->getStringTable().data() + SS->Verdef->getAux()->vda_name);
NV.Index = NextIndex++;
}
SS->symbol()->VersionId = NV.Index;

View File

@ -359,7 +359,7 @@ static RelExpr fromPlt(RelExpr Expr) {
template <class ELFT> static uint32_t getAlignment(SharedSymbol<ELFT> *SS) {
typedef typename ELFT::uint uintX_t;
uintX_t SecAlign = SS->File->getSection(SS->Sym)->sh_addralign;
uintX_t SecAlign = SS->file()->getSection(SS->Sym)->sh_addralign;
uintX_t SymValue = SS->Sym.st_value;
int TrailingZeros =
std::min(countTrailingZeros(SecAlign), countTrailingZeros(SymValue));
@ -385,11 +385,11 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol<ELFT> *SS) {
// Look through the DSO's dynamic symbol table for aliases and create a
// dynamic symbol for each one. This causes the copy relocation to correctly
// interpose any aliases.
for (const Elf_Sym &S : SS->File->getElfSymbols(true)) {
for (const Elf_Sym &S : SS->file()->getElfSymbols(true)) {
if (S.st_shndx != Shndx || S.st_value != Value)
continue;
auto *Alias = dyn_cast_or_null<SharedSymbol<ELFT>>(
Symtab<ELFT>::X->find(check(S.getName(SS->File->getStringTable()))));
Symtab<ELFT>::X->find(check(S.getName(SS->file()->getStringTable()))));
if (!Alias)
continue;
Alias->OffsetInBss = Off;

View File

@ -253,7 +253,7 @@ std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing,
std::string Sym = Existing->getName();
if (Config->Demangle)
Sym = demangle(Sym);
return Sym + " in " + getFilename(Existing->getSourceFile<ELFT>()) + " and " +
return Sym + " in " + getFilename(Existing->File) + " and " +
getFilename(NewFile);
}
@ -274,22 +274,21 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding,
/*IsUsedInRegularObj*/ !File || !isa<BitcodeFile>(File), File);
if (WasInserted) {
S->Binding = Binding;
replaceBody<Undefined>(S, Name, StOther, Type);
cast<Undefined>(S->body())->File = File;
replaceBody<Undefined>(S, Name, StOther, Type, File);
return S;
}
if (Binding != STB_WEAK) {
if (S->body()->isShared() || S->body()->isLazy())
S->Binding = Binding;
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body()))
SS->File->IsUsed = true;
SS->file()->IsUsed = true;
}
if (auto *L = dyn_cast<Lazy>(S->body())) {
// An undefined weak will not fetch archive members, but we have to remember
// its type. See also comment in addLazyArchive.
if (S->isWeak())
L->Type = Type;
else if (auto F = L->getFile())
else if (auto F = L->fetch())
addFile(std::move(F));
}
return S;
@ -535,7 +534,7 @@ void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) {
template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() {
for (StringRef S : Config->Undefined)
if (auto *L = dyn_cast_or_null<Lazy>(find(S)))
if (std::unique_ptr<InputFile> File = L->getFile())
if (std::unique_ptr<InputFile> File = L->fetch())
addFile(std::move(File));
}
@ -653,9 +652,9 @@ template <class ELFT> void SymbolTable<ELFT>::traceDefined() {
for (const auto &Symbol : Config->TraceSymbol)
if (SymbolBody *B = find(Symbol.getKey()))
if (B->isDefined() || B->isCommon())
if (InputFile *File = B->getSourceFile<ELFT>())
outs() << getFilename(File) << ": definition of "
<< B->getName() << "\n";
if (B->File)
outs() << getFilename(B->File) << ": definition of " << B->getName()
<< "\n";
}
template class elf::SymbolTable<ELF32LE>;

View File

@ -142,18 +142,6 @@ template <class ELFT> bool SymbolBody::hasThunk() const {
return false;
}
template <class ELFT> InputFile *SymbolBody::getSourceFile() {
if (auto *S = dyn_cast<DefinedRegular<ELFT>>(this))
return S->Section ? S->Section->getFile() : nullptr;
if (auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
return S->File;
if (auto *S = dyn_cast<DefinedBitcode>(this))
return S->File;
if (auto *S = dyn_cast<Undefined>(this))
return S->File;
return nullptr;
}
template <class ELFT>
typename ELFT::uint SymbolBody::getVA(typename ELFT::uint Addend) const {
typename ELFT::uint OutVA = getSymVA<ELFT>(*this, Addend);
@ -207,17 +195,25 @@ Defined::Defined(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type)
DefinedBitcode::DefinedBitcode(StringRef Name, uint8_t StOther, uint8_t Type,
BitcodeFile *F)
: Defined(DefinedBitcodeKind, Name, StOther, Type), File(F) {}
: Defined(DefinedBitcodeKind, Name, StOther, Type) {
this->File = F;
}
bool DefinedBitcode::classof(const SymbolBody *S) {
return S->kind() == DefinedBitcodeKind;
}
Undefined::Undefined(StringRef Name, uint8_t StOther, uint8_t Type)
: SymbolBody(SymbolBody::UndefinedKind, Name, StOther, Type) {}
Undefined::Undefined(StringRef Name, uint8_t StOther, uint8_t Type,
InputFile *File)
: SymbolBody(SymbolBody::UndefinedKind, Name, StOther, Type) {
this->File = File;
}
Undefined::Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type)
: SymbolBody(SymbolBody::UndefinedKind, NameOffset, StOther, Type) {}
Undefined::Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type,
InputFile *File)
: SymbolBody(SymbolBody::UndefinedKind, NameOffset, StOther, Type) {
this->File = File;
}
template <typename ELFT>
DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
@ -230,24 +226,35 @@ DefinedCommon::DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment,
: Defined(SymbolBody::DefinedCommonKind, N, StOther, Type),
Alignment(Alignment), Size(Size) {}
std::unique_ptr<InputFile> Lazy::getFile() {
std::unique_ptr<InputFile> Lazy::fetch() {
if (auto *S = dyn_cast<LazyArchive>(this))
return S->getFile();
return cast<LazyObject>(this)->getFile();
return S->fetch();
return cast<LazyObject>(this)->fetch();
}
std::unique_ptr<InputFile> LazyArchive::getFile() {
MemoryBufferRef MBRef = File.getMember(&Sym);
LazyArchive::LazyArchive(ArchiveFile &File,
const llvm::object::Archive::Symbol S, uint8_t Type)
: Lazy(LazyArchiveKind, S.getName(), Type), Sym(S) {
this->File = &File;
}
LazyObject::LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type)
: Lazy(LazyObjectKind, Name, Type) {
this->File = &File;
}
std::unique_ptr<InputFile> LazyArchive::fetch() {
MemoryBufferRef MBRef = file()->getMember(&Sym);
// getMember returns an empty buffer if the member was already
// read from the library.
if (MBRef.getBuffer().empty())
return std::unique_ptr<InputFile>(nullptr);
return createObjectFile(MBRef, File.getName());
return createObjectFile(MBRef, file()->getName());
}
std::unique_ptr<InputFile> LazyObject::getFile() {
MemoryBufferRef MBRef = File.getBuffer();
std::unique_ptr<InputFile> LazyObject::fetch() {
MemoryBufferRef MBRef = file()->getBuffer();
if (MBRef.getBuffer().empty())
return std::unique_ptr<InputFile>(nullptr);
return createObjectFile(MBRef);
@ -264,11 +271,6 @@ template bool SymbolBody::hasThunk<ELF32BE>() const;
template bool SymbolBody::hasThunk<ELF64LE>() const;
template bool SymbolBody::hasThunk<ELF64BE>() const;
template InputFile *SymbolBody::template getSourceFile<ELF32LE>();
template InputFile *SymbolBody::template getSourceFile<ELF32BE>();
template InputFile *SymbolBody::template getSourceFile<ELF64LE>();
template InputFile *SymbolBody::template getSourceFile<ELF64BE>();
template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;
template uint32_t SymbolBody::template getVA<ELF32BE>(uint32_t) const;
template uint64_t SymbolBody::template getVA<ELF64LE>(uint64_t) const;

View File

@ -99,9 +99,8 @@ public:
template <class ELFT> typename ELFT::uint getThunkVA() const;
template <class ELFT> typename ELFT::uint getSize() const;
// Returns the file from which the symbol was created.
// For logging purpose only.
template <class ELFT> InputFile *getSourceFile();
// The file from which this symbol was created.
InputFile *File = nullptr;
protected:
SymbolBody(Kind K, StringRef Name, uint8_t StOther, uint8_t Type);
@ -163,8 +162,7 @@ class DefinedBitcode : public Defined {
public:
DefinedBitcode(StringRef Name, uint8_t StOther, uint8_t Type, BitcodeFile *F);
static bool classof(const SymbolBody *S);
BitcodeFile *File;
BitcodeFile *file() { return (BitcodeFile *)this->File; }
};
class DefinedCommon : public Defined {
@ -197,7 +195,10 @@ public:
: Defined(SymbolBody::DefinedRegularKind, Name, Sym.st_other,
Sym.getType()),
Value(Sym.st_value), Size(Sym.st_size),
Section(Section ? Section->Repl : NullInputSection) {}
Section(Section ? Section->Repl : NullInputSection) {
if (Section)
this->File = Section->getFile();
}
DefinedRegular(const Elf_Sym &Sym, InputSectionBase<ELFT> *Section)
: Defined(SymbolBody::DefinedRegularKind, Sym.st_name, Sym.st_other,
@ -205,6 +206,8 @@ public:
Value(Sym.st_value), Size(Sym.st_size),
Section(Section ? Section->Repl : NullInputSection) {
assert(isLocal());
if (Section)
this->File = Section->getFile();
}
DefinedRegular(StringRef Name, uint8_t StOther)
@ -263,16 +266,14 @@ public:
class Undefined : public SymbolBody {
public:
Undefined(StringRef Name, uint8_t StOther, uint8_t Type);
Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type);
Undefined(StringRef Name, uint8_t StOther, uint8_t Type, InputFile *F);
Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type, InputFile *F);
static bool classof(const SymbolBody *S) {
return S->kind() == UndefinedKind;
}
// The file this undefined symbol was created from.
// For logging purpose only.
InputFile *File = nullptr;
InputFile *file() { return this->File; }
};
template <class ELFT> class SharedSymbol : public Defined {
@ -288,13 +289,16 @@ public:
SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
const Elf_Verdef *Verdef)
: Defined(SymbolBody::SharedKind, Name, Sym.st_other, Sym.getType()),
File(F), Sym(Sym), Verdef(Verdef) {
Sym(Sym), Verdef(Verdef) {
// IFuncs defined in DSOs are treated as functions by the static linker.
if (isGnuIFunc())
Type = llvm::ELF::STT_FUNC;
this->File = F;
}
SharedFile<ELFT> *File;
SharedFile<ELFT> *file() { return (SharedFile<ELFT> *)this->File; }
public:
const Elf_Sym &Sym;
// This field is a pointer to the symbol's version definition.
@ -323,24 +327,23 @@ public:
// Returns an object file for this symbol, or a nullptr if the file
// was already returned.
std::unique_ptr<InputFile> getFile();
std::unique_ptr<InputFile> fetch();
};
// LazyArchive symbols represents symbols in archive files.
class LazyArchive : public Lazy {
public:
LazyArchive(ArchiveFile &File, const llvm::object::Archive::Symbol S,
uint8_t Type)
: Lazy(LazyArchiveKind, S.getName(), Type), File(File), Sym(S) {}
uint8_t Type);
static bool classof(const SymbolBody *S) {
return S->kind() == LazyArchiveKind;
}
std::unique_ptr<InputFile> getFile();
ArchiveFile *file() { return (ArchiveFile *)this->File; }
std::unique_ptr<InputFile> fetch();
private:
ArchiveFile &File;
const llvm::object::Archive::Symbol Sym;
};
@ -348,17 +351,14 @@ private:
// --start-lib and --end-lib options.
class LazyObject : public Lazy {
public:
LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type)
: Lazy(LazyObjectKind, Name, Type), File(File) {}
LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type);
static bool classof(const SymbolBody *S) {
return S->kind() == LazyObjectKind;
}
std::unique_ptr<InputFile> getFile();
private:
LazyObjectFile &File;
LazyObjectFile *file() { return (LazyObjectFile *)this->File; }
std::unique_ptr<InputFile> fetch();
};
// Some linker-generated symbols need to be created as

View File

@ -275,8 +275,8 @@ static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
return;
std::string Msg = "undefined symbol: " + Sym->getName().str();
if (InputFile *File = Sym->getSourceFile<ELFT>())
Msg += " in " + getFilename(File);
if (Sym->File)
Msg += " in " + getFilename(Sym->File);
if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn)
warning(Msg);
else
@ -715,7 +715,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
if (isOutputDynamic() && S->includeInDynsym()) {
Out<ELFT>::DynSymTab->addSymbol(Body);
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
if (SS->File->isNeeded())
if (SS->file()->isNeeded())
Out<ELFT>::VerNeed->addSymbol(SS);
}
}