diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 98523429a5078c..acbc97b331b0e1 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -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); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 42d0e4c202ec61..16943c484d96bc 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1574,7 +1574,7 @@ template 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); @@ -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); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 975700505facb4..b8a70d4e898fc2 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -203,7 +203,7 @@ void SymbolTable::handleDynamicList() { syms = findByVersion(ver); for (Symbol *sym : syms) - sym->exportDynamic = sym->inDynamicList = true; + sym->isExported = sym->inDynamicList = true; } } @@ -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(); } diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index b10391c65dfdc3..890877cb1bc046 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -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; @@ -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); } } } @@ -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; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 48df6f60db864b..64f2f6eaa8d09d 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -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; @@ -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; @@ -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; } @@ -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) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index eb07d82fc96012..ffa6e3c008c48e 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4776,8 +4776,8 @@ template 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(ctx, ".dynstr", true); part.dynSymTab = std::make_unique>(ctx, *part.dynStrTab); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 6c7bcee02047b5..3ba1cdbce572b7 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -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); } } @@ -1841,9 +1840,10 @@ template void Writer::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); @@ -1931,7 +1931,8 @@ template void Writer::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(sym->file)) if (file->isNeeded && !sym->isUndefined())