[llvm-branch-commits] [lld] release/20.x: [ELF] Refine isExported/isPreemptible condition (PR #126848)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Feb 17 16:15:32 PST 2025
https://github.com/llvmbot updated https://github.com/llvm/llvm-project/pull/126848
>From a2b502050302a4cf8a9c4e623331810eed51bb81 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 30 Jan 2025 19:03:38 -0800
Subject: [PATCH 1/3] [ELF] ICF: replace includeInDynsym with isExported
Similar to the change to MarkLive.cpp when isExported was introduced.
includeInDynsym might return true even when isExported is false for
statically linked executables.
(cherry picked from commit 45f538ecba1a51768002a5bc0c194b5af4cd9c27)
---
lld/ELF/Driver.cpp | 2 +-
lld/test/ELF/icf-safe.s | 9 ++++++---
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 2d8a5ade2fece..6121a4254453c 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2434,7 +2434,7 @@ static void findKeepUniqueSections(Ctx &ctx, opt::InputArgList &args) {
// or DSOs, so we conservatively mark them as address-significant.
bool icfSafe = ctx.arg.icf == ICFLevel::Safe;
for (Symbol *sym : ctx.symtab->getSymbols())
- if (sym->includeInDynsym(ctx))
+ if (sym->isExported)
markAddrsig(icfSafe, sym);
// Visit the address-significance table in each object file and mark each
diff --git a/lld/test/ELF/icf-safe.s b/lld/test/ELF/icf-safe.s
index 96776feccbc67..5381532609938 100644
--- a/lld/test/ELF/icf-safe.s
+++ b/lld/test/ELF/icf-safe.s
@@ -1,16 +1,19 @@
# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/shared.s -o %ta.o
+# RUN: ld.lld -shared -soname=ta %ta.o -o %ta.so
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
# RUN: llvm-objcopy %t1.o %t1copy.o
# RUN: llvm-objcopy --localize-symbol=h1 %t1.o %t1changed.o
# RUN: ld.lld -r %t1.o -o %t1reloc.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-safe.s -o %t2.o
-# RUN: ld.lld %t1.o %t2.o -o %t2 --icf=safe --print-icf-sections | FileCheck %s
+# RUN: ld.lld %t1.o %t2.o -o %t2 --icf=safe --print-icf-sections --export-dynamic | FileCheck %s
# RUN: ld.lld %t1copy.o %t2.o -o %t2 --icf=safe --print-icf-sections | FileCheck %s
# RUN: ld.lld %t1.o %t2.o -o %t3 --icf=safe --print-icf-sections -shared | FileCheck --check-prefix=EXPORT %s
-# RUN: ld.lld %t1.o %t2.o -o %t3 --icf=safe --print-icf-sections --export-dynamic | FileCheck --check-prefix=EXPORT %s
+## Exported symbols are suppressed for ICF when dynamic linking is enabled.
+# RUN: ld.lld %t1.o %t2.o %ta.so -o %t3 --icf=safe --print-icf-sections --export-dynamic | FileCheck --check-prefix=EXPORT %s
# RUN: ld.lld %t1.o %t2.o -o %t2 --icf=all --print-icf-sections | FileCheck --check-prefix=ALL %s
-# RUN: ld.lld %t1.o %t2.o -o %t2 --icf=all --print-icf-sections --export-dynamic | FileCheck --check-prefix=ALL-EXPORT %s
+# RUN: ld.lld %t1.o %t2.o %ta.so -o %t2 --icf=all --print-icf-sections --export-dynamic | FileCheck --check-prefix=ALL-EXPORT %s
# RUN: ld.lld %t1changed.o -o %t4 --icf=safe 2>&1 | FileCheck --check-prefix=SH_LINK_0 %s
# RUN: ld.lld %t1reloc.o -o %t4 --icf=safe 2>&1 | FileCheck --check-prefix=SH_LINK_0 %s
>From 02a511e42c6783f14ac45d71c5278dd031c1bcf7 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 30 Jan 2025 22:24:04 -0800
Subject: [PATCH 2/3] [ELF] Merge exportDynamic/isExported and remove
Symbol::includeInDynsym
Commit 3733ed6f1c6b0eef1e13e175ac81ad309fc0b080 introduced isExported to
cache includeInDynsym. If we don't unnecessarily set isExported for
undefined symbols, exportDynamic/includeInDynsym can be replaced with
isExported.
(cherry picked from commit d6fa74ab3d4cc77005836e72a2d6fe222bab4c59)
---
lld/ELF/Driver.cpp | 3 ++-
lld/ELF/InputFiles.cpp | 4 ++--
lld/ELF/SymbolTable.cpp | 8 +++-----
lld/ELF/Symbols.cpp | 27 +++++++++++++--------------
lld/ELF/Symbols.h | 15 +++++----------
lld/ELF/SyntheticSections.cpp | 4 ++--
lld/ELF/Writer.cpp | 13 +++++++------
7 files changed, 34 insertions(+), 40 deletions(-)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 6121a4254453c..391140bce7394 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2575,7 +2575,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 caee72cf31955..d43de8ce6dfef 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1581,7 +1581,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);
@@ -1778,7 +1778,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 975700505facb..b8a70d4e898fc 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 b10391c65dfdc..890877cb1bc04 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 48df6f60db864..64f2f6eaa8d09 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 eb07d82fc9601..ffa6e3c008c48 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -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);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 6c7bcee02047b..3ba1cdbce572b 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 <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);
@@ -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())
>From 9bcc825ee491a85c2f7b1573d6a3abf6d5cf0c8a Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 5 Feb 2025 21:16:00 -0800
Subject: [PATCH 3/3] [ELF] Refine isExported/isPreemptible condition
Reland 994cea3f0a2d0caf4d66321ad5a06ab330144d89 after bolt tests no
longer rely on -pie --unresolved-symbols=ignore-all with no input DSO
generating PLT entries.
---
Commit f10441ad003236ef3b9e5415a571d2be0c0ce5ce , while dropping a
special case for isUndefWeak and --no-dynamic-linking, made
--export-dynamic ineffective when -pie is used without any input DSO.
This change restores --export-dynamic and unifies -pie and -pie
--no-dynamic-linker when there is no input DSO.
* -pie with no input DSO suppresses undefined symbols in .dynsym.
Previously this only appied to -pie --no-dynamic-linker.
* As a side effect, -pie with no input DSO suppresses PLT.
(cherry picked from commit 52fc6ffcda0895c0c7b976ad1f5cb5a282b571d2)
---
lld/ELF/Config.h | 2 --
lld/ELF/Driver.cpp | 11 ++---------
lld/ELF/Symbols.cpp | 4 +++-
lld/ELF/SyntheticSections.cpp | 4 ++--
lld/ELF/Writer.cpp | 11 ++++++-----
lld/test/ELF/executable-undefined-ignoreall.s | 6 ++++--
lld/test/ELF/ppc32-weak-undef-call.s | 6 +++---
lld/test/ELF/ppc64-undefined-weak.s | 16 ++++++++--------
lld/test/ELF/riscv-gp.s | 13 ++++++++-----
lld/test/ELF/weak-undef-lib.s | 2 +-
lld/test/ELF/weak-undef-no-dynamic-linker.s | 7 +++----
lld/test/ELF/weak-undef-rw.s | 16 ++++++++--------
12 files changed, 48 insertions(+), 50 deletions(-)
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 98e52b52ea46a..9826ed0517337 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -292,7 +292,6 @@ struct Config {
bool gdbIndex;
bool gnuHash = false;
bool gnuUnique;
- bool hasDynSymTab;
bool ignoreDataAddressEquality;
bool ignoreFunctionAddressEquality;
bool ltoCSProfileGenerate;
@@ -306,7 +305,6 @@ struct Config {
bool mipsN32Abi = false;
bool mmapOutputFile;
bool nmagic;
- bool noDynamicLinker = false;
bool noinhibitExec;
bool nostdlib;
bool oFormatBinary;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 391140bce7394..a1e9ecae08557 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -781,11 +781,8 @@ static StringRef getDynamicLinker(Ctx &ctx, opt::InputArgList &args) {
auto *arg = args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker);
if (!arg)
return "";
- if (arg->getOption().getID() == OPT_no_dynamic_linker) {
- // --no-dynamic-linker suppresses undefined weak symbols in .dynsym
- ctx.arg.noDynamicLinker = true;
+ if (arg->getOption().getID() == OPT_no_dynamic_linker)
return "";
- }
return arg->getValue();
}
@@ -2921,12 +2918,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
parseFiles(ctx, files);
- // Dynamic linking is used if there is an input DSO,
- // or -shared or non-static pie is specified.
- ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.shared ||
- (ctx.arg.pie && !ctx.arg.noDynamicLinker);
// Create dynamic sections for dynamic linking and static PIE.
- ctx.arg.hasDynSymTab = ctx.hasDynsym || ctx.arg.isPic;
+ ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.isPic;
// If an entry symbol is in a static archive, pull out that file now.
if (Symbol *sym = ctx.symtab->find(ctx.arg.entry))
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 890877cb1bc04..80b0691428007 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -360,7 +360,9 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
// 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.
+ // In addition, compute isExported and isPreemptible.
bool hasDynsym = ctx.hasDynsym;
+ bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared;
for (Symbol *sym : ctx.symtab->getSymbols()) {
if (sym->hasVersionSuffix)
sym->parseSymbolVersion(ctx);
@@ -371,7 +373,7 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
continue;
}
if (!sym->isDefined() && !sym->isCommon()) {
- sym->isPreemptible = computeIsPreemptible(ctx, *sym);
+ sym->isPreemptible = maybePreemptible && computeIsPreemptible(ctx, *sym);
} else if (ctx.arg.exportDynamic &&
(sym->isUsedInRegularObj || !sym->ltoCanOmit)) {
sym->isExported = true;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index ffa6e3c008c48..b03c4282ab1aa 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -4740,7 +4740,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
// Add MIPS-specific sections.
if (ctx.arg.emachine == EM_MIPS) {
- if (!ctx.arg.shared && ctx.arg.hasDynSymTab) {
+ if (!ctx.arg.shared && ctx.hasDynsym) {
ctx.in.mipsRldMap = std::make_unique<MipsRldMapSection>(ctx);
add(*ctx.in.mipsRldMap);
}
@@ -4803,7 +4803,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
part.relaDyn = std::make_unique<RelocationSection<ELFT>>(
ctx, relaDynName, ctx.arg.zCombreloc, threadCount);
- if (ctx.arg.hasDynSymTab) {
+ if (ctx.hasDynsym) {
add(*part.dynSymTab);
part.verSym = std::make_unique<VersionTableSection>(ctx);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 3ba1cdbce572b..0db922b07aabf 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -284,6 +284,7 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
llvm::TimeTraceScope timeScope("Demote symbols");
DenseMap<InputFile *, DenseMap<SectionBase *, size_t>> sectionIndexMap;
bool hasDynsym = ctx.hasDynsym;
+ bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared;
for (Symbol *sym : ctx.symtab->getSymbols()) {
if (auto *d = dyn_cast<Defined>(sym)) {
if (d->section && !d->section->isLive())
@@ -300,7 +301,8 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
}
if (hasDynsym)
- sym->isPreemptible = (sym->isUndefined() || sym->isExported) &&
+ sym->isPreemptible = maybePreemptible &&
+ (sym->isUndefined() || sym->isExported) &&
computeIsPreemptible(ctx, *sym);
}
}
@@ -1929,10 +1931,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (ctx.in.symTab)
ctx.in.symTab->addSymbol(sym);
- // computeBinding might localize a linker-synthesized hidden symbol
- // (e.g. __global_pointer$) that was considered exported.
- if (ctx.hasDynsym && (sym->isUndefined() || sym->isExported) &&
- !sym->isLocal()) {
+ // computeBinding might localize a symbol that was considered exported
+ // but then synthesized as hidden (e.g. _DYNAMIC).
+ if ((sym->isExported || sym->isPreemptible) && !sym->isLocal()) {
ctx.partitions[sym->partition - 1].dynSymTab->addSymbol(sym);
if (auto *file = dyn_cast<SharedFile>(sym->file))
if (file->isNeeded && !sym->isUndefined())
diff --git a/lld/test/ELF/executable-undefined-ignoreall.s b/lld/test/ELF/executable-undefined-ignoreall.s
index 073b22bd84543..1f83b1b61830a 100644
--- a/lld/test/ELF/executable-undefined-ignoreall.s
+++ b/lld/test/ELF/executable-undefined-ignoreall.s
@@ -1,11 +1,13 @@
# REQUIRES: x86
-## --unresolved-symbols=ignore-all behaves similar to -shared:
+## In dynamic linking, --unresolved-symbols=ignore-all behaves similar to -shared:
## for PLT relocations to undefined symbols, produce dynamic relocations if we
## emit .dynsym.
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/shared.s -o %ta.o
+# RUN: ld.lld -shared -soname=ta %ta.o -o %ta.so
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
-# RUN: ld.lld %t.o -o %t --unresolved-symbols=ignore-all -pie
+# RUN: ld.lld %t.o %ta.so -o %t --unresolved-symbols=ignore-all -pie
# RUN: llvm-readobj -r %t | FileCheck %s
# CHECK: Relocations [
diff --git a/lld/test/ELF/ppc32-weak-undef-call.s b/lld/test/ELF/ppc32-weak-undef-call.s
index dfb45e5fe18cf..1ad280a49c038 100644
--- a/lld/test/ELF/ppc32-weak-undef-call.s
+++ b/lld/test/ELF/ppc32-weak-undef-call.s
@@ -1,15 +1,15 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
# RUN: ld.lld %t.o -o %t
-# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PDE %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=STATIC %s
# RUN: ld.lld -pie %t.o -o %t
-# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PIC %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=STATIC %s
# RUN: ld.lld -shared %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PIC %s
## It does not really matter how we fixup it, but we cannot overflow and
## should not generate a call stub (this would waste space).
-# PDE: bl 0x100100b4
+# STATIC: bl {{.*}} <.text>
## With -pie or -shared, create a call stub. ld.bfd produces bl .+0
# PIC: bl 0x[[PLT:[0-9a-f]+]]
diff --git a/lld/test/ELF/ppc64-undefined-weak.s b/lld/test/ELF/ppc64-undefined-weak.s
index 7b1be5e36dd32..e9168020b216f 100644
--- a/lld/test/ELF/ppc64-undefined-weak.s
+++ b/lld/test/ELF/ppc64-undefined-weak.s
@@ -2,25 +2,25 @@
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
# RUN: ld.lld %t.o -o %t
-# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC
# RUN: ld.lld -pie %t.o -o %t
-# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PIC
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC
# RUN: ld.lld -shared %t.o -o %t.so
# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s --check-prefix=PIC
# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o
# RUN: ld.lld %t.o -o %t
-# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC
## Branches to an undefined weak symbol need a thunk iff a dynamic relocation is
## produced. undefweak2 is hidden and does not need a dynamic relocation, so we
## suppress the thunk. undefweak1 needs a thunk iff -pie or -shared.
-# PDE-LABEL: <_start>:
-# PDE-NEXT: bl {{.*}} <_start>
-# PDE-NEXT: nop
-# PDE-NEXT: bl {{.*}} <_start+0x8>
-# PDE-NEXT: nop
+# STATIC-LABEL: <_start>:
+# STATIC-NEXT: bl {{.*}} <_start>
+# STATIC-NEXT: nop
+# STATIC-NEXT: bl {{.*}} <_start+0x8>
+# STATIC-NEXT: nop
# PIC-LABEL: <_start>:
# PIC-NEXT: bl {{.*}} <__plt_undefweak1>
diff --git a/lld/test/ELF/riscv-gp.s b/lld/test/ELF/riscv-gp.s
index a30f5e9fbc625..2f715e1470f2d 100644
--- a/lld/test/ELF/riscv-gp.s
+++ b/lld/test/ELF/riscv-gp.s
@@ -14,17 +14,20 @@
# SEC32: {{0*}}000039c0 0 NOTYPE GLOBAL DEFAULT [[#SDATA]] __global_pointer$
# SEC64: [ [[#SDATA:]]] .sdata PROGBITS {{0*}}000032e0
+# SEC64: '.dynsym'
+# SEC64-NOT: __global_pointer$
+# SEC64: '.symtab'
# SEC64: {{0*}}00003ae0 0 NOTYPE GLOBAL DEFAULT [[#SDATA]] __global_pointer$
# ERR: error: relocation R_RISCV_PCREL_HI20 cannot be used against symbol '__global_pointer$'; recompile with -fPIC
# RUN: ld.lld -pie --no-dynamic-linker --export-dynamic %t.64.o -o %t.64e
-# RUN: llvm-readelf -s %t.64e | FileCheck %s --check-prefix=STATICPIE
+# RUN: llvm-readelf -s %t.64e | FileCheck %s --check-prefix=STATICE
-# STATICPIE: '.dynsym'
-# STATICPIE-NOT: __global_pointer$
-# STATICPIE: '.symtab'
-# STATICPIE: __global_pointer$
+# STATICE: '.dynsym'
+# STATICE: __global_pointer$
+# STATICE: '.symtab'
+# STATICE: __global_pointer$
## -r mode does not define __global_pointer$.
# RUN: ld.lld -r %t.64.o -o %t.64.ro
diff --git a/lld/test/ELF/weak-undef-lib.s b/lld/test/ELF/weak-undef-lib.s
index a554e1d5a2f89..0ff1bc755f075 100644
--- a/lld/test/ELF/weak-undef-lib.s
+++ b/lld/test/ELF/weak-undef-lib.s
@@ -7,7 +7,7 @@
# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
# RUN: ld.lld -pie -o %t %t1.o --start-lib %t2.o
-# RUN: llvm-readobj --dyn-syms %t | FileCheck %s
+# RUN: llvm-readelf --dyn-syms %t | FileCheck %s --check-prefix=STATICPIE
# CHECK: Name: foo
# CHECK-NEXT: Value: 0x0
diff --git a/lld/test/ELF/weak-undef-no-dynamic-linker.s b/lld/test/ELF/weak-undef-no-dynamic-linker.s
index fa6936e1ef393..11abd5351af9d 100644
--- a/lld/test/ELF/weak-undef-no-dynamic-linker.s
+++ b/lld/test/ELF/weak-undef-no-dynamic-linker.s
@@ -1,13 +1,12 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: ld.lld -pie %t.o -o %t
-# RUN: llvm-readobj --dyn-syms %t | FileCheck %s
+# RUN: llvm-readobj --dyn-syms %t | FileCheck --check-prefix=NO %s
# RUN: ld.lld -pie --no-dynamic-linker %t.o -o %t
# RUN: llvm-readobj --dyn-syms %t | FileCheck --check-prefix=NO %s
-## With --no-dynamic-linker, don't emit undefined weak symbols to .dynsym .
-## This will suppress a relocation.
-# CHECK: Name: foo
+## With static PIE (whether or not --no-dynamic-linker is specified), don't
+## emit undefined weak symbols to .dynsym . This suppresses relocations.
# NO-NOT: Name: foo
.weak foo
diff --git a/lld/test/ELF/weak-undef-rw.s b/lld/test/ELF/weak-undef-rw.s
index ec3e4ce734895..c5cf1bdcaba68 100644
--- a/lld/test/ELF/weak-undef-rw.s
+++ b/lld/test/ELF/weak-undef-rw.s
@@ -1,23 +1,23 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: ld.lld %t.o -o %t --export-dynamic
-# RUN: llvm-readelf -r --hex-dump=.data %t | FileCheck %s --check-prefix=NOPIC
+# RUN: llvm-readelf -r --hex-dump=.data %t | FileCheck %s --check-prefix=STATIC
# RUN: ld.lld %t.o -o %t.pie -pie
-# RUN: llvm-readobj -r %t.pie | FileCheck %s --check-prefix=PIC
+# RUN: llvm-readelf -r --hex-dump=.data %t.pie | FileCheck %s --check-prefix=STATIC
# RUN: ld.lld %t.o -o %t.so -shared
# RUN: llvm-readobj -r %t.so | FileCheck %s --check-prefix=PIC
## gABI leaves the behavior of weak undefined references implementation defined.
-## We choose to resolve them statically for -no-pie and produce dynamic relocations
-## for -pie and -shared.
+## We choose to resolve them statically for static linking and produce dynamic relocations
+## for dynamic linking (-shared or at least one input DSO).
##
## Note: Some ports of GNU ld support -z nodynamic-undefined-weak that we don't
## implement.
-# NOPIC: no relocations
-# NOPIC: Hex dump of section '.data':
-# NOPIC-NEXT: {{.*}} 00000000 00000000
-# NOPIC-EMPTY:
+# STATIC: no relocations
+# STATIC: Hex dump of section '.data':
+# STATIC-NEXT: {{.*}} 00000000 00000000 .
+# STATIC-EMPTY:
# PIC: .rela.dyn {
# PIC-NEXT: R_X86_64_64 foobar 0x0
More information about the llvm-branch-commits
mailing list