diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1379,7 +1379,8 @@ // symbols not specified by --dynamic-list are non-preemptible. config->symbolic = config->bsymbolic == BsymbolicKind::All || args.hasArg(OPT_dynamic_list); - for (auto *arg : args.filtered(OPT_dynamic_list)) + for (auto *arg : + args.filtered(OPT_dynamic_list, OPT_export_dynamic_symbol_list)) if (Optional buffer = readFile(arg->getValue())) readDynamicList(*buffer); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -156,10 +156,8 @@ defm dynamic_linker: Eq<"dynamic-linker", "Which dynamic linker to use">; defm dynamic_list : Eq<"dynamic-list", - "Read a list of dynamic symbols. (executable) Put matched non-local defined" - "symbols to the dynamic symbol table. (shared object) References to matched" - "non-local STV_DEFAULT symbols shouldn't be bound to definitions within the " - "shared object. Implies -Bsymbolic but does not set DF_SYMBOLIC">, + "Similar to --export-dynamic-symbol-list. When creating a shared object, " + "this additionally implies -Bsymbolic but does not set DF_SYMBOLIC">, MetaVarName<"">; def eb: F<"EB">, HelpText<"Select the big-endian format in OUTPUT_FORMAT">; @@ -209,6 +207,10 @@ "Does not imply -Bsymbolic.">, MetaVarName<"glob">; +defm export_dynamic_symbol_list : EEq<"export-dynamic-symbol-list", + "Read a list of dynamic symbol patterns. Apply --export-dynamic-symbol on each pattern">, + MetaVarName<"file">; + defm fatal_warnings: B<"fatal-warnings", "Treat warnings as errors", "Do not treat warnings as errors (default)">; diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -24,8 +24,8 @@ ELF Improvements ---------------- -* ``-Bsymbolic-non-weak-functions`` has been added as a ``STB_GLOBAL`` subset of ``-Bsymbolic-functions``. - (`D102570 `_) +* ``--export-dynamic-symbol-list`` has been added. + (`D107317 `_) Breaking changes ---------------- diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -167,10 +167,9 @@ This is recorded in an ELF segment of type .Dv PT_INTERP . .It Fl -dynamic-list Ns = Ns Ar file -Read a list of dynamic symbols from -.Ar file . -(executable) Put matched non-local defined symbols to the dynamic symbol table. -(shared object) References to matched non-local STV_DEFAULT symbols shouldn't be bound to definitions within the shared object. Implies +Similar to +.Cm -export-dynamic-symbol-list . +When creating a shared object, implies .Cm -Bsymbolic but does not set DF_SYMBOLIC .It Fl -EB @@ -225,6 +224,12 @@ .Cm -Bsymbolic-functions or .Cm --dynamic-list +.It Fl -export-dynamic-symbol-list Ns = Ns Ar file +Read a list of dynamic symbol patterns from +.Ar file . +Apply +.Cm -export-dynamic-symbol +on each pattern. .It Fl -fatal-warnings Treat warnings as errors. .It Fl -filter Ns = Ns Ar value , Fl F Ar value diff --git a/lld/test/ELF/export-dynamic-symbol.s b/lld/test/ELF/export-dynamic-symbol.s --- a/lld/test/ELF/export-dynamic-symbol.s +++ b/lld/test/ELF/export-dynamic-symbol.s @@ -3,7 +3,11 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o ## For an executable, --export-dynamic-symbol exports a symbol if it is non-local and defined. -# RUN: ld.lld -pie --export-dynamic-symbol foo %t.o -o %t +# RUN: ld.lld -pie --export-dynamic-symbol foo --export-dynamic-symbol qux %t.o -o %t +# RUN: llvm-nm -D -p %t | FileCheck %s +# RUN: echo '{ foo; };' > %t1.list +# RUN: echo '{ foo; qux; };' > %t2.list +# RUN: ld.lld -pie --export-dynamic-symbol-list=%t2.list %t.o -o %t # RUN: llvm-nm -D -p %t | FileCheck %s ## --export-dynamic exports all non-local defined symbols. @@ -14,6 +18,7 @@ # CHECK-NOT: . # START: T _start # CHECK: T foo +# CHECK: T qux # CHECK-NOT: . ## --export-dynamic-symbol does not imply -u: %t1.a(%t1.o) is not fetched. @@ -23,36 +28,53 @@ # RUN: ld.lld --export-dynamic-symbol bar %t1.a %t.o -o %t.nofetch # RUN: llvm-nm %t.nofetch | FileCheck /dev/null --implicit-check-not=bar +## For -shared, if no option expresses a symbolic intention, --export-dynamic-symbol is a no-op. +# RUN: ld.lld -shared --export-dynamic-symbol foo %t.o -o %t.noop +# RUN: llvm-objdump -d %t.noop | FileCheck --check-prefix=PLT2 %s +# RUN: ld.lld -shared --export-dynamic-symbol-list %t2.list %t.o -o %t.noop +# RUN: llvm-objdump -d %t.noop | FileCheck --check-prefix=PLT2 %s + ## --export-dynamic-symbol can make a symbol preemptible even if it would be otherwise ## non-preemptible (due to -Bsymbolic, -Bsymbolic-functions or --dynamic-list). # RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol nomatch %t.o -o %t.nopreempt # RUN: llvm-objdump -d %t.nopreempt | FileCheck --check-prefix=NOPLT %s # RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol foo %t.o -o %t.preempt -# RUN: llvm-objdump -d %t.preempt | FileCheck --check-prefix=PLT %s +# RUN: llvm-objdump -d %t.preempt | FileCheck --check-prefix=PLT1 %s +# RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol-list %t1.list %t.o -o %t.preempt +# RUN: llvm-objdump -d %t.preempt | FileCheck --check-prefix=PLT1 %s ## 'nomatch' does not match any symbol. Don't warn. # RUN: ld.lld --fatal-warnings -shared -Bsymbolic-functions --export-dynamic-symbol nomatch %t.o -o %t.nopreempt2 # RUN: llvm-objdump -d %t.nopreempt2 | FileCheck --check-prefix=NOPLT %s # RUN: ld.lld -shared -Bsymbolic-functions --export-dynamic-symbol foo %t.o -o %t.preempt2 -# RUN: llvm-objdump -d %t.preempt2 | FileCheck --check-prefix=PLT %s +# RUN: llvm-objdump -d %t.preempt2 | FileCheck --check-prefix=PLT1 %s # RUN: echo '{};' > %t.list # RUN: ld.lld -shared --dynamic-list %t.list --export-dynamic-symbol foo %t.o -o %t.preempt3 -# RUN: llvm-objdump -d %t.preempt3 | FileCheck --check-prefix=PLT %s +# RUN: llvm-objdump -d %t.preempt3 | FileCheck --check-prefix=PLT1 %s ## The option value is a glob. # RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol 'f*' %t.o -o - | \ -# RUN: llvm-objdump -d - | FileCheck --check-prefix=PLT %s +# RUN: llvm-objdump -d - | FileCheck --check-prefix=PLT1 %s # RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol '[f]o[o]' %t.o -o - | \ -# RUN: llvm-objdump -d - | FileCheck --check-prefix=PLT %s +# RUN: llvm-objdump -d - | FileCheck --check-prefix=PLT1 %s # RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol 'f?o' %t.o -o - | \ -# RUN: llvm-objdump -d - | FileCheck --check-prefix=PLT %s +# RUN: llvm-objdump -d - | FileCheck --check-prefix=PLT1 %s + +# PLT1: +# PLT1: + +# PLT2: +# PLT2: -# PLT: # NOPLT-NOT: +# NOPLT-NOT: -.global _start, foo +.global _start, foo, qux .type foo, @function +.type qux, @function _start: call foo + call qux foo: +qux: