Skip to content

Commit 52fc6ff

Browse files
committed
[ELF] Refine isExported/isPreemptible condition
Reland 994cea3 after bolt tests no longer rely on -pie --unresolved-symbols=ignore-all with no input DSO generating PLT entries. --- Commit f10441a , 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.
1 parent 9d88ffe commit 52fc6ff

12 files changed

+48
-50
lines changed

lld/ELF/Config.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ struct Config {
298298
bool gdbIndex;
299299
bool gnuHash = false;
300300
bool gnuUnique;
301-
bool hasDynSymTab;
302301
bool ignoreDataAddressEquality;
303302
bool ignoreFunctionAddressEquality;
304303
bool ltoCSProfileGenerate;
@@ -312,7 +311,6 @@ struct Config {
312311
bool mipsN32Abi = false;
313312
bool mmapOutputFile;
314313
bool nmagic;
315-
bool noDynamicLinker = false;
316314
bool noinhibitExec;
317315
bool nostdlib;
318316
bool oFormatBinary;

lld/ELF/Driver.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -781,11 +781,8 @@ static StringRef getDynamicLinker(Ctx &ctx, opt::InputArgList &args) {
781781
auto *arg = args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker);
782782
if (!arg)
783783
return "";
784-
if (arg->getOption().getID() == OPT_no_dynamic_linker) {
785-
// --no-dynamic-linker suppresses undefined weak symbols in .dynsym
786-
ctx.arg.noDynamicLinker = true;
784+
if (arg->getOption().getID() == OPT_no_dynamic_linker)
787785
return "";
788-
}
789786
return arg->getValue();
790787
}
791788

@@ -2948,12 +2945,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
29482945

29492946
parseFiles(ctx, files);
29502947

2951-
// Dynamic linking is used if there is an input DSO,
2952-
// or -shared or non-static pie is specified.
2953-
ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.shared ||
2954-
(ctx.arg.pie && !ctx.arg.noDynamicLinker);
29552948
// Create dynamic sections for dynamic linking and static PIE.
2956-
ctx.arg.hasDynSymTab = ctx.hasDynsym || ctx.arg.isPic;
2949+
ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.isPic;
29572950

29582951
// If an entry symbol is in a static archive, pull out that file now.
29592952
if (Symbol *sym = ctx.symtab->find(ctx.arg.entry))

lld/ELF/Symbols.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,9 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
360360
// Symbol themselves might know their versions because symbols
361361
// can contain versions in the form of <name>@<version>.
362362
// Let them parse and update their names to exclude version suffix.
363+
// In addition, compute isExported and isPreemptible.
363364
bool hasDynsym = ctx.hasDynsym;
365+
bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared;
364366
for (Symbol *sym : ctx.symtab->getSymbols()) {
365367
if (sym->hasVersionSuffix)
366368
sym->parseSymbolVersion(ctx);
@@ -371,7 +373,7 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
371373
continue;
372374
}
373375
if (!sym->isDefined() && !sym->isCommon()) {
374-
sym->isPreemptible = computeIsPreemptible(ctx, *sym);
376+
sym->isPreemptible = maybePreemptible && computeIsPreemptible(ctx, *sym);
375377
} else if (ctx.arg.exportDynamic &&
376378
(sym->isUsedInRegularObj || !sym->ltoCanOmit)) {
377379
sym->isExported = true;

lld/ELF/SyntheticSections.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4740,7 +4740,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
47404740

47414741
// Add MIPS-specific sections.
47424742
if (ctx.arg.emachine == EM_MIPS) {
4743-
if (!ctx.arg.shared && ctx.arg.hasDynSymTab) {
4743+
if (!ctx.arg.shared && ctx.hasDynsym) {
47444744
ctx.in.mipsRldMap = std::make_unique<MipsRldMapSection>(ctx);
47454745
add(*ctx.in.mipsRldMap);
47464746
}
@@ -4803,7 +4803,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
48034803
part.relaDyn = std::make_unique<RelocationSection<ELFT>>(
48044804
ctx, relaDynName, ctx.arg.zCombreloc, threadCount);
48054805

4806-
if (ctx.arg.hasDynSymTab) {
4806+
if (ctx.hasDynsym) {
48074807
add(*part.dynSymTab);
48084808

48094809
part.verSym = std::make_unique<VersionTableSection>(ctx);

lld/ELF/Writer.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
285285
llvm::TimeTraceScope timeScope("Demote symbols");
286286
DenseMap<InputFile *, DenseMap<SectionBase *, size_t>> sectionIndexMap;
287287
bool hasDynsym = ctx.hasDynsym;
288+
bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared;
288289
for (Symbol *sym : ctx.symtab->getSymbols()) {
289290
if (auto *d = dyn_cast<Defined>(sym)) {
290291
if (d->section && !d->section->isLive())
@@ -301,7 +302,8 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
301302
}
302303

303304
if (hasDynsym)
304-
sym->isPreemptible = (sym->isUndefined() || sym->isExported) &&
305+
sym->isPreemptible = maybePreemptible &&
306+
(sym->isUndefined() || sym->isExported) &&
305307
computeIsPreemptible(ctx, *sym);
306308
}
307309
}
@@ -1940,10 +1942,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
19401942
if (ctx.in.symTab)
19411943
ctx.in.symTab->addSymbol(sym);
19421944

1943-
// computeBinding might localize a linker-synthesized hidden symbol
1944-
// (e.g. __global_pointer$) that was considered exported.
1945-
if (ctx.hasDynsym && (sym->isUndefined() || sym->isExported) &&
1946-
!sym->isLocal()) {
1945+
// computeBinding might localize a symbol that was considered exported
1946+
// but then synthesized as hidden (e.g. _DYNAMIC).
1947+
if ((sym->isExported || sym->isPreemptible) && !sym->isLocal()) {
19471948
ctx.partitions[sym->partition - 1].dynSymTab->addSymbol(sym);
19481949
if (auto *file = dyn_cast<SharedFile>(sym->file))
19491950
if (file->isNeeded && !sym->isUndefined())

lld/test/ELF/executable-undefined-ignoreall.s

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
# REQUIRES: x86
22

3-
## --unresolved-symbols=ignore-all behaves similar to -shared:
3+
## In dynamic linking, --unresolved-symbols=ignore-all behaves similar to -shared:
44
## for PLT relocations to undefined symbols, produce dynamic relocations if we
55
## emit .dynsym.
66

7+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/shared.s -o %ta.o
8+
# RUN: ld.lld -shared -soname=ta %ta.o -o %ta.so
79
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
8-
# RUN: ld.lld %t.o -o %t --unresolved-symbols=ignore-all -pie
10+
# RUN: ld.lld %t.o %ta.so -o %t --unresolved-symbols=ignore-all -pie
911
# RUN: llvm-readobj -r %t | FileCheck %s
1012

1113
# CHECK: Relocations [

lld/test/ELF/ppc32-weak-undef-call.s

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# REQUIRES: ppc
22
# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
33
# RUN: ld.lld %t.o -o %t
4-
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PDE %s
4+
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=STATIC %s
55
# RUN: ld.lld -pie %t.o -o %t
6-
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PIC %s
6+
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=STATIC %s
77
# RUN: ld.lld -shared %t.o -o %t
88
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PIC %s
99

1010
## It does not really matter how we fixup it, but we cannot overflow and
1111
## should not generate a call stub (this would waste space).
12-
# PDE: bl 0x100100b4
12+
# STATIC: bl {{.*}} <.text>
1313

1414
## With -pie or -shared, create a call stub. ld.bfd produces bl .+0
1515
# PIC: bl 0x[[PLT:[0-9a-f]+]]

lld/test/ELF/ppc64-undefined-weak.s

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@
22

33
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
44
# RUN: ld.lld %t.o -o %t
5-
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE
5+
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC
66
# RUN: ld.lld -pie %t.o -o %t
7-
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PIC
7+
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC
88
# RUN: ld.lld -shared %t.o -o %t.so
99
# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s --check-prefix=PIC
1010

1111
# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o
1212
# RUN: ld.lld %t.o -o %t
13-
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE
13+
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC
1414

1515
## Branches to an undefined weak symbol need a thunk iff a dynamic relocation is
1616
## produced. undefweak2 is hidden and does not need a dynamic relocation, so we
1717
## suppress the thunk. undefweak1 needs a thunk iff -pie or -shared.
1818

19-
# PDE-LABEL: <_start>:
20-
# PDE-NEXT: bl {{.*}} <_start>
21-
# PDE-NEXT: nop
22-
# PDE-NEXT: bl {{.*}} <_start+0x8>
23-
# PDE-NEXT: nop
19+
# STATIC-LABEL: <_start>:
20+
# STATIC-NEXT: bl {{.*}} <_start>
21+
# STATIC-NEXT: nop
22+
# STATIC-NEXT: bl {{.*}} <_start+0x8>
23+
# STATIC-NEXT: nop
2424

2525
# PIC-LABEL: <_start>:
2626
# PIC-NEXT: bl {{.*}} <__plt_undefweak1>

lld/test/ELF/riscv-gp.s

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,20 @@
1414
# SEC32: {{0*}}000039c0 0 NOTYPE GLOBAL DEFAULT [[#SDATA]] __global_pointer$
1515

1616
# SEC64: [ [[#SDATA:]]] .sdata PROGBITS {{0*}}000032e0
17+
# SEC64: '.dynsym'
18+
# SEC64-NOT: __global_pointer$
19+
# SEC64: '.symtab'
1720
# SEC64: {{0*}}00003ae0 0 NOTYPE GLOBAL DEFAULT [[#SDATA]] __global_pointer$
1821

1922
# ERR: error: relocation R_RISCV_PCREL_HI20 cannot be used against symbol '__global_pointer$'; recompile with -fPIC
2023

2124
# RUN: ld.lld -pie --no-dynamic-linker --export-dynamic %t.64.o -o %t.64e
22-
# RUN: llvm-readelf -s %t.64e | FileCheck %s --check-prefix=STATICPIE
25+
# RUN: llvm-readelf -s %t.64e | FileCheck %s --check-prefix=STATICE
2326

24-
# STATICPIE: '.dynsym'
25-
# STATICPIE-NOT: __global_pointer$
26-
# STATICPIE: '.symtab'
27-
# STATICPIE: __global_pointer$
27+
# STATICE: '.dynsym'
28+
# STATICE: __global_pointer$
29+
# STATICE: '.symtab'
30+
# STATICE: __global_pointer$
2831

2932
## -r mode does not define __global_pointer$.
3033
# RUN: ld.lld -r %t.64.o -o %t.64.ro

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
88

99
# RUN: ld.lld -pie -o %t %t1.o --start-lib %t2.o
10-
# RUN: llvm-readobj --dyn-syms %t | FileCheck %s
10+
# RUN: llvm-readelf --dyn-syms %t | FileCheck %s --check-prefix=STATICPIE
1111

1212
# CHECK: Name: foo
1313
# CHECK-NEXT: Value: 0x0

lld/test/ELF/weak-undef-no-dynamic-linker.s

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# REQUIRES: x86
22
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
33
# RUN: ld.lld -pie %t.o -o %t
4-
# RUN: llvm-readobj --dyn-syms %t | FileCheck %s
4+
# RUN: llvm-readobj --dyn-syms %t | FileCheck --check-prefix=NO %s
55
# RUN: ld.lld -pie --no-dynamic-linker %t.o -o %t
66
# RUN: llvm-readobj --dyn-syms %t | FileCheck --check-prefix=NO %s
77

8-
## With --no-dynamic-linker, don't emit undefined weak symbols to .dynsym .
9-
## This will suppress a relocation.
10-
# CHECK: Name: foo
8+
## With static PIE (whether or not --no-dynamic-linker is specified), don't
9+
## emit undefined weak symbols to .dynsym . This suppresses relocations.
1110
# NO-NOT: Name: foo
1211

1312
.weak foo

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
# REQUIRES: x86
22
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
33
# RUN: ld.lld %t.o -o %t --export-dynamic
4-
# RUN: llvm-readelf -r --hex-dump=.data %t | FileCheck %s --check-prefix=NOPIC
4+
# RUN: llvm-readelf -r --hex-dump=.data %t | FileCheck %s --check-prefix=STATIC
55
# RUN: ld.lld %t.o -o %t.pie -pie
6-
# RUN: llvm-readobj -r %t.pie | FileCheck %s --check-prefix=PIC
6+
# RUN: llvm-readelf -r --hex-dump=.data %t.pie | FileCheck %s --check-prefix=STATIC
77
# RUN: ld.lld %t.o -o %t.so -shared
88
# RUN: llvm-readobj -r %t.so | FileCheck %s --check-prefix=PIC
99

1010
## gABI leaves the behavior of weak undefined references implementation defined.
11-
## We choose to resolve them statically for -no-pie and produce dynamic relocations
12-
## for -pie and -shared.
11+
## We choose to resolve them statically for static linking and produce dynamic relocations
12+
## for dynamic linking (-shared or at least one input DSO).
1313
##
1414
## Note: Some ports of GNU ld support -z nodynamic-undefined-weak that we don't
1515
## implement.
1616

17-
# NOPIC: no relocations
18-
# NOPIC: Hex dump of section '.data':
19-
# NOPIC-NEXT: {{.*}} 00000000 00000000
20-
# NOPIC-EMPTY:
17+
# STATIC: no relocations
18+
# STATIC: Hex dump of section '.data':
19+
# STATIC-NEXT: {{.*}} 00000000 00000000 .
20+
# STATIC-EMPTY:
2121

2222
# PIC: .rela.dyn {
2323
# PIC-NEXT: R_X86_64_64 foobar 0x0

0 commit comments

Comments
 (0)