forked from OSchip/llvm-project
Merge SymbolBody and Symbol into one class, SymbolBody.
SymbolBody and Symbol were separated classes due to a historical reason. Symbol used to be a pointer to a SymbolBody, and the relationship between Symbol and SymbolBody was n:1. r2681780 changed that. Since that patch, SymbolBody and Symbol are allocated next to each other to improve memory locality, and they have 1:1 relationship now. So, the separation of Symbol and SymbolBody no longer makes sense. This patch merges them into one class. In order to avoid updating too many places, I chose SymbolBody as a unified name. I'll rename it Symbol in a follow-up patch. Differential Revision: https://reviews.llvm.org/D39406 llvm-svn: 317006
This commit is contained in:
parent
f3c33ca83e
commit
f1f00841d9
|
@ -24,7 +24,6 @@ namespace lld {
|
|||
namespace elf {
|
||||
|
||||
class InputFile;
|
||||
struct Symbol;
|
||||
|
||||
enum ELFKind {
|
||||
ELFNoneKind,
|
||||
|
|
|
@ -997,13 +997,12 @@ static void excludeLibs(opt::InputArgList &Args, ArrayRef<InputFile *> Files) {
|
|||
DenseSet<StringRef> Libs = getExcludeLibs(Args);
|
||||
bool All = Libs.count("ALL");
|
||||
|
||||
for (InputFile *File : Files) {
|
||||
for (InputFile *File : Files)
|
||||
if (Optional<StringRef> Archive = getArchiveName(File))
|
||||
if (All || Libs.count(path::filename(*Archive)))
|
||||
for (SymbolBody *SymBody : File->getSymbols())
|
||||
if (!SymBody->isLocal())
|
||||
SymBody->symbol()->VersionId = VER_NDX_LOCAL;
|
||||
}
|
||||
for (SymbolBody *Sym : File->getSymbols())
|
||||
if (!Sym->isLocal())
|
||||
Sym->VersionId = VER_NDX_LOCAL;
|
||||
}
|
||||
|
||||
// Do actual linking. Note that when this function is called,
|
||||
|
|
|
@ -551,16 +551,14 @@ SymbolBody *ObjFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
|
|||
|
||||
switch (Sym->st_shndx) {
|
||||
case SHN_UNDEF:
|
||||
return Symtab
|
||||
->addUndefined<ELFT>(Name, /*IsLocal=*/false, Binding, StOther, Type,
|
||||
/*CanOmitFromDynSym=*/false, this)
|
||||
->body();
|
||||
return Symtab->addUndefined<ELFT>(Name, /*IsLocal=*/false, Binding, StOther,
|
||||
Type,
|
||||
/*CanOmitFromDynSym=*/false, this);
|
||||
case SHN_COMMON:
|
||||
if (Value == 0 || Value >= UINT32_MAX)
|
||||
fatal(toString(this) + ": common symbol '" + Name +
|
||||
"' has invalid alignment: " + Twine(Value));
|
||||
return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, this)
|
||||
->body();
|
||||
return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, this);
|
||||
}
|
||||
|
||||
switch (Binding) {
|
||||
|
@ -570,13 +568,11 @@ SymbolBody *ObjFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
|
|||
case STB_WEAK:
|
||||
case STB_GNU_UNIQUE:
|
||||
if (Sec == &InputSection::Discarded)
|
||||
return Symtab
|
||||
->addUndefined<ELFT>(Name, /*IsLocal=*/false, Binding, StOther, Type,
|
||||
/*CanOmitFromDynSym=*/false, this)
|
||||
->body();
|
||||
return Symtab
|
||||
->addRegular<ELFT>(Name, StOther, Type, Value, Size, Binding, Sec, this)
|
||||
->body();
|
||||
return Symtab->addUndefined<ELFT>(Name, /*IsLocal=*/false, Binding,
|
||||
StOther, Type,
|
||||
/*CanOmitFromDynSym=*/false, this);
|
||||
return Symtab->addRegular<ELFT>(Name, StOther, Type, Value, Size, Binding,
|
||||
Sec, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -587,8 +583,7 @@ ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File)
|
|||
template <class ELFT> void ArchiveFile::parse() {
|
||||
Symbols.reserve(File->getNumberOfSymbols());
|
||||
for (const Archive::Symbol &Sym : File->symbols())
|
||||
Symbols.push_back(
|
||||
Symtab->addLazyArchive<ELFT>(Sym.getName(), this, Sym)->body());
|
||||
Symbols.push_back(Symtab->addLazyArchive<ELFT>(Sym.getName(), this, Sym));
|
||||
}
|
||||
|
||||
// Returns a buffer pointing to a member file containing a given symbol.
|
||||
|
@ -848,9 +843,9 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {
|
|||
}
|
||||
|
||||
template <class ELFT>
|
||||
static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
|
||||
const lto::InputFile::Symbol &ObjSym,
|
||||
BitcodeFile *F) {
|
||||
static SymbolBody *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
|
||||
const lto::InputFile::Symbol &ObjSym,
|
||||
BitcodeFile *F) {
|
||||
StringRef NameRef = Saver.save(ObjSym.getName());
|
||||
uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL;
|
||||
|
||||
|
@ -883,8 +878,7 @@ void BitcodeFile::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {
|
|||
KeptComdats.push_back(ComdatGroups.insert(CachedHashStringRef(S)).second);
|
||||
|
||||
for (const lto::InputFile::Symbol &ObjSym : Obj->symbols())
|
||||
Symbols.push_back(
|
||||
createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, this)->body());
|
||||
Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, this));
|
||||
}
|
||||
|
||||
static ELFKind getELFKind(MemoryBufferRef MB) {
|
||||
|
|
|
@ -108,8 +108,8 @@ static std::unique_ptr<lto::LTO> createLTO() {
|
|||
}
|
||||
|
||||
BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {
|
||||
for (Symbol *Sym : Symtab->getSymbols()) {
|
||||
StringRef Name = Sym->body()->getName();
|
||||
for (SymbolBody *Sym : Symtab->getSymbols()) {
|
||||
StringRef Name = Sym->getName();
|
||||
for (StringRef Prefix : {"__start_", "__stop_"})
|
||||
if (Name.startswith(Prefix))
|
||||
UsedStartStop.insert(Name.substr(Prefix.size()));
|
||||
|
@ -118,9 +118,9 @@ BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {
|
|||
|
||||
BitcodeCompiler::~BitcodeCompiler() = default;
|
||||
|
||||
static void undefine(Symbol *S) {
|
||||
replaceBody<Undefined>(S, nullptr, S->body()->getName(), /*IsLocal=*/false,
|
||||
STV_DEFAULT, S->body()->Type);
|
||||
static void undefine(SymbolBody *S) {
|
||||
replaceBody<Undefined>(S, nullptr, S->getName(), /*IsLocal=*/false,
|
||||
STV_DEFAULT, S->Type);
|
||||
}
|
||||
|
||||
void BitcodeCompiler::add(BitcodeFile &F) {
|
||||
|
@ -136,8 +136,7 @@ void BitcodeCompiler::add(BitcodeFile &F) {
|
|||
|
||||
// Provide a resolution to the LTO API for each symbol.
|
||||
for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) {
|
||||
SymbolBody *B = Syms[SymNum];
|
||||
Symbol *Sym = B->symbol();
|
||||
SymbolBody *Sym = Syms[SymNum];
|
||||
lto::SymbolResolution &R = Resols[SymNum];
|
||||
++SymNum;
|
||||
|
||||
|
@ -146,7 +145,7 @@ void BitcodeCompiler::add(BitcodeFile &F) {
|
|||
// flags an undefined in IR with a definition in ASM as prevailing.
|
||||
// Once IRObjectFile is fixed to report only one symbol this hack can
|
||||
// be removed.
|
||||
R.Prevailing = !ObjSym.isUndefined() && B->getFile() == &F;
|
||||
R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F;
|
||||
|
||||
// We ask LTO to preserve following global symbols:
|
||||
// 1) All symbols when doing relocatable link, so that them can be used
|
||||
|
@ -165,7 +164,7 @@ void BitcodeCompiler::add(BitcodeFile &F) {
|
|||
// still not final:
|
||||
// 1) Aliased (with --defsym) or wrapped (with --wrap) symbols.
|
||||
// 2) Symbols redefined in linker script.
|
||||
R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(B->getName());
|
||||
R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(Sym->getName());
|
||||
}
|
||||
checkError(LTOObj->add(std::move(F.Obj), Resols));
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
|
|||
return;
|
||||
|
||||
// Define a symbol.
|
||||
Symbol *Sym;
|
||||
SymbolBody *Sym;
|
||||
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
|
||||
std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility,
|
||||
/*CanOmitFromDynSym*/ false,
|
||||
|
@ -151,7 +151,7 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
|
|||
|
||||
replaceBody<DefinedRegular>(Sym, nullptr, Cmd->Name, /*IsLocal=*/false,
|
||||
Visibility, STT_NOTYPE, SymValue, 0, Sec);
|
||||
Cmd->Sym = cast<DefinedRegular>(Sym->body());
|
||||
Cmd->Sym = cast<DefinedRegular>(Sym);
|
||||
}
|
||||
|
||||
// This function is called from assignAddresses, while we are
|
||||
|
|
|
@ -228,9 +228,9 @@ template <class ELFT> static void doGcSections() {
|
|||
|
||||
// Preserve externally-visible symbols if the symbols defined by this
|
||||
// file can interrupt other ELF file's symbols at runtime.
|
||||
for (Symbol *S : Symtab->getSymbols())
|
||||
for (SymbolBody *S : Symtab->getSymbols())
|
||||
if (S->includeInDynsym())
|
||||
MarkSymbol(S->body());
|
||||
MarkSymbol(S);
|
||||
|
||||
// Preserve special sections and those which are specified in linker
|
||||
// script KEEP command.
|
||||
|
|
|
@ -544,7 +544,7 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
|
|||
for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) {
|
||||
Sym->CopyRelSec = Sec;
|
||||
Sym->IsPreemptible = false;
|
||||
Sym->symbol()->IsUsedInRegularObj = true;
|
||||
Sym->IsUsedInRegularObj = true;
|
||||
}
|
||||
|
||||
In<ELFT>::RelaDyn->addReloc({Target->CopyRel, Sec, 0, false, SS, 0});
|
||||
|
@ -717,11 +717,11 @@ static bool maybeReportUndefined(SymbolBody &Sym, InputSectionBase &Sec,
|
|||
if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll)
|
||||
return false;
|
||||
|
||||
if (Sym.isLocal() || !Sym.isUndefined() || Sym.symbol()->isWeak())
|
||||
if (Sym.isLocal() || !Sym.isUndefined() || Sym.isWeak())
|
||||
return false;
|
||||
|
||||
bool CanBeExternal = Sym.symbol()->computeBinding() != STB_LOCAL &&
|
||||
Sym.getVisibility() == STV_DEFAULT;
|
||||
bool CanBeExternal =
|
||||
Sym.computeBinding() != STB_LOCAL && Sym.getVisibility() == STV_DEFAULT;
|
||||
if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -136,9 +136,9 @@ template <class ELFT> void SymbolTable::addCombinedLTOObject() {
|
|||
template <class ELFT>
|
||||
DefinedRegular *SymbolTable::addAbsolute(StringRef Name, uint8_t Visibility,
|
||||
uint8_t Binding) {
|
||||
Symbol *Sym = addRegular<ELFT>(Name, Visibility, STT_NOTYPE, 0, 0, Binding,
|
||||
nullptr, nullptr);
|
||||
return cast<DefinedRegular>(Sym->body());
|
||||
SymbolBody *Sym = addRegular<ELFT>(Name, Visibility, STT_NOTYPE, 0, 0,
|
||||
Binding, nullptr, nullptr);
|
||||
return cast<DefinedRegular>(Sym);
|
||||
}
|
||||
|
||||
// Set a flag for --trace-symbol so that we can print out a log message
|
||||
|
@ -150,12 +150,11 @@ void SymbolTable::trace(StringRef Name) {
|
|||
// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
|
||||
// Used to implement --wrap.
|
||||
template <class ELFT> void SymbolTable::addSymbolWrap(StringRef Name) {
|
||||
SymbolBody *B = find(Name);
|
||||
if (!B)
|
||||
SymbolBody *Sym = find(Name);
|
||||
if (!Sym)
|
||||
return;
|
||||
Symbol *Sym = B->symbol();
|
||||
Symbol *Real = addUndefined<ELFT>(Saver.save("__real_" + Name));
|
||||
Symbol *Wrap = addUndefined<ELFT>(Saver.save("__wrap_" + Name));
|
||||
SymbolBody *Real = addUndefined<ELFT>(Saver.save("__real_" + Name));
|
||||
SymbolBody *Wrap = addUndefined<ELFT>(Saver.save("__wrap_" + Name));
|
||||
|
||||
defsym(Real, Sym);
|
||||
defsym(Sym, Wrap);
|
||||
|
@ -172,7 +171,7 @@ void SymbolTable::addSymbolAlias(StringRef Alias, StringRef Name) {
|
|||
return;
|
||||
}
|
||||
|
||||
defsym(addUndefined<ELFT>(Alias), B->symbol());
|
||||
defsym(addUndefined<ELFT>(Alias), B);
|
||||
}
|
||||
|
||||
// Apply symbol renames created by -wrap and -defsym. The renames are created
|
||||
|
@ -190,13 +189,13 @@ void SymbolTable::applySymbolRenames() {
|
|||
// __wrap_foo point to, we just want have __real_foo in the symbol table.
|
||||
|
||||
// First make a copy of __real_foo
|
||||
std::vector<Symbol> Origs;
|
||||
std::vector<SymbolUnion> Origs;
|
||||
for (const auto &P : WrapSymbols)
|
||||
Origs.push_back(*P.second);
|
||||
Origs.emplace_back(*(SymbolUnion *)P.second);
|
||||
|
||||
// Replace __real_foo with foo and foo with __wrap_foo
|
||||
for (SymbolRenaming &S : Defsyms) {
|
||||
S.Dst->body()->copyFrom(S.Src->body());
|
||||
S.Dst->copyFrom(S.Src);
|
||||
S.Dst->File = S.Src->File;
|
||||
S.Dst->Binding = S.Binding;
|
||||
}
|
||||
|
@ -205,16 +204,16 @@ void SymbolTable::applySymbolRenames() {
|
|||
// __real_foo into it.
|
||||
for (unsigned I = 0, N = WrapSymbols.size(); I < N; ++I) {
|
||||
// We now have two copies of __wrap_foo. Drop one.
|
||||
Symbol *Wrap = WrapSymbols[I].first;
|
||||
SymbolBody *Wrap = WrapSymbols[I].first;
|
||||
Wrap->IsUsedInRegularObj = false;
|
||||
|
||||
Symbol *Real = &Origs[I];
|
||||
auto *Real = (SymbolBody *)&Origs[I];
|
||||
// If __real_foo was undefined, we don't want it in the symbol table.
|
||||
if (!Real->body()->isInCurrentOutput())
|
||||
if (!Real->isInCurrentOutput())
|
||||
continue;
|
||||
|
||||
auto *NewSym = make<Symbol>();
|
||||
memcpy(NewSym, Real, sizeof(Symbol));
|
||||
auto *NewSym = (SymbolBody *)make<SymbolUnion>();
|
||||
memcpy(NewSym, Real, sizeof(SymbolUnion));
|
||||
SymVector.push_back(NewSym);
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +227,7 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
|
|||
}
|
||||
|
||||
// Find an existing symbol or create and insert a new one.
|
||||
std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
|
||||
std::pair<SymbolBody *, bool> SymbolTable::insert(StringRef Name) {
|
||||
// <name>@@<version> means the symbol is the default version. In that
|
||||
// case <name>@@<version> will be used to resolve references to <name>.
|
||||
//
|
||||
|
@ -249,9 +248,9 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
|
|||
V = SymIndex((int)SymVector.size(), true);
|
||||
}
|
||||
|
||||
Symbol *Sym;
|
||||
SymbolBody *Sym;
|
||||
if (IsNew) {
|
||||
Sym = make<Symbol>();
|
||||
Sym = (SymbolBody *)make<SymbolUnion>();
|
||||
Sym->InVersionScript = false;
|
||||
Sym->Binding = STB_WEAK;
|
||||
Sym->Visibility = STV_DEFAULT;
|
||||
|
@ -269,11 +268,11 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
|
|||
|
||||
// Find an existing symbol or create and insert a new one, then apply the given
|
||||
// attributes.
|
||||
std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, uint8_t Type,
|
||||
uint8_t Visibility,
|
||||
bool CanOmitFromDynSym,
|
||||
InputFile *File) {
|
||||
Symbol *S;
|
||||
std::pair<SymbolBody *, bool> SymbolTable::insert(StringRef Name, uint8_t Type,
|
||||
uint8_t Visibility,
|
||||
bool CanOmitFromDynSym,
|
||||
InputFile *File) {
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(Name);
|
||||
|
||||
|
@ -286,17 +285,16 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, uint8_t Type,
|
|||
if (!File || File->kind() == InputFile::ObjKind)
|
||||
S->IsUsedInRegularObj = true;
|
||||
|
||||
if (!WasInserted && S->body()->Type != SymbolBody::UnknownType &&
|
||||
((Type == STT_TLS) != S->body()->isTls())) {
|
||||
error("TLS attribute mismatch: " + toString(*S->body()) +
|
||||
"\n>>> defined in " + toString(S->File) + "\n>>> defined in " +
|
||||
toString(File));
|
||||
if (!WasInserted && S->Type != SymbolBody::UnknownType &&
|
||||
((Type == STT_TLS) != S->isTls())) {
|
||||
error("TLS attribute mismatch: " + toString(*S) + "\n>>> defined in " +
|
||||
toString(S->File) + "\n>>> defined in " + toString(File));
|
||||
}
|
||||
|
||||
return {S, WasInserted};
|
||||
}
|
||||
|
||||
template <class ELFT> Symbol *SymbolTable::addUndefined(StringRef Name) {
|
||||
template <class ELFT> SymbolBody *SymbolTable::addUndefined(StringRef Name) {
|
||||
return addUndefined<ELFT>(Name, /*IsLocal=*/false, STB_GLOBAL, STV_DEFAULT,
|
||||
/*Type*/ 0,
|
||||
/*CanOmitFromDynSym*/ false, /*File*/ nullptr);
|
||||
|
@ -305,30 +303,29 @@ template <class ELFT> Symbol *SymbolTable::addUndefined(StringRef Name) {
|
|||
static uint8_t getVisibility(uint8_t StOther) { return StOther & 3; }
|
||||
|
||||
template <class ELFT>
|
||||
Symbol *SymbolTable::addUndefined(StringRef Name, bool IsLocal, uint8_t Binding,
|
||||
uint8_t StOther, uint8_t Type,
|
||||
bool CanOmitFromDynSym, InputFile *File) {
|
||||
Symbol *S;
|
||||
SymbolBody *SymbolTable::addUndefined(StringRef Name, bool IsLocal,
|
||||
uint8_t Binding, uint8_t StOther,
|
||||
uint8_t Type, bool CanOmitFromDynSym,
|
||||
InputFile *File) {
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
uint8_t Visibility = getVisibility(StOther);
|
||||
std::tie(S, WasInserted) =
|
||||
insert(Name, Type, Visibility, CanOmitFromDynSym, File);
|
||||
// An undefined symbol with non default visibility must be satisfied
|
||||
// in the same DSO.
|
||||
if (WasInserted ||
|
||||
(isa<SharedSymbol>(S->body()) && Visibility != STV_DEFAULT)) {
|
||||
if (WasInserted || (isa<SharedSymbol>(S) && Visibility != STV_DEFAULT)) {
|
||||
S->Binding = Binding;
|
||||
replaceBody<Undefined>(S, File, Name, IsLocal, StOther, Type);
|
||||
return S;
|
||||
}
|
||||
if (Binding != STB_WEAK) {
|
||||
SymbolBody *B = S->body();
|
||||
if (!B->isInCurrentOutput())
|
||||
if (!S->isInCurrentOutput())
|
||||
S->Binding = Binding;
|
||||
if (auto *SS = dyn_cast<SharedSymbol>(B))
|
||||
if (auto *SS = dyn_cast<SharedSymbol>(S))
|
||||
SS->getFile<ELFT>()->IsUsed = true;
|
||||
}
|
||||
if (auto *L = dyn_cast<Lazy>(S->body())) {
|
||||
if (auto *L = dyn_cast<Lazy>(S)) {
|
||||
// An undefined weak will not fetch archive members. See comment on Lazy in
|
||||
// Symbols.h for the details.
|
||||
if (S->isWeak())
|
||||
|
@ -345,9 +342,9 @@ Symbol *SymbolTable::addUndefined(StringRef Name, bool IsLocal, uint8_t Binding,
|
|||
// FIXME: If users can transition to using
|
||||
// .symver foo,foo@@@VER
|
||||
// we can delete this hack.
|
||||
static int compareVersion(Symbol *S, StringRef Name) {
|
||||
static int compareVersion(SymbolBody *S, StringRef Name) {
|
||||
bool A = Name.contains("@@");
|
||||
bool B = S->body()->getName().contains("@@");
|
||||
bool B = S->getName().contains("@@");
|
||||
if (A && !B)
|
||||
return 1;
|
||||
if (!A && B)
|
||||
|
@ -358,17 +355,14 @@ static int compareVersion(Symbol *S, StringRef Name) {
|
|||
// We have a new defined symbol with the specified binding. Return 1 if the new
|
||||
// symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
|
||||
// strong defined symbols.
|
||||
static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding,
|
||||
static int compareDefined(SymbolBody *S, bool WasInserted, uint8_t Binding,
|
||||
StringRef Name) {
|
||||
if (WasInserted)
|
||||
return 1;
|
||||
SymbolBody *Body = S->body();
|
||||
if (!Body->isInCurrentOutput())
|
||||
if (!S->isInCurrentOutput())
|
||||
return 1;
|
||||
|
||||
if (int R = compareVersion(S, Name))
|
||||
return R;
|
||||
|
||||
if (Binding == STB_WEAK)
|
||||
return -1;
|
||||
if (S->isWeak())
|
||||
|
@ -379,21 +373,21 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding,
|
|||
// We have a new non-common defined symbol with the specified binding. Return 1
|
||||
// if the new symbol should win, -1 if the new symbol should lose, or 0 if there
|
||||
// is a conflict. If the new symbol wins, also update the binding.
|
||||
static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
|
||||
bool IsAbsolute, uint64_t Value,
|
||||
StringRef Name) {
|
||||
static int compareDefinedNonCommon(SymbolBody *S, bool WasInserted,
|
||||
uint8_t Binding, bool IsAbsolute,
|
||||
uint64_t Value, StringRef Name) {
|
||||
if (int Cmp = compareDefined(S, WasInserted, Binding, Name)) {
|
||||
if (Cmp > 0)
|
||||
S->Binding = Binding;
|
||||
return Cmp;
|
||||
}
|
||||
SymbolBody *B = S->body();
|
||||
if (isa<DefinedCommon>(B)) {
|
||||
if (isa<DefinedCommon>(S)) {
|
||||
// Non-common symbols take precedence over common symbols.
|
||||
if (Config->WarnCommon)
|
||||
warn("common " + S->body()->getName() + " is overridden");
|
||||
warn("common " + S->getName() + " is overridden");
|
||||
return 1;
|
||||
} else if (auto *R = dyn_cast<DefinedRegular>(B)) {
|
||||
}
|
||||
if (auto *R = dyn_cast<DefinedRegular>(S)) {
|
||||
if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute &&
|
||||
R->Value == Value)
|
||||
return -1;
|
||||
|
@ -401,10 +395,11 @@ static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
|
|||
return 0;
|
||||
}
|
||||
|
||||
Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
|
||||
uint8_t Binding, uint8_t StOther, uint8_t Type,
|
||||
InputFile *File) {
|
||||
Symbol *S;
|
||||
SymbolBody *SymbolTable::addCommon(StringRef N, uint64_t Size,
|
||||
uint32_t Alignment, uint8_t Binding,
|
||||
uint8_t StOther, uint8_t Type,
|
||||
InputFile *File) {
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther),
|
||||
/*CanOmitFromDynSym*/ false, File);
|
||||
|
@ -413,16 +408,16 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
|
|||
S->Binding = Binding;
|
||||
replaceBody<DefinedCommon>(S, File, N, Size, Alignment, StOther, Type);
|
||||
} else if (Cmp == 0) {
|
||||
auto *C = dyn_cast<DefinedCommon>(S->body());
|
||||
auto *C = dyn_cast<DefinedCommon>(S);
|
||||
if (!C) {
|
||||
// Non-common symbols take precedence over common symbols.
|
||||
if (Config->WarnCommon)
|
||||
warn("common " + S->body()->getName() + " is overridden");
|
||||
warn("common " + S->getName() + " is overridden");
|
||||
return S;
|
||||
}
|
||||
|
||||
if (Config->WarnCommon)
|
||||
warn("multiple common of " + S->body()->getName());
|
||||
warn("multiple common of " + S->getName());
|
||||
|
||||
Alignment = C->Alignment = std::max(C->Alignment, Alignment);
|
||||
if (Size > C->Size)
|
||||
|
@ -477,10 +472,11 @@ static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec,
|
|||
}
|
||||
|
||||
template <typename ELFT>
|
||||
Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
|
||||
uint64_t Value, uint64_t Size, uint8_t Binding,
|
||||
SectionBase *Section, InputFile *File) {
|
||||
Symbol *S;
|
||||
SymbolBody *SymbolTable::addRegular(StringRef Name, uint8_t StOther,
|
||||
uint8_t Type, uint64_t Value, uint64_t Size,
|
||||
uint8_t Binding, SectionBase *Section,
|
||||
InputFile *File) {
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther),
|
||||
/*CanOmitFromDynSym*/ false, File);
|
||||
|
@ -490,8 +486,8 @@ Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
|
|||
replaceBody<DefinedRegular>(S, File, Name, /*IsLocal=*/false, StOther, Type,
|
||||
Value, Size, Section);
|
||||
else if (Cmp == 0)
|
||||
reportDuplicate<ELFT>(S->body(),
|
||||
dyn_cast_or_null<InputSectionBase>(Section), Value);
|
||||
reportDuplicate<ELFT>(S, dyn_cast_or_null<InputSectionBase>(Section),
|
||||
Value);
|
||||
return S;
|
||||
}
|
||||
|
||||
|
@ -502,7 +498,7 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
|
|||
// DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
|
||||
// as the visibility, which will leave the visibility in the symbol table
|
||||
// unchanged.
|
||||
Symbol *S;
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT,
|
||||
/*CanOmitFromDynSym*/ true, File);
|
||||
|
@ -510,11 +506,10 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
|
|||
if (Sym.getVisibility() == STV_DEFAULT)
|
||||
S->ExportDynamic = true;
|
||||
|
||||
SymbolBody *Body = S->body();
|
||||
// An undefined symbol with non default visibility must be satisfied
|
||||
// in the same DSO.
|
||||
if (WasInserted || ((Body->isUndefined() || Body->isLazy()) &&
|
||||
Body->getVisibility() == STV_DEFAULT)) {
|
||||
if (WasInserted || ((S->isUndefined() || S->isLazy()) &&
|
||||
S->getVisibility() == STV_DEFAULT)) {
|
||||
replaceBody<SharedSymbol>(S, File, Name, Sym.st_other, Sym.getType(),
|
||||
Sym.st_value, Sym.st_size, Alignment, Verdef);
|
||||
if (!S->isWeak())
|
||||
|
@ -522,10 +517,10 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
|
|||
}
|
||||
}
|
||||
|
||||
Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding,
|
||||
uint8_t StOther, uint8_t Type,
|
||||
bool CanOmitFromDynSym, BitcodeFile *F) {
|
||||
Symbol *S;
|
||||
SymbolBody *SymbolTable::addBitcode(StringRef Name, uint8_t Binding,
|
||||
uint8_t StOther, uint8_t Type,
|
||||
bool CanOmitFromDynSym, BitcodeFile *F) {
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) =
|
||||
insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F);
|
||||
|
@ -535,7 +530,7 @@ Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding,
|
|||
replaceBody<DefinedRegular>(S, F, Name, /*IsLocal=*/false, StOther, Type, 0,
|
||||
0, nullptr);
|
||||
else if (Cmp == 0)
|
||||
reportDuplicate(S->body(), F);
|
||||
reportDuplicate(S, F);
|
||||
return S;
|
||||
}
|
||||
|
||||
|
@ -546,10 +541,10 @@ SymbolBody *SymbolTable::find(StringRef Name) {
|
|||
SymIndex V = It->second;
|
||||
if (V.Idx == -1)
|
||||
return nullptr;
|
||||
return SymVector[V.Idx]->body();
|
||||
return SymVector[V.Idx];
|
||||
}
|
||||
|
||||
void SymbolTable::defsym(Symbol *Dst, Symbol *Src) {
|
||||
void SymbolTable::defsym(SymbolBody *Dst, SymbolBody *Src) {
|
||||
// We want to tell LTO not to inline Dst symbol because LTO doesn't
|
||||
// know the final symbol contents after renaming.
|
||||
Dst->CanInline = false;
|
||||
|
@ -561,22 +556,22 @@ void SymbolTable::defsym(Symbol *Dst, Symbol *Src) {
|
|||
}
|
||||
|
||||
template <class ELFT>
|
||||
Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile *F,
|
||||
const object::Archive::Symbol Sym) {
|
||||
Symbol *S;
|
||||
SymbolBody *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile *F,
|
||||
const object::Archive::Symbol Sym) {
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(Name);
|
||||
if (WasInserted) {
|
||||
replaceBody<LazyArchive>(S, F, Sym, SymbolBody::UnknownType);
|
||||
return S;
|
||||
}
|
||||
if (!S->body()->isUndefined())
|
||||
if (!S->isUndefined())
|
||||
return S;
|
||||
|
||||
// An undefined weak will not fetch archive members. See comment on Lazy in
|
||||
// Symbols.h for the details.
|
||||
if (S->isWeak()) {
|
||||
replaceBody<LazyArchive>(S, F, Sym, S->body()->Type);
|
||||
replaceBody<LazyArchive>(S, F, Sym, S->Type);
|
||||
return S;
|
||||
}
|
||||
std::pair<MemoryBufferRef, uint64_t> MBInfo = F->getMember(&Sym);
|
||||
|
@ -587,19 +582,19 @@ Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile *F,
|
|||
|
||||
template <class ELFT>
|
||||
void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) {
|
||||
Symbol *S;
|
||||
SymbolBody *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(Name);
|
||||
if (WasInserted) {
|
||||
replaceBody<LazyObject>(S, &Obj, Name, SymbolBody::UnknownType);
|
||||
return;
|
||||
}
|
||||
if (!S->body()->isUndefined())
|
||||
if (!S->isUndefined())
|
||||
return;
|
||||
|
||||
// See comment for addLazyArchive above.
|
||||
if (S->isWeak())
|
||||
replaceBody<LazyObject>(S, &Obj, Name, S->body()->Type);
|
||||
replaceBody<LazyObject>(S, &Obj, Name, S->Type);
|
||||
else if (InputFile *F = Obj.fetch())
|
||||
addFile<ELFT>(F);
|
||||
}
|
||||
|
@ -609,7 +604,7 @@ template <class ELFT> void SymbolTable::fetchIfLazy(StringRef Name) {
|
|||
if (SymbolBody *B = find(Name)) {
|
||||
// Mark the symbol not to be eliminated by LTO
|
||||
// even if it is a bitcode symbol.
|
||||
B->symbol()->IsUsedInRegularObj = true;
|
||||
B->IsUsedInRegularObj = true;
|
||||
if (auto *L = dyn_cast_or_null<Lazy>(B))
|
||||
if (InputFile *File = L->fetch())
|
||||
addFile<ELFT>(File);
|
||||
|
@ -629,13 +624,13 @@ template <class ELFT> void SymbolTable::scanShlibUndefined() {
|
|||
SymbolBody *Sym = find(U);
|
||||
if (!Sym || !Sym->isDefined())
|
||||
continue;
|
||||
Sym->symbol()->ExportDynamic = true;
|
||||
Sym->ExportDynamic = true;
|
||||
|
||||
// If -dynamic-list is given, the default version is set to
|
||||
// VER_NDX_LOCAL, which prevents a symbol to be exported via .dynsym.
|
||||
// Set to VER_NDX_GLOBAL so the symbol will be handled as if it were
|
||||
// specified by -dynamic-list.
|
||||
Sym->symbol()->VersionId = VER_NDX_GLOBAL;
|
||||
Sym->VersionId = VER_NDX_GLOBAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -656,14 +651,13 @@ template <class ELFT> void SymbolTable::scanShlibUndefined() {
|
|||
StringMap<std::vector<SymbolBody *>> &SymbolTable::getDemangledSyms() {
|
||||
if (!DemangledSyms) {
|
||||
DemangledSyms.emplace();
|
||||
for (Symbol *Sym : SymVector) {
|
||||
SymbolBody *B = Sym->body();
|
||||
if (!B->isInCurrentOutput())
|
||||
for (SymbolBody *Sym : SymVector) {
|
||||
if (!Sym->isInCurrentOutput())
|
||||
continue;
|
||||
if (Optional<std::string> S = demangle(B->getName()))
|
||||
(*DemangledSyms)[*S].push_back(B);
|
||||
if (Optional<std::string> S = demangle(Sym->getName()))
|
||||
(*DemangledSyms)[*S].push_back(Sym);
|
||||
else
|
||||
(*DemangledSyms)[B->getName()].push_back(B);
|
||||
(*DemangledSyms)[Sym->getName()].push_back(Sym);
|
||||
}
|
||||
}
|
||||
return *DemangledSyms;
|
||||
|
@ -689,11 +683,9 @@ std::vector<SymbolBody *> SymbolTable::findAllByVersion(SymbolVersion Ver) {
|
|||
return Res;
|
||||
}
|
||||
|
||||
for (Symbol *Sym : SymVector) {
|
||||
SymbolBody *B = Sym->body();
|
||||
if (B->isInCurrentOutput() && M.match(B->getName()))
|
||||
Res.push_back(B);
|
||||
}
|
||||
for (SymbolBody *Sym : SymVector)
|
||||
if (Sym->isInCurrentOutput() && M.match(Sym->getName()))
|
||||
Res.push_back(Sym);
|
||||
return Res;
|
||||
}
|
||||
|
||||
|
@ -722,8 +714,8 @@ void SymbolTable::handleDynamicList() {
|
|||
|
||||
for (SymbolBody *B : Syms) {
|
||||
if (!Config->Shared)
|
||||
B->symbol()->ExportDynamic = true;
|
||||
else if (B->symbol()->includeInDynsym())
|
||||
B->ExportDynamic = true;
|
||||
else if (B->includeInDynsym())
|
||||
B->IsPreemptible = true;
|
||||
}
|
||||
}
|
||||
|
@ -746,14 +738,13 @@ void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
|
|||
}
|
||||
|
||||
// Assign the version.
|
||||
for (SymbolBody *B : Syms) {
|
||||
for (SymbolBody *Sym : Syms) {
|
||||
// Skip symbols containing version info because symbol versions
|
||||
// specified by symbol names take precedence over version scripts.
|
||||
// See parseSymbolVersion().
|
||||
if (B->getName().contains('@'))
|
||||
if (Sym->getName().contains('@'))
|
||||
continue;
|
||||
|
||||
Symbol *Sym = B->symbol();
|
||||
if (Sym->InVersionScript)
|
||||
warn("duplicate symbol '" + Ver.Name + "' in version script");
|
||||
Sym->VersionId = VersionId;
|
||||
|
@ -769,8 +760,8 @@ void SymbolTable::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) {
|
|||
// so we set a version to a symbol only if no version has been assigned
|
||||
// to the symbol. This behavior is compatible with GNU.
|
||||
for (SymbolBody *B : findAllByVersion(Ver))
|
||||
if (B->symbol()->VersionId == Config->DefaultSymbolVersion)
|
||||
B->symbol()->VersionId = VersionId;
|
||||
if (B->VersionId == Config->DefaultSymbolVersion)
|
||||
B->VersionId = VersionId;
|
||||
}
|
||||
|
||||
// This function processes version scripts by updating VersionId
|
||||
|
@ -801,8 +792,8 @@ void SymbolTable::scanVersionScript() {
|
|||
// Symbol themselves might know their versions because symbols
|
||||
// can contain versions in the form of <name>@<version>.
|
||||
// Let them parse and update their names to exclude version suffix.
|
||||
for (Symbol *Sym : SymVector)
|
||||
Sym->body()->parseSymbolVersion();
|
||||
for (SymbolBody *Sym : SymVector)
|
||||
Sym->parseSymbolVersion();
|
||||
}
|
||||
|
||||
template void SymbolTable::addSymbolWrap<ELF32LE>(StringRef);
|
||||
|
@ -810,23 +801,27 @@ template void SymbolTable::addSymbolWrap<ELF32BE>(StringRef);
|
|||
template void SymbolTable::addSymbolWrap<ELF64LE>(StringRef);
|
||||
template void SymbolTable::addSymbolWrap<ELF64BE>(StringRef);
|
||||
|
||||
template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef);
|
||||
template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef);
|
||||
template Symbol *SymbolTable::addUndefined<ELF64LE>(StringRef);
|
||||
template Symbol *SymbolTable::addUndefined<ELF64BE>(StringRef);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF32LE>(StringRef);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF32BE>(StringRef);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF64LE>(StringRef);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF64BE>(StringRef);
|
||||
|
||||
template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef, bool, uint8_t,
|
||||
uint8_t, uint8_t, bool,
|
||||
InputFile *);
|
||||
template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef, bool, uint8_t,
|
||||
uint8_t, uint8_t, bool,
|
||||
InputFile *);
|
||||
template Symbol *SymbolTable::addUndefined<ELF64LE>(StringRef, bool, uint8_t,
|
||||
uint8_t, uint8_t, bool,
|
||||
InputFile *);
|
||||
template Symbol *SymbolTable::addUndefined<ELF64BE>(StringRef, bool, uint8_t,
|
||||
uint8_t, uint8_t, bool,
|
||||
InputFile *);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF32LE>(StringRef, bool,
|
||||
uint8_t, uint8_t,
|
||||
uint8_t, bool,
|
||||
InputFile *);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF32BE>(StringRef, bool,
|
||||
uint8_t, uint8_t,
|
||||
uint8_t, bool,
|
||||
InputFile *);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF64LE>(StringRef, bool,
|
||||
uint8_t, uint8_t,
|
||||
uint8_t, bool,
|
||||
InputFile *);
|
||||
template SymbolBody *SymbolTable::addUndefined<ELF64BE>(StringRef, bool,
|
||||
uint8_t, uint8_t,
|
||||
uint8_t, bool,
|
||||
InputFile *);
|
||||
|
||||
template void SymbolTable::addSymbolAlias<ELF32LE>(StringRef, StringRef);
|
||||
template void SymbolTable::addSymbolAlias<ELF32BE>(StringRef, StringRef);
|
||||
|
@ -838,18 +833,18 @@ template void SymbolTable::addCombinedLTOObject<ELF32BE>();
|
|||
template void SymbolTable::addCombinedLTOObject<ELF64LE>();
|
||||
template void SymbolTable::addCombinedLTOObject<ELF64BE>();
|
||||
|
||||
template Symbol *SymbolTable::addRegular<ELF32LE>(StringRef, uint8_t, uint8_t,
|
||||
uint64_t, uint64_t, uint8_t,
|
||||
SectionBase *, InputFile *);
|
||||
template Symbol *SymbolTable::addRegular<ELF32BE>(StringRef, uint8_t, uint8_t,
|
||||
uint64_t, uint64_t, uint8_t,
|
||||
SectionBase *, InputFile *);
|
||||
template Symbol *SymbolTable::addRegular<ELF64LE>(StringRef, uint8_t, uint8_t,
|
||||
uint64_t, uint64_t, uint8_t,
|
||||
SectionBase *, InputFile *);
|
||||
template Symbol *SymbolTable::addRegular<ELF64BE>(StringRef, uint8_t, uint8_t,
|
||||
uint64_t, uint64_t, uint8_t,
|
||||
SectionBase *, InputFile *);
|
||||
template SymbolBody *
|
||||
SymbolTable::addRegular<ELF32LE>(StringRef, uint8_t, uint8_t, uint64_t,
|
||||
uint64_t, uint8_t, SectionBase *, InputFile *);
|
||||
template SymbolBody *
|
||||
SymbolTable::addRegular<ELF32BE>(StringRef, uint8_t, uint8_t, uint64_t,
|
||||
uint64_t, uint8_t, SectionBase *, InputFile *);
|
||||
template SymbolBody *
|
||||
SymbolTable::addRegular<ELF64LE>(StringRef, uint8_t, uint8_t, uint64_t,
|
||||
uint64_t, uint8_t, SectionBase *, InputFile *);
|
||||
template SymbolBody *
|
||||
SymbolTable::addRegular<ELF64BE>(StringRef, uint8_t, uint8_t, uint64_t,
|
||||
uint64_t, uint8_t, SectionBase *, InputFile *);
|
||||
|
||||
template DefinedRegular *SymbolTable::addAbsolute<ELF32LE>(StringRef, uint8_t,
|
||||
uint8_t);
|
||||
|
@ -860,16 +855,16 @@ template DefinedRegular *SymbolTable::addAbsolute<ELF64LE>(StringRef, uint8_t,
|
|||
template DefinedRegular *SymbolTable::addAbsolute<ELF64BE>(StringRef, uint8_t,
|
||||
uint8_t);
|
||||
|
||||
template Symbol *
|
||||
template SymbolBody *
|
||||
SymbolTable::addLazyArchive<ELF32LE>(StringRef, ArchiveFile *,
|
||||
const object::Archive::Symbol);
|
||||
template Symbol *
|
||||
template SymbolBody *
|
||||
SymbolTable::addLazyArchive<ELF32BE>(StringRef, ArchiveFile *,
|
||||
const object::Archive::Symbol);
|
||||
template Symbol *
|
||||
template SymbolBody *
|
||||
SymbolTable::addLazyArchive<ELF64LE>(StringRef, ArchiveFile *,
|
||||
const object::Archive::Symbol);
|
||||
template Symbol *
|
||||
template SymbolBody *
|
||||
SymbolTable::addLazyArchive<ELF64BE>(StringRef, ArchiveFile *,
|
||||
const object::Archive::Symbol);
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
struct Symbol;
|
||||
|
||||
// SymbolTable is a bucket of all known symbols, including defined,
|
||||
// undefined, or lazy symbols (the last one is symbols in archive
|
||||
// files whose archive members are not yet loaded).
|
||||
|
@ -41,22 +39,22 @@ public:
|
|||
template <class ELFT> void addSymbolWrap(StringRef Name);
|
||||
void applySymbolRenames();
|
||||
|
||||
ArrayRef<Symbol *> getSymbols() const { return SymVector; }
|
||||
ArrayRef<SymbolBody *> getSymbols() const { return SymVector; }
|
||||
|
||||
template <class ELFT>
|
||||
DefinedRegular *addAbsolute(StringRef Name,
|
||||
uint8_t Visibility = llvm::ELF::STV_HIDDEN,
|
||||
uint8_t Binding = llvm::ELF::STB_GLOBAL);
|
||||
|
||||
template <class ELFT> Symbol *addUndefined(StringRef Name);
|
||||
template <class ELFT> SymbolBody *addUndefined(StringRef Name);
|
||||
template <class ELFT>
|
||||
Symbol *addUndefined(StringRef Name, bool IsLocal, uint8_t Binding,
|
||||
uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym,
|
||||
InputFile *File);
|
||||
SymbolBody *addUndefined(StringRef Name, bool IsLocal, uint8_t Binding,
|
||||
uint8_t StOther, uint8_t Type,
|
||||
bool CanOmitFromDynSym, InputFile *File);
|
||||
template <class ELFT>
|
||||
Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
|
||||
uint64_t Value, uint64_t Size, uint8_t Binding,
|
||||
SectionBase *Section, InputFile *File);
|
||||
SymbolBody *addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
|
||||
uint64_t Value, uint64_t Size, uint8_t Binding,
|
||||
SectionBase *Section, InputFile *File);
|
||||
|
||||
template <class ELFT>
|
||||
void addShared(StringRef Name, SharedFile<ELFT> *F,
|
||||
|
@ -64,22 +62,23 @@ public:
|
|||
const typename ELFT::Verdef *Verdef);
|
||||
|
||||
template <class ELFT>
|
||||
Symbol *addLazyArchive(StringRef Name, ArchiveFile *F,
|
||||
const llvm::object::Archive::Symbol S);
|
||||
SymbolBody *addLazyArchive(StringRef Name, ArchiveFile *F,
|
||||
const llvm::object::Archive::Symbol S);
|
||||
|
||||
template <class ELFT> void addLazyObject(StringRef Name, LazyObjFile &Obj);
|
||||
|
||||
Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther,
|
||||
uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *File);
|
||||
SymbolBody *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther,
|
||||
uint8_t Type, bool CanOmitFromDynSym,
|
||||
BitcodeFile *File);
|
||||
|
||||
Symbol *addCommon(StringRef Name, uint64_t Size, uint32_t Alignment,
|
||||
uint8_t Binding, uint8_t StOther, uint8_t Type,
|
||||
InputFile *File);
|
||||
SymbolBody *addCommon(StringRef Name, uint64_t Size, uint32_t Alignment,
|
||||
uint8_t Binding, uint8_t StOther, uint8_t Type,
|
||||
InputFile *File);
|
||||
|
||||
std::pair<Symbol *, bool> insert(StringRef Name);
|
||||
std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type,
|
||||
uint8_t Visibility, bool CanOmitFromDynSym,
|
||||
InputFile *File);
|
||||
std::pair<SymbolBody *, bool> insert(StringRef Name);
|
||||
std::pair<SymbolBody *, bool> insert(StringRef Name, uint8_t Type,
|
||||
uint8_t Visibility,
|
||||
bool CanOmitFromDynSym, InputFile *File);
|
||||
|
||||
template <class ELFT> void fetchIfLazy(StringRef Name);
|
||||
template <class ELFT> void scanShlibUndefined();
|
||||
|
@ -94,7 +93,7 @@ public:
|
|||
private:
|
||||
std::vector<SymbolBody *> findByVersion(SymbolVersion Ver);
|
||||
std::vector<SymbolBody *> findAllByVersion(SymbolVersion Ver);
|
||||
void defsym(Symbol *Dst, Symbol *Src);
|
||||
void defsym(SymbolBody *Dst, SymbolBody *Src);
|
||||
|
||||
llvm::StringMap<std::vector<SymbolBody *>> &getDemangledSyms();
|
||||
void handleAnonymousVersion();
|
||||
|
@ -116,7 +115,7 @@ private:
|
|||
// FIXME: Experiment with passing in a custom hashing or sorting the symbols
|
||||
// once symbol resolution is finished.
|
||||
llvm::DenseMap<llvm::CachedHashStringRef, SymIndex> Symtab;
|
||||
std::vector<Symbol *> SymVector;
|
||||
std::vector<SymbolBody *> SymVector;
|
||||
|
||||
// Comdat groups define "link once" sections. If two comdat groups have the
|
||||
// same name, only one of them is linked, and the other is ignored. This set
|
||||
|
@ -133,8 +132,8 @@ private:
|
|||
llvm::Optional<llvm::StringMap<std::vector<SymbolBody *>>> DemangledSyms;
|
||||
|
||||
struct SymbolRenaming {
|
||||
Symbol *Dst;
|
||||
Symbol *Src;
|
||||
SymbolBody *Dst;
|
||||
SymbolBody *Src;
|
||||
uint8_t Binding;
|
||||
};
|
||||
|
||||
|
@ -142,7 +141,7 @@ private:
|
|||
std::vector<SymbolRenaming> Defsyms;
|
||||
|
||||
// For -wrap.
|
||||
std::vector<std::pair<Symbol *, Symbol *>> WrapSymbols;
|
||||
std::vector<std::pair<SymbolBody *, SymbolBody *>> WrapSymbols;
|
||||
|
||||
// For LTO.
|
||||
std::unique_ptr<BitcodeCompiler> LTO;
|
||||
|
|
|
@ -113,7 +113,7 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) {
|
|||
return 0;
|
||||
case SymbolBody::LazyArchiveKind:
|
||||
case SymbolBody::LazyObjectKind:
|
||||
assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer");
|
||||
assert(Body.IsUsedInRegularObj && "lazy symbol reached writer");
|
||||
return 0;
|
||||
}
|
||||
llvm_unreachable("invalid symbol kind");
|
||||
|
@ -122,7 +122,7 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) {
|
|||
// Returns true if this is a weak undefined symbol.
|
||||
bool SymbolBody::isUndefWeak() const {
|
||||
// See comment on Lazy in Symbols.h for the details.
|
||||
return !isLocal() && symbol()->isWeak() && (isUndefined() || isLazy());
|
||||
return !isLocal() && isWeak() && (isUndefined() || isLazy());
|
||||
}
|
||||
|
||||
InputFile *SymbolBody::getFile() const {
|
||||
|
@ -133,15 +133,24 @@ InputFile *SymbolBody::getFile() const {
|
|||
// SymbolBody, or having a special absolute section if needed.
|
||||
return Sec ? cast<InputSectionBase>(Sec)->File : nullptr;
|
||||
}
|
||||
return symbol()->File;
|
||||
return File;
|
||||
}
|
||||
|
||||
// Overwrites all attributes with Other's so that this symbol becomes
|
||||
// an alias to Other. This is useful for handling some options such as
|
||||
// --wrap.
|
||||
void SymbolBody::copyFrom(SymbolBody *Other) {
|
||||
memcpy(symbol()->Body.buffer, Other->symbol()->Body.buffer,
|
||||
sizeof(Symbol::Body));
|
||||
SymbolBody Sym = *this;
|
||||
memcpy(this, Other, sizeof(SymbolUnion));
|
||||
|
||||
Binding = Sym.Binding;
|
||||
VersionId = Sym.VersionId;
|
||||
Visibility = Sym.Visibility;
|
||||
IsUsedInRegularObj = Sym.IsUsedInRegularObj;
|
||||
ExportDynamic = Sym.ExportDynamic;
|
||||
CanInline = Sym.CanInline;
|
||||
Traced = Sym.Traced;
|
||||
InVersionScript = Sym.InVersionScript;
|
||||
}
|
||||
|
||||
uint64_t SymbolBody::getVA(int64_t Addend) const {
|
||||
|
@ -235,9 +244,9 @@ void SymbolBody::parseSymbolVersion() {
|
|||
continue;
|
||||
|
||||
if (IsDefault)
|
||||
symbol()->VersionId = Ver.Id;
|
||||
VersionId = Ver.Id;
|
||||
else
|
||||
symbol()->VersionId = Ver.Id | VERSYM_HIDDEN;
|
||||
VersionId = Ver.Id | VERSYM_HIDDEN;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -287,44 +296,43 @@ LazyObjFile *LazyObject::getFile() {
|
|||
|
||||
InputFile *LazyObject::fetch() { return getFile()->fetch(); }
|
||||
|
||||
uint8_t Symbol::computeBinding() const {
|
||||
uint8_t SymbolBody::computeBinding() const {
|
||||
if (Config->Relocatable)
|
||||
return Binding;
|
||||
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
|
||||
return STB_LOCAL;
|
||||
if (VersionId == VER_NDX_LOCAL && body()->isInCurrentOutput())
|
||||
if (VersionId == VER_NDX_LOCAL && isInCurrentOutput())
|
||||
return STB_LOCAL;
|
||||
if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
|
||||
return STB_GLOBAL;
|
||||
return Binding;
|
||||
}
|
||||
|
||||
bool Symbol::includeInDynsym() const {
|
||||
bool SymbolBody::includeInDynsym() const {
|
||||
if (!Config->HasDynSymTab)
|
||||
return false;
|
||||
if (computeBinding() == STB_LOCAL)
|
||||
return false;
|
||||
if (!body()->isInCurrentOutput())
|
||||
if (!isInCurrentOutput())
|
||||
return true;
|
||||
return ExportDynamic;
|
||||
}
|
||||
|
||||
// Print out a log message for --trace-symbol.
|
||||
void elf::printTraceSymbol(Symbol *Sym) {
|
||||
SymbolBody *B = Sym->body();
|
||||
void elf::printTraceSymbol(SymbolBody *Sym) {
|
||||
std::string S;
|
||||
if (B->isUndefined())
|
||||
if (Sym->isUndefined())
|
||||
S = ": reference to ";
|
||||
else if (B->isCommon())
|
||||
else if (Sym->isCommon())
|
||||
S = ": common definition of ";
|
||||
else if (B->isLazy())
|
||||
else if (Sym->isLazy())
|
||||
S = ": lazy definition of ";
|
||||
else if (B->isShared())
|
||||
else if (Sym->isShared())
|
||||
S = ": shared definition of ";
|
||||
else
|
||||
S = ": definition of ";
|
||||
|
||||
message(toString(Sym->File) + S + B->getName());
|
||||
message(toString(Sym->File) + S + Sym->getName());
|
||||
}
|
||||
|
||||
// Returns a symbol for an error message.
|
||||
|
|
|
@ -34,8 +34,6 @@ template <class ELFT> class ObjFile;
|
|||
class OutputSection;
|
||||
template <class ELFT> class SharedFile;
|
||||
|
||||
struct Symbol;
|
||||
|
||||
// The base class for real symbol classes.
|
||||
class SymbolBody {
|
||||
public:
|
||||
|
@ -51,14 +49,52 @@ public:
|
|||
};
|
||||
|
||||
SymbolBody(Kind K) : SymbolKind(K) {}
|
||||
|
||||
Symbol *symbol();
|
||||
const Symbol *symbol() const {
|
||||
return const_cast<SymbolBody *>(this)->symbol();
|
||||
}
|
||||
|
||||
Kind kind() const { return static_cast<Kind>(SymbolKind); }
|
||||
|
||||
// Symbol binding. This is not overwritten by replaceSymbol to track
|
||||
// changes during resolution. In particular:
|
||||
// - An undefined weak is still weak when it resolves to a shared library.
|
||||
// - An undefined weak will not fetch archive members, but we have to
|
||||
// remember it is weak.
|
||||
uint8_t Binding;
|
||||
|
||||
// Version definition index.
|
||||
uint16_t VersionId;
|
||||
|
||||
// Symbol visibility. This is the computed minimum visibility of all
|
||||
// observed non-DSO symbols.
|
||||
unsigned Visibility : 2;
|
||||
|
||||
// True if the symbol was used for linking and thus need to be added to the
|
||||
// output file's symbol table. This is true for all symbols except for
|
||||
// unreferenced DSO symbols and bitcode symbols that are unreferenced except
|
||||
// by other bitcode objects.
|
||||
unsigned IsUsedInRegularObj : 1;
|
||||
|
||||
// If this flag is true and the symbol has protected or default visibility, it
|
||||
// will appear in .dynsym. This flag is set by interposable DSO symbols in
|
||||
// executables, by most symbols in DSOs and executables built with
|
||||
// --export-dynamic, and by dynamic lists.
|
||||
unsigned ExportDynamic : 1;
|
||||
|
||||
// False if LTO shouldn't inline whatever this symbol points to. If a symbol
|
||||
// is overwritten after LTO, LTO shouldn't inline the symbol because it
|
||||
// doesn't know the final contents of the symbol.
|
||||
unsigned CanInline : 1;
|
||||
|
||||
// True if this symbol is specified by --trace-symbol option.
|
||||
unsigned Traced : 1;
|
||||
|
||||
// This symbol version was found in a version script.
|
||||
unsigned InVersionScript : 1;
|
||||
|
||||
// The file from which this symbol was created.
|
||||
InputFile *File = nullptr;
|
||||
|
||||
bool includeInDynsym() const;
|
||||
uint8_t computeBinding() const;
|
||||
bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
|
||||
|
||||
bool isUndefined() const { return SymbolKind == UndefinedKind; }
|
||||
bool isDefined() const { return SymbolKind <= DefinedLast; }
|
||||
bool isCommon() const { return SymbolKind == DefinedCommonKind; }
|
||||
|
@ -344,89 +380,47 @@ struct ElfSym {
|
|||
static DefinedRegular *MipsLocalGp;
|
||||
};
|
||||
|
||||
// A real symbol object, SymbolBody, is usually stored within a Symbol. There's
|
||||
// always one Symbol for each symbol name. The resolver updates the SymbolBody
|
||||
// stored in the Body field of this object as it resolves symbols. Symbol also
|
||||
// holds computed properties of symbol names.
|
||||
struct Symbol {
|
||||
// Symbol binding. This is on the Symbol to track changes during resolution.
|
||||
// In particular:
|
||||
// An undefined weak is still weak when it resolves to a shared library.
|
||||
// An undefined weak will not fetch archive members, but we have to remember
|
||||
// it is weak.
|
||||
uint8_t Binding;
|
||||
|
||||
// Version definition index.
|
||||
uint16_t VersionId;
|
||||
|
||||
// Symbol visibility. This is the computed minimum visibility of all
|
||||
// observed non-DSO symbols.
|
||||
unsigned Visibility : 2;
|
||||
|
||||
// True if the symbol was used for linking and thus need to be added to the
|
||||
// output file's symbol table. This is true for all symbols except for
|
||||
// unreferenced DSO symbols and bitcode symbols that are unreferenced except
|
||||
// by other bitcode objects.
|
||||
unsigned IsUsedInRegularObj : 1;
|
||||
|
||||
// If this flag is true and the symbol has protected or default visibility, it
|
||||
// will appear in .dynsym. This flag is set by interposable DSO symbols in
|
||||
// executables, by most symbols in DSOs and executables built with
|
||||
// --export-dynamic, and by dynamic lists.
|
||||
unsigned ExportDynamic : 1;
|
||||
|
||||
// False if LTO shouldn't inline whatever this symbol points to. If a symbol
|
||||
// is overwritten after LTO, LTO shouldn't inline the symbol because it
|
||||
// doesn't know the final contents of the symbol.
|
||||
unsigned CanInline : 1;
|
||||
|
||||
// True if this symbol is specified by --trace-symbol option.
|
||||
unsigned Traced : 1;
|
||||
|
||||
// This symbol version was found in a version script.
|
||||
unsigned InVersionScript : 1;
|
||||
|
||||
// The file from which this symbol was created.
|
||||
InputFile *File = nullptr;
|
||||
|
||||
bool includeInDynsym() const;
|
||||
uint8_t computeBinding() const;
|
||||
bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
|
||||
|
||||
// This field is used to store the Symbol's SymbolBody. This instantiation of
|
||||
// AlignedCharArrayUnion gives us a struct with a char array field that is
|
||||
// large and aligned enough to store any derived class of SymbolBody.
|
||||
llvm::AlignedCharArrayUnion<DefinedCommon, DefinedRegular, Undefined,
|
||||
SharedSymbol, LazyArchive, LazyObject>
|
||||
Body;
|
||||
|
||||
SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); }
|
||||
const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); }
|
||||
// A buffer class that is large enough to hold any SymbolBody-derived
|
||||
// object. We allocate memory using this class and instantiate a symbol
|
||||
// using the placement new.
|
||||
union SymbolUnion {
|
||||
alignas(DefinedRegular) char A[sizeof(DefinedRegular)];
|
||||
alignas(DefinedCommon) char B[sizeof(DefinedCommon)];
|
||||
alignas(Undefined) char C[sizeof(Undefined)];
|
||||
alignas(SharedSymbol) char D[sizeof(SharedSymbol)];
|
||||
alignas(LazyArchive) char E[sizeof(LazyArchive)];
|
||||
alignas(LazyObject) char F[sizeof(LazyObject)];
|
||||
};
|
||||
|
||||
void printTraceSymbol(Symbol *Sym);
|
||||
void printTraceSymbol(SymbolBody *Sym);
|
||||
|
||||
template <typename T, typename... ArgT>
|
||||
void replaceBody(Symbol *S, InputFile *File, ArgT &&... Arg) {
|
||||
static_assert(sizeof(T) <= sizeof(S->Body), "Body too small");
|
||||
static_assert(alignof(T) <= alignof(decltype(S->Body)),
|
||||
"Body not aligned enough");
|
||||
void replaceBody(SymbolBody *S, InputFile *File, ArgT &&... Arg) {
|
||||
static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
|
||||
static_assert(alignof(T) <= alignof(SymbolUnion),
|
||||
"SymbolUnion not aligned enough");
|
||||
assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr &&
|
||||
"Not a SymbolBody");
|
||||
|
||||
SymbolBody Sym = *S;
|
||||
|
||||
new (S) T(std::forward<ArgT>(Arg)...);
|
||||
S->File = File;
|
||||
new (S->Body.buffer) T(std::forward<ArgT>(Arg)...);
|
||||
|
||||
S->Binding = Sym.Binding;
|
||||
S->VersionId = Sym.VersionId;
|
||||
S->Visibility = Sym.Visibility;
|
||||
S->IsUsedInRegularObj = Sym.IsUsedInRegularObj;
|
||||
S->ExportDynamic = Sym.ExportDynamic;
|
||||
S->CanInline = Sym.CanInline;
|
||||
S->Traced = Sym.Traced;
|
||||
S->InVersionScript = Sym.InVersionScript;
|
||||
|
||||
// Print out a log message if --trace-symbol was specified.
|
||||
// This is for debugging.
|
||||
if (S->Traced)
|
||||
printTraceSymbol(S);
|
||||
}
|
||||
|
||||
inline Symbol *SymbolBody::symbol() {
|
||||
assert(!isLocal());
|
||||
return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
|
||||
offsetof(Symbol, Body));
|
||||
}
|
||||
} // namespace elf
|
||||
|
||||
std::string toString(const elf::SymbolBody &B);
|
||||
|
|
|
@ -66,8 +66,8 @@ uint64_t SyntheticSection::getVA() const {
|
|||
// Create a .bss section for each common symbol and replace the common symbol
|
||||
// with a DefinedRegular symbol.
|
||||
template <class ELFT> void elf::createCommonSections() {
|
||||
for (Symbol *S : Symtab->getSymbols()) {
|
||||
auto *Sym = dyn_cast<DefinedCommon>(S->body());
|
||||
for (SymbolBody *S : Symtab->getSymbols()) {
|
||||
auto *Sym = dyn_cast<DefinedCommon>(S);
|
||||
|
||||
if (!Sym)
|
||||
continue;
|
||||
|
@ -1533,8 +1533,7 @@ void SymbolTableBaseSection::postThunkContents() {
|
|||
// move all local symbols before global symbols.
|
||||
auto It = std::stable_partition(
|
||||
Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) {
|
||||
return S.Symbol->isLocal() ||
|
||||
S.Symbol->symbol()->computeBinding() == STB_LOCAL;
|
||||
return S.Symbol->isLocal() || S.Symbol->computeBinding() == STB_LOCAL;
|
||||
});
|
||||
size_t NumLocals = It - Symbols.begin();
|
||||
getParent()->Info = NumLocals + 1;
|
||||
|
@ -1591,8 +1590,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
if (Body->isLocal()) {
|
||||
ESym->setBindingAndType(STB_LOCAL, Body->Type);
|
||||
} else {
|
||||
ESym->setBindingAndType(Body->symbol()->computeBinding(), Body->Type);
|
||||
ESym->setVisibility(Body->symbol()->Visibility);
|
||||
ESym->setBindingAndType(Body->computeBinding(), Body->Type);
|
||||
ESym->setVisibility(Body->Visibility);
|
||||
}
|
||||
|
||||
ESym->st_name = Ent.StrTabOffset;
|
||||
|
@ -2284,7 +2283,7 @@ template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const {
|
|||
template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
|
||||
for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) {
|
||||
OutVersym->vs_index = S.Symbol->symbol()->VersionId;
|
||||
OutVersym->vs_index = S.Symbol->VersionId;
|
||||
++OutVersym;
|
||||
}
|
||||
}
|
||||
|
@ -2307,7 +2306,7 @@ template <class ELFT>
|
|||
void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
|
||||
auto *Ver = reinterpret_cast<const typename ELFT::Verdef *>(SS->Verdef);
|
||||
if (!Ver) {
|
||||
SS->symbol()->VersionId = VER_NDX_GLOBAL;
|
||||
SS->VersionId = VER_NDX_GLOBAL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2327,7 +2326,7 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
|
|||
Ver->getAux()->vda_name);
|
||||
NV.Index = NextIndex++;
|
||||
}
|
||||
SS->symbol()->VersionId = NV.Index;
|
||||
SS->VersionId = NV.Index;
|
||||
}
|
||||
|
||||
template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
|
|
|
@ -425,7 +425,7 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,
|
|||
}
|
||||
|
||||
static bool includeInSymtab(const SymbolBody &B) {
|
||||
if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj)
|
||||
if (!B.isLocal() && !B.IsUsedInRegularObj)
|
||||
return false;
|
||||
|
||||
if (auto *D = dyn_cast<DefinedRegular>(&B)) {
|
||||
|
@ -743,10 +743,10 @@ addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val,
|
|||
SymbolBody *S = Symtab->find(Name);
|
||||
if (!S || S->isInCurrentOutput())
|
||||
return nullptr;
|
||||
Symbol *Sym = Symtab->addRegular<ELFT>(Name, StOther, STT_NOTYPE, Val,
|
||||
/*Size=*/0, Binding, Sec,
|
||||
/*File=*/nullptr);
|
||||
return cast<DefinedRegular>(Sym->body());
|
||||
SymbolBody *Sym = Symtab->addRegular<ELFT>(Name, StOther, STT_NOTYPE, Val,
|
||||
/*Size=*/0, Binding, Sec,
|
||||
/*File=*/nullptr);
|
||||
return cast<DefinedRegular>(Sym);
|
||||
}
|
||||
|
||||
// The beginning and the ending of .rel[a].plt section are marked
|
||||
|
@ -1188,11 +1188,11 @@ static void removeUnusedSyntheticSections() {
|
|||
static bool computeIsPreemptible(const SymbolBody &B) {
|
||||
assert(!B.isLocal());
|
||||
// Only symbols that appear in dynsym can be preempted.
|
||||
if (!B.symbol()->includeInDynsym())
|
||||
if (!B.includeInDynsym())
|
||||
return false;
|
||||
|
||||
// Only default visibility symbols can be preempted.
|
||||
if (B.symbol()->Visibility != STV_DEFAULT)
|
||||
if (B.Visibility != STV_DEFAULT)
|
||||
return false;
|
||||
|
||||
// At this point copy relocations have not been created yet, so any
|
||||
|
@ -1248,8 +1248,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
applySynthetic({InX::EhFrame},
|
||||
[](SyntheticSection *SS) { SS->finalizeContents(); });
|
||||
|
||||
for (Symbol *S : Symtab->getSymbols())
|
||||
S->body()->IsPreemptible |= computeIsPreemptible(*S->body());
|
||||
for (SymbolBody *S : Symtab->getSymbols())
|
||||
S->IsPreemptible |= computeIsPreemptible(*S);
|
||||
|
||||
// Scan relocations. This must be done after every symbol is declared so that
|
||||
// we can correctly decide if a dynamic relocation is needed.
|
||||
|
@ -1263,18 +1263,16 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
|
||||
// Now that we have defined all possible global symbols including linker-
|
||||
// synthesized ones. Visit all symbols to give the finishing touches.
|
||||
for (Symbol *S : Symtab->getSymbols()) {
|
||||
SymbolBody *Body = S->body();
|
||||
|
||||
if (!includeInSymtab(*Body))
|
||||
for (SymbolBody *Sym : Symtab->getSymbols()) {
|
||||
if (!includeInSymtab(*Sym))
|
||||
continue;
|
||||
if (InX::SymTab)
|
||||
InX::SymTab->addSymbol(Body);
|
||||
InX::SymTab->addSymbol(Sym);
|
||||
|
||||
if (InX::DynSymTab && S->includeInDynsym()) {
|
||||
InX::DynSymTab->addSymbol(Body);
|
||||
if (auto *SS = dyn_cast<SharedSymbol>(Body))
|
||||
if (cast<SharedFile<ELFT>>(S->File)->isNeeded())
|
||||
if (InX::DynSymTab && Sym->includeInDynsym()) {
|
||||
InX::DynSymTab->addSymbol(Sym);
|
||||
if (auto *SS = dyn_cast<SharedSymbol>(Sym))
|
||||
if (cast<SharedFile<ELFT>>(Sym->File)->isNeeded())
|
||||
In<ELFT>::VerNeed->addSymbol(SS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,13 +140,13 @@ We will describe the key data structures in LLD in this section.
|
|||
The linker can be understood as the interactions between them.
|
||||
Once you understand their functions, the code of the linker should look obvious to you.
|
||||
|
||||
* SymbolBody
|
||||
* Symbol
|
||||
|
||||
SymbolBody is a class to represent symbols.
|
||||
This class represents a symbol.
|
||||
They are created for symbols in object files or archive files.
|
||||
The linker creates linker-defined symbols as well.
|
||||
|
||||
There are basically three types of SymbolBodies: Defined, Undefined, or Lazy.
|
||||
There are basically three types of Symbols: Defined, Undefined, or Lazy.
|
||||
|
||||
- Defined symbols are for all symbols that are considered as "resolved",
|
||||
including real defined symbols, COMDAT symbols, common symbols,
|
||||
|
@ -156,26 +156,17 @@ Once you understand their functions, the code of the linker should look obvious
|
|||
- Lazy symbols represent symbols we found in archive file headers
|
||||
which can turn into Defined if we read archieve members.
|
||||
|
||||
* Symbol
|
||||
There's only one Symbol instance for each unique symbol name. This uniqueness
|
||||
is guaranteed by the symbol table. As the resolver reads symbols from input
|
||||
files, it replaces an existing Symbol with the "best" Symbol for its symbol
|
||||
name using the placement new.
|
||||
|
||||
A Symbol is a container for a SymbolBody. There's only one Symbol for each
|
||||
unique symbol name (this uniqueness is guaranteed by the symbol table).
|
||||
Each global symbol has only one SymbolBody at any one time, which is
|
||||
the SymbolBody stored within a memory region of the Symbol large enough
|
||||
to store any SymbolBody.
|
||||
|
||||
As the resolver reads symbols from input files, it replaces the Symbol's
|
||||
SymbolBody with the "best" SymbolBody for its symbol name by constructing
|
||||
the new SymbolBody in place on top of the existing SymbolBody. For example,
|
||||
if the resolver is given a defined symbol, and the SymbolBody with its name
|
||||
is undefined, it will construct a Defined SymbolBody over the Undefined
|
||||
SymbolBody.
|
||||
|
||||
This means that each SymbolBody pointer always points to the best SymbolBody,
|
||||
and it is possible to get from a SymbolBody to a Symbol, or vice versa,
|
||||
by adding or subtracting a fixed offset. This memory layout helps reduce
|
||||
the cache miss rate through high locality and a small number of required
|
||||
pointer indirections.
|
||||
The above mechanism allows you to use pointers to Symbols as a very cheap way
|
||||
to access name resolution results. Assume for example that you have a pointer
|
||||
to an undefined symbol before name resolution. If the symbol is resolved to a
|
||||
defined symbol by the resolver, the pointer will "automatically" point to the
|
||||
defined symbol, because the undefined symbol the pointer pointed to will have
|
||||
been replaced by the defined symbol in-place.
|
||||
|
||||
* SymbolTable
|
||||
|
||||
|
@ -221,8 +212,7 @@ There are mainly three actors in this linker.
|
|||
InputFile is a superclass of file readers.
|
||||
We have a different subclass for each input file type,
|
||||
such as regular object file, archive file, etc.
|
||||
They are responsible for creating and owning SymbolBodies and
|
||||
InputSections/Chunks.
|
||||
They are responsible for creating and owning Symbols and InputSections/Chunks.
|
||||
|
||||
* Writer
|
||||
|
||||
|
|
Loading…
Reference in New Issue