Skip to content

Commit 2b6b72c

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.5-bogner
1 parent c3be452 commit 2b6b72c

File tree

7 files changed

+43
-14
lines changed

7 files changed

+43
-14
lines changed

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ struct Config {
368368
bool writeAddends;
369369
bool zCombreloc;
370370
bool zCopyreloc;
371+
bool zDynamicUndefined;
371372
bool zForceBti;
372373
bool zForceIbt;
373374
bool zGlobal;

lld/ELF/Driver.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ static void checkZOptions(Ctx &ctx, opt::InputArgList &args) {
591591
args::getZOptionValue(args, OPT_z, "max-page-size", 0);
592592
args::getZOptionValue(args, OPT_z, "common-page-size", 0);
593593
getZFlag(args, "rel", "rela", false);
594+
getZFlag(args, "dynamic-undefined-weak", "nodynamic-undefined-weak", false);
594595
for (auto *arg : args.filtered(OPT_z))
595596
if (!arg->isClaimed())
596597
Warn(ctx) << "unknown -z value: " << StringRef(arg->getValue());
@@ -3058,6 +3059,13 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
30583059
ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.isPic;
30593060
ctx.arg.exportDynamic &= ctx.hasDynsym;
30603061

3062+
// Preemptibility of undefined symbols when ctx.hasDynsym is true. Default is
3063+
// true for dynamic linking.
3064+
ctx.arg.zDynamicUndefined =
3065+
getZFlag(args, "dynamic-undefined-weak", "nodynamic-undefined-weak",
3066+
ctx.sharedFiles.size() || ctx.arg.shared) &&
3067+
ctx.hasDynsym;
3068+
30613069
// If an entry symbol is in a static archive, pull out that file now.
30623070
if (Symbol *sym = ctx.symtab->find(ctx.arg.entry))
30633071
handleUndefined(ctx, sym, "--entry");

lld/ELF/Symbols.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,13 @@ bool elf::computeIsPreemptible(Ctx &ctx, const Symbol &sym) {
333333
if (sym.visibility() != STV_DEFAULT)
334334
return false;
335335

336-
// At this point copy relocations have not been created yet, so any
337-
// symbol that is not defined locally is preemptible.
336+
// At this point copy relocations have not been created yet.
337+
// Shared symbols are preemptible. Undefined symbols are preemptible
338+
// when zDynamicUndefined (default in dynamic linking). Weakness is not
339+
// checked, though undefined non-weak would typically trigger relocation
340+
// errors unless options like -z undefs are used.
338341
if (!sym.isDefined())
339-
return true;
342+
return !sym.isUndefined() || ctx.arg.zDynamicUndefined;
340343

341344
if (!ctx.arg.shared)
342345
return false;
@@ -360,7 +363,6 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
360363
// can contain versions in the form of <name>@<version>.
361364
// Let them parse and update their names to exclude version suffix.
362365
// In addition, compute isExported and isPreemptible.
363-
bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared;
364366
for (Symbol *sym : ctx.symtab->getSymbols()) {
365367
if (sym->hasVersionSuffix)
366368
sym->parseSymbolVersion(ctx);
@@ -369,11 +371,11 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
369371
continue;
370372
}
371373
if (!sym->isDefined() && !sym->isCommon()) {
372-
sym->isPreemptible = maybePreemptible && computeIsPreemptible(ctx, *sym);
374+
sym->isPreemptible = computeIsPreemptible(ctx, *sym);
373375
} else if (ctx.arg.exportDynamic &&
374376
(sym->isUsedInRegularObj || !sym->ltoCanOmit)) {
375377
sym->isExported = true;
376-
sym->isPreemptible = maybePreemptible && computeIsPreemptible(ctx, *sym);
378+
sym->isPreemptible = computeIsPreemptible(ctx, *sym);
377379
}
378380
}
379381
}

lld/ELF/Writer.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,6 @@ static void demoteDefined(Defined &sym, DenseMap<SectionBase *, size_t> &map) {
285285
static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
286286
llvm::TimeTraceScope timeScope("Demote symbols");
287287
DenseMap<InputFile *, DenseMap<SectionBase *, size_t>> sectionIndexMap;
288-
bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared;
289288
for (Symbol *sym : ctx.symtab->getSymbols()) {
290289
if (auto *d = dyn_cast<Defined>(sym)) {
291290
if (d->section && !d->section->isLive())
@@ -301,9 +300,8 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
301300
}
302301
}
303302

304-
if (maybePreemptible)
305-
sym->isPreemptible = (sym->isUndefined() || sym->isExported) &&
306-
computeIsPreemptible(ctx, *sym);
303+
sym->isPreemptible = (sym->isUndefined() || sym->isExported) &&
304+
computeIsPreemptible(ctx, *sym);
307305
}
308306
}
309307

lld/test/ELF/driver.test

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
# ERR9: error: cannot open output file utput=/no/such/file
4848

4949
# RUN: ld.lld %t -z foo -o /dev/null 2>&1 | FileCheck -check-prefix=ERR10 %s --implicit-check-not=warning:
50-
# RUN: ld.lld %t -z foo -z rel -z rela -z max-page-size=1 -z common-page-size=1 -o /dev/null --version 2>&1 | \
50+
# RUN: ld.lld %t -z foo -z rel -z rela -z max-page-size=1 -z common-page-size=1 -z dynamic-undefined-weak \
51+
# RUN: -z nodynamic-undefined-weak -o /dev/null --version 2>&1 | \
5152
# RUN: FileCheck -check-prefix=ERR10 %s --implicit-check-not=warning:
5253
# ERR10: warning: unknown -z value: foo
5354

lld/test/ELF/weak-undef-got-plt.s

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66

77
# RUN: ld.lld a.o -o a
88
# RUN: llvm-readelf -r a | FileCheck %s --check-prefix=NORELOC
9+
# RUN: ld.lld a.o -o a -z dynamic-undefined-weak
10+
# RUN: llvm-readelf -r a | FileCheck %s --check-prefix=NORELOC
911
# RUN: ld.lld a.o s.so -o as
1012
# RUN: llvm-objdump -dR as | FileCheck %s
13+
# RUN: ld.lld a.o s.so -o as -z nodynamic-undefined-weak
14+
# RUN: llvm-readelf -r a | FileCheck %s --check-prefix=NORELOC
1115

1216
# RUN: ld.lld -pie a.o s.so -o as.pie
1317
# RUN: llvm-objdump -dR as.pie | FileCheck %s
18+
# RUN: ld.lld -pie a.o s.so -o as.pie -z nodynamic-undefined-weak
19+
# RUN: llvm-readelf -r as.pie | FileCheck --check-prefix=NORELOC %s
1420

1521
# RUN: ld.lld -shared a.o -o a.so
1622
# RUN: llvm-objdump -dR a.so | FileCheck %s

lld/test/ELF/weak-undef-rw.s

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,22 @@
1818
## gABI leaves the behavior of weak undefined references implementation defined.
1919
## We choose to resolve them statically for static linking and produce dynamic relocations
2020
## for dynamic linking (-shared or at least one input DSO).
21-
##
22-
## Note: Some ports of GNU ld support -z nodynamic-undefined-weak that we don't
23-
## implement.
21+
22+
## -z dynamic-undefined-weak is ignored if .dynsym is absent (-no-pie without DSO)
23+
# RUN: ld.lld a.o -o a.d -z dynamic-undefined-weak 2>&1 | count 0
24+
# RUN: llvm-readelf -r --hex-dump=.data a.d | FileCheck %s --check-prefix=STATIC
25+
26+
## Currently no effect for S+A relocations.
27+
# RUN: ld.lld a.o s.so -o as.d -z dynamic-undefined-weak
28+
# RUN: llvm-readelf -r --hex-dump=.data as.d | FileCheck %s --check-prefix=STATIC
29+
30+
## -z dynamic-undefined-weak forces dynamic relocations if .dynsym is present.
31+
# RUN: ld.lld a.o -o a.pie.d -pie -z dynamic-undefined-weak
32+
# RUN: llvm-readelf -r a.pie.d | FileCheck %s --check-prefix=DYN
33+
34+
## -z nodynamic-undefined-weak suppresses dynamic relocations.
35+
# RUN: ld.lld a.o -o a.so.n -shared -z dynamic-undefined-weak -z nodynamic-undefined-weak
36+
# RUN: llvm-readelf -r --hex-dump=.data a.so.n | FileCheck %s --check-prefix=STATIC
2437

2538
# STATIC: no relocations
2639
# STATIC: Hex dump of section '.data':

0 commit comments

Comments
 (0)