Skip to content

Commit

Permalink
[ELF] Merge exportDynamic/isExported and remove Symbol::includeInDynsym
Browse files Browse the repository at this point in the history
Commit 3733ed6 introduced isExported to
cache includeInDynsym. If we don't unnecessarily set isExported for
undefined symbols, exportDynamic/includeInDynsym can be replaced with
isExported.
  • Loading branch information
MaskRay committed Jan 31, 2025
1 parent 3b2f4f4 commit d6fa74a
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 40 deletions.
3 changes: 2 additions & 1 deletion lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2554,7 +2554,8 @@ void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
for (Symbol *sym : obj->getGlobalSymbols()) {
if (!sym->isDefined())
continue;
if (ctx.hasDynsym && sym->includeInDynsym(ctx))
if (ctx.hasDynsym && ctx.arg.exportDynamic &&
sym->computeBinding(ctx) != STB_LOCAL)
sym->isExported = true;
if (sym->hasVersionSuffix)
sym->parseSymbolVersion(ctx);
Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,7 +1574,7 @@ template <class ELFT> void SharedFile::parse() {
}
Symbol *s = ctx.symtab->addSymbol(
Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()});
s->exportDynamic = true;
s->isExported = true;
if (sym.getBinding() != STB_WEAK &&
ctx.arg.unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore)
requiredSymbols.push_back(s);
Expand Down Expand Up @@ -1771,7 +1771,7 @@ static void createBitcodeSymbol(Ctx &ctx, Symbol *&sym,
nullptr);
// The definition can be omitted if all bitcode definitions satisfy
// `canBeOmittedFromSymbolTable()` and isUsedInRegularObj is false.
// The latter condition is tested in Symbol::includeInDynsym.
// The latter condition is tested in parseVersionAndComputeIsPreemptible.
sym->ltoCanOmit = objSym.canBeOmittedFromSymbolTable() &&
(!sym->isDefined() || sym->ltoCanOmit);
sym->resolve(ctx, newSym);
Expand Down
8 changes: 3 additions & 5 deletions lld/ELF/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ void SymbolTable::handleDynamicList() {
syms = findByVersion(ver);

for (Symbol *sym : syms)
sym->exportDynamic = sym->inDynamicList = true;
sym->isExported = sym->inDynamicList = true;
}
}

Expand Down Expand Up @@ -350,10 +350,8 @@ void SymbolTable::scanVersionScript() {
assignAsterisk(pat, &v, true);
}

// isPreemptible is false at this point. To correctly compute the binding of a
// Defined (which is used by includeInDynsym(ctx)), we need to know if it is
// VER_NDX_LOCAL or not. Compute symbol versions before handling
// --dynamic-list.
// Handle --dynamic-list. If a specified symbol is also matched by local: in a
// version script, the version script takes precedence.
handleDynamicList();
}

Expand Down
27 changes: 13 additions & 14 deletions lld/ELF/Symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,16 +268,6 @@ uint8_t Symbol::computeBinding(Ctx &ctx) const {
return binding;
}

bool Symbol::includeInDynsym(Ctx &ctx) const {
if (computeBinding(ctx) == STB_LOCAL)
return false;
if (!isDefined() && !isCommon())
return true;

return exportDynamic ||
(ctx.arg.exportDynamic && (isUsedInRegularObj || !ltoCanOmit));
}

// Print out a log message for --trace-symbol.
void elf::printTraceSymbol(const Symbol &sym, StringRef name) {
std::string s;
Expand Down Expand Up @@ -374,9 +364,18 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
for (Symbol *sym : ctx.symtab->getSymbols()) {
if (sym->hasVersionSuffix)
sym->parseSymbolVersion(ctx);
if (hasDynsym) {
sym->isExported = sym->includeInDynsym(ctx);
sym->isPreemptible = sym->isExported && computeIsPreemptible(ctx, *sym);
if (!hasDynsym)
continue;
if (sym->computeBinding(ctx) == STB_LOCAL) {
sym->isExported = false;
continue;
}
if (!sym->isDefined() && !sym->isCommon()) {
sym->isPreemptible = computeIsPreemptible(ctx, *sym);
} else if (ctx.arg.exportDynamic &&
(sym->isUsedInRegularObj || !sym->ltoCanOmit)) {
sym->isExported = true;
sym->isPreemptible = computeIsPreemptible(ctx, *sym);
}
}
}
Expand Down Expand Up @@ -655,7 +654,7 @@ void Symbol::resolve(Ctx &ctx, const LazySymbol &other) {
}

void Symbol::resolve(Ctx &ctx, const SharedSymbol &other) {
exportDynamic = true;
isExported = true;
if (isPlaceholder()) {
other.overwrite(*this);
return;
Expand Down
15 changes: 5 additions & 10 deletions lld/ELF/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ class Symbol {
uint8_t partition;

// True if this symbol is preemptible at load time.
//
// Primarily set in two locations, (a) parseVersionAndComputeIsPreemptible and
// (b) demoteSymbolsAndComputeIsPreemptible.
LLVM_PREFERRED_TYPE(bool)
uint8_t isPreemptible : 1;

Expand All @@ -131,16 +134,9 @@ class Symbol {
// - If -shared or --export-dynamic is specified, any symbol in an object
// file/bitcode sets this property, unless suppressed by LTO
// canBeOmittedFromSymbolTable().
//
// Primarily set in two locations, (a) after parseSymbolVersion and
// (b) during demoteSymbols.
LLVM_PREFERRED_TYPE(bool)
uint8_t isExported : 1;

// Used to compute isExported. Set when defined or referenced by a SharedFile.
LLVM_PREFERRED_TYPE(bool)
uint8_t exportDynamic : 1;

LLVM_PREFERRED_TYPE(bool)
uint8_t ltoCanOmit : 1;

Expand All @@ -159,7 +155,6 @@ class Symbol {
stOther = (stOther & ~3) | visibility;
}

bool includeInDynsym(Ctx &) const;
uint8_t computeBinding(Ctx &) const;
bool isGlobal() const { return binding == llvm::ELF::STB_GLOBAL; }
bool isWeak() const { return binding == llvm::ELF::STB_WEAK; }
Expand Down Expand Up @@ -247,8 +242,8 @@ class Symbol {
Symbol(Kind k, InputFile *file, StringRef name, uint8_t binding,
uint8_t stOther, uint8_t type)
: file(file), nameData(name.data()), nameSize(name.size()), type(type),
binding(binding), stOther(stOther), symbolKind(k), exportDynamic(false),
ltoCanOmit(false), archSpecificBit(false) {}
binding(binding), stOther(stOther), symbolKind(k), ltoCanOmit(false),
archSpecificBit(false) {}

void overwrite(Symbol &sym, Kind k) const {
if (sym.traced)
Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4776,8 +4776,8 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
add(*part.buildId);
}

// dynSymTab is always present to simplify sym->includeInDynsym(ctx) in
// finalizeSections.
// dynSymTab is always present to simplify several finalizeSections
// functions.
part.dynStrTab = std::make_unique<StringTableSection>(ctx, ".dynstr", true);
part.dynSymTab =
std::make_unique<SymbolTableSection<ELFT>>(ctx, *part.dynStrTab);
Expand Down
13 changes: 7 additions & 6 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,12 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
sym->type)
.overwrite(*sym);
sym->versionId = VER_NDX_GLOBAL;
if (hasDynsym && sym->includeInDynsym(ctx))
sym->isExported = true;
}
}

if (hasDynsym)
sym->isPreemptible = sym->isExported && computeIsPreemptible(ctx, *sym);
sym->isPreemptible = (sym->isUndefined() || sym->isExported) &&
computeIsPreemptible(ctx, *sym);
}
}

Expand Down Expand Up @@ -1841,9 +1840,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {

// If the previous code block defines any non-hidden symbols (e.g.
// __global_pointer$), they may be exported.
if (ctx.hasDynsym)
if (ctx.hasDynsym && ctx.arg.exportDynamic)
for (Symbol *sym : ctx.synthesizedSymbols)
sym->isExported = sym->includeInDynsym(ctx);
if (sym->computeBinding(ctx) != STB_LOCAL)
sym->isExported = true;

demoteSymbolsAndComputeIsPreemptible(ctx);

Expand Down Expand Up @@ -1931,7 +1931,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {

// computeBinding might localize a linker-synthesized hidden symbol
// (e.g. __global_pointer$) that was considered exported.
if (sym->isExported && !sym->isLocal()) {
if (ctx.hasDynsym && (sym->isUndefined() || sym->isExported) &&
!sym->isLocal()) {
ctx.partitions[sym->partition - 1].dynSymTab->addSymbol(sym);
if (auto *file = dyn_cast<SharedFile>(sym->file))
if (file->isNeeded && !sym->isUndefined())
Expand Down

0 comments on commit d6fa74a

Please sign in to comment.