[PATCH 1/3] ld/ELF: Move -z dynamic-undefined-weak flag handling to elf.em

H.J. Lu hjl.tools@gmail.com
Wed Jul 16 18:21:59 GMT 2025


On Wed, Jul 16, 2025 at 9:05 AM Hakan Candar <hakan@envs.net> wrote:
>
> The -z [no]dynamic-undefined-weak flag was previously handled through
> emulparams scripts, only wired into select backends like x86 and PPC.
>
> This patch moves its handling into elf.em so that it applies uniformly
> across all ELF backends, removing the need for per-target boilerplate.
>
> This change does not alter behavior for targets that already used the
> flag, but enables proper support on targets that previously ignored or
> warned on it (e.g., AArch64, RISC-V, MIPS).
>
> ld/
>         * emultempl/elf.em: Add -z dynamic-undefined-weak flag handling.
>         * emulparams/dynamic_undefined_weak.sh: Delete.
>         * emulparams/elf32_x86_64.sh: Remove source line.
>         * emulparams/elf32ppccommon.sh: Likewise.
>         * emulparams/elf_i386.sh: Likewise.
>         * emulparams/elf_i386_be.sh: Likewise.
>         * emulparams/elf_i386_ldso.sh: Likewise.
>         * emulparams/elf_i386_vxworks.sh: Likewise.
>         * emulparams/elf_iamcu.sh: Likewise.
>         * emulparams/elf_x86_64.sh: Likewise.
>         * ld.texi: Clarify that '-z dynamic-undefined-weak' is now accepted
>         for all ELF targets, though some backends may not fully support it.
>         * lexsup.c (elf_shlib_list_options): Document '-z dynamic-undefined-weak'
>         and '-z nodynamic-undefined-weak' options in help output.
>         * NEWS: Mention the new, centralized behaviour.
>
> ld/testsuite/
>         * ld-undefined/weak-undef.exp: Enable validation of
>         undefined symbol retention for AArch64, RISC-V, and MIPS by
>         setting appropriate assembler flags.
>
> Signed-off-by: Hakan Candar <hakan@envs.net>
> ---
>  ld/NEWS                                  |  7 ++++
>  ld/emulparams/dynamic_undefined_weak.sh  | 15 ---------
>  ld/emulparams/elf32_x86_64.sh            |  1 -
>  ld/emulparams/elf32ppccommon.sh          |  1 -
>  ld/emulparams/elf_i386.sh                |  1 -
>  ld/emulparams/elf_i386_be.sh             |  1 -
>  ld/emulparams/elf_i386_ldso.sh           |  1 -
>  ld/emulparams/elf_i386_vxworks.sh        |  1 -
>  ld/emulparams/elf_iamcu.sh               |  1 -
>  ld/emulparams/elf_x86_64.sh              |  1 -
>  ld/emultempl/elf.em                      |  7 ++++
>  ld/ld.texi                               |  7 ++--
>  ld/lexsup.c                              |  3 ++
>  ld/testsuite/ld-undefined/weak-fundef.s  |  3 ++
>  ld/testsuite/ld-undefined/weak-undef.exp | 42 ++++++++++--------------
>  15 files changed, 42 insertions(+), 50 deletions(-)
>  delete mode 100644 ld/emulparams/dynamic_undefined_weak.sh
>
> diff --git a/ld/NEWS b/ld/NEWS
> index 217c5b7b0d3..dcb8511fc04 100644
> --- a/ld/NEWS
> +++ b/ld/NEWS
> @@ -2,6 +2,13 @@
>
>  Changes in 2.45:
>
> +* The -z [no]dynamic-undefined-weak option is now handled centrally in the
> +  ELF emulation code and is accepted on all ELF targets.  This removes the
> +  need for per-target wiring.
> +
> +  Some backends may not yet fully respect this centralized
> +  logic due to backend-specific conditionals.
> +
>  * On s390 64-bit (s390x), generate SFrame stack trace information (.sframe)
>    for the linker generated .plt section.  Enabled by default.  Can be disabled
>    using linker option --no-ld-generated-unwind-info.
> diff --git a/ld/emulparams/dynamic_undefined_weak.sh b/ld/emulparams/dynamic_undefined_weak.sh
> deleted file mode 100644
> index 21393d40d26..00000000000
> --- a/ld/emulparams/dynamic_undefined_weak.sh
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -PARSE_AND_LIST_OPTIONS_DYNAMIC_UNDEFINED_WEAK='
> -  fprintf (file, _("\
> -  -z dynamic-undefined-weak   Make undefined weak symbols dynamic\n\
> -  -z nodynamic-undefined-weak Do not make undefined weak symbols dynamic\n"));
> -'
> -
> -PARSE_AND_LIST_ARGS_CASE_Z_DYNAMIC_UNDEFINED_WEAK='
> -      else if (strcmp (optarg, "dynamic-undefined-weak") == 0)
> -       link_info.dynamic_undefined_weak = true;
> -      else if (strcmp (optarg, "nodynamic-undefined-weak") == 0)
> -       link_info.dynamic_undefined_weak = false;
> -'
> -
> -PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_DYNAMIC_UNDEFINED_WEAK"
> -PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_DYNAMIC_UNDEFINED_WEAK"
> diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
> index 6a92eec129d..1a027732239 100644
> --- a/ld/emulparams/elf32_x86_64.sh
> +++ b/ld/emulparams/elf32_x86_64.sh
> @@ -1,6 +1,5 @@
>  source_sh ${srcdir}/emulparams/plt_unwind.sh
>  source_sh ${srcdir}/emulparams/extern_protected_data.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>  source_sh ${srcdir}/emulparams/reloc_overflow.sh
>  source_sh ${srcdir}/emulparams/call_nop.sh
>  source_sh ${srcdir}/emulparams/cet.sh
> diff --git a/ld/emulparams/elf32ppccommon.sh b/ld/emulparams/elf32ppccommon.sh
> index da892988f5d..f3ca889a37b 100644
> --- a/ld/emulparams/elf32ppccommon.sh
> +++ b/ld/emulparams/elf32ppccommon.sh
> @@ -1,6 +1,5 @@
>  # The PLT-agnostic parts of a generic 32-bit ELF PowerPC target.  Included by:
>  # elf32ppc.sh elf32ppcvxworks.sh elf64ppc.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>
>  TEMPLATE_NAME=elf
>  GENERATE_SHLIB_SCRIPT=yes
> diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
> index 6f698bb0b06..e7ef5185bd4 100644
> --- a/ld/emulparams/elf_i386.sh
> +++ b/ld/emulparams/elf_i386.sh
> @@ -1,6 +1,5 @@
>  source_sh ${srcdir}/emulparams/plt_unwind.sh
>  source_sh ${srcdir}/emulparams/extern_protected_data.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>  source_sh ${srcdir}/emulparams/call_nop.sh
>  source_sh ${srcdir}/emulparams/cet.sh
>  source_sh ${srcdir}/emulparams/x86-report-relative.sh
> diff --git a/ld/emulparams/elf_i386_be.sh b/ld/emulparams/elf_i386_be.sh
> index dbe68e99e63..a03770f9aff 100644
> --- a/ld/emulparams/elf_i386_be.sh
> +++ b/ld/emulparams/elf_i386_be.sh
> @@ -1,5 +1,4 @@
>  source_sh ${srcdir}/emulparams/extern_protected_data.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>  source_sh ${srcdir}/emulparams/call_nop.sh
>  SCRIPT_NAME=elf
>  OUTPUT_FORMAT="elf32-i386"
> diff --git a/ld/emulparams/elf_i386_ldso.sh b/ld/emulparams/elf_i386_ldso.sh
> index 081de5f8e71..4917a65f80c 100644
> --- a/ld/emulparams/elf_i386_ldso.sh
> +++ b/ld/emulparams/elf_i386_ldso.sh
> @@ -1,6 +1,5 @@
>  source_sh ${srcdir}/emulparams/plt_unwind.sh
>  source_sh ${srcdir}/emulparams/extern_protected_data.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>  source_sh ${srcdir}/emulparams/call_nop.sh
>  SCRIPT_NAME=elf
>  OUTPUT_FORMAT="elf32-i386"
> diff --git a/ld/emulparams/elf_i386_vxworks.sh b/ld/emulparams/elf_i386_vxworks.sh
> index 40c809263d1..4645967a81f 100644
> --- a/ld/emulparams/elf_i386_vxworks.sh
> +++ b/ld/emulparams/elf_i386_vxworks.sh
> @@ -13,5 +13,4 @@ GENERATE_PIE_SCRIPT=yes
>  NO_SMALL_DATA=yes
>  source_sh ${srcdir}/emulparams/vxworks.sh
>  source_sh ${srcdir}/emulparams/extern_protected_data.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>  source_sh ${srcdir}/emulparams/call_nop.sh
> diff --git a/ld/emulparams/elf_iamcu.sh b/ld/emulparams/elf_iamcu.sh
> index c1582235eda..ccd74a2ba05 100644
> --- a/ld/emulparams/elf_iamcu.sh
> +++ b/ld/emulparams/elf_iamcu.sh
> @@ -1,6 +1,5 @@
>  source_sh ${srcdir}/emulparams/plt_unwind.sh
>  source_sh ${srcdir}/emulparams/extern_protected_data.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>  source_sh ${srcdir}/emulparams/call_nop.sh
>  SCRIPT_NAME=elf
>  OUTPUT_FORMAT="elf32-iamcu"
> diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
> index 92449745c7a..ac779591f01 100644
> --- a/ld/emulparams/elf_x86_64.sh
> +++ b/ld/emulparams/elf_x86_64.sh
> @@ -1,6 +1,5 @@
>  source_sh ${srcdir}/emulparams/plt_unwind.sh
>  source_sh ${srcdir}/emulparams/extern_protected_data.sh
> -source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
>  source_sh ${srcdir}/emulparams/reloc_overflow.sh
>  source_sh ${srcdir}/emulparams/call_nop.sh
>  source_sh ${srcdir}/emulparams/cet.sh
> diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
> index 431205fe644..5e87a294fbc 100644
> --- a/ld/emultempl/elf.em
> +++ b/ld/emultempl/elf.em
> @@ -1115,6 +1115,13 @@ fragment <<EOF
>         link_info.textrel_check = textrel_check_none;
>  EOF
>
> +fragment <<EOF
> +      else if (strcmp (optarg, "dynamic-undefined-weak") == 0)
> +        link_info.dynamic_undefined_weak = true;
> +      else if (strcmp (optarg, "nodynamic-undefined-weak") == 0)
> +        link_info.dynamic_undefined_weak = false;
> +EOF
> +
>  if test -n "$PARSE_AND_LIST_ARGS_CASE_Z" ; then
>  fragment <<EOF
>   $PARSE_AND_LIST_ARGS_CASE_Z
> diff --git a/ld/ld.texi b/ld/ld.texi
> index 413335ad765..ffdb4d97412 100644
> --- a/ld/ld.texi
> +++ b/ld/ld.texi
> @@ -1438,8 +1438,11 @@ if they are referenced from a regular object file and not forced local
>  by symbol visibility or versioning.  Do not make them dynamic if
>  @samp{nodynamic-undefined-weak}.  If neither option is given, a target
>  may default to either option being in force, or make some other
> -selection of undefined weak symbols dynamic.  Not all targets support
> -these options.
> +selection of undefined weak symbols dynamic.
> +
> +These options are available for all ELF targets, but some backends may
> +not yet fully implement consistent handling of undefined symbol retention.
> +This is considered a backend bug, not lack of support.
>
>  @item execstack
>  Marks the object as requiring executable stack.
> diff --git a/ld/lexsup.c b/ld/lexsup.c
> index bde20465835..5f0c040e352 100644
> --- a/ld/lexsup.c
> +++ b/ld/lexsup.c
> @@ -2267,6 +2267,9 @@ elf_shlib_list_options (FILE *file)
>    fprintf (file, _("\
>    -z nomemory-seal            Don't mark oject to be memory sealed (default)\n"));
>  #endif
> +  fprintf (file, _("\
> +  -z dynamic-undefined-weak   Make undefined weak symbols dynamic\n\
> +  -z nodynamic-undefined-weak Do not make undefined weak symbols dynamic\n"));

Please add "(default)" to the default option.

>  }
>
>  static void
> diff --git a/ld/testsuite/ld-undefined/weak-fundef.s b/ld/testsuite/ld-undefined/weak-fundef.s
> index de8f641b6c2..79af8052473 100644
> --- a/ld/testsuite/ld-undefined/weak-fundef.s
> +++ b/ld/testsuite/ld-undefined/weak-fundef.s
> @@ -15,3 +15,6 @@
>         bl undef_weak_fun,%r2
>         nop
>   .endif
> + .ifdef JAL
> +       jal undef_weak_fun
> + .endif
> diff --git a/ld/testsuite/ld-undefined/weak-undef.exp b/ld/testsuite/ld-undefined/weak-undef.exp
> index 071fbebb927..2d6f8f2c573 100644
> --- a/ld/testsuite/ld-undefined/weak-undef.exp
> +++ b/ld/testsuite/ld-undefined/weak-undef.exp
> @@ -103,13 +103,15 @@ set testname "weak undefined function symbols in shared lib"
>
>  set asflags ""
>  switch -glob $target_triplet {
> -    aarch64* -
> +    aarch64* { set asflags "--defsym BL=1" }
>      arm* -
>      powerpc64* { set asflags "--defsym BL=1" }
>      powerpc* { set asflags "--defsym BLPLT=1" }
>      hppa* { set asflags "--defsym HPPA=1" }
>      i\[3-7\]86* -
>      x86_64* { set asflags "--defsym CALLPLT=1" }
> +    riscv* { set asflags "--defsym CALLPLT=1" }
> +    mips* { set asflags "--defsym JAL=1 -KPIC" }
>  }
>
>  if { $asflags == "" || ![is_elf_format] || ![check_shared_lib_support]} then {
> @@ -123,34 +125,24 @@ if { $asflags == "" || ![is_elf_format] || ![check_shared_lib_support]} then {
>      set testname "weak undefined function symbols in dynamic exe"
>      undef_weak_exe $testname "--no-as-needed" 1
>
> -    # Find -z options supported by the default emulation
> -    set emul [get_target_emul]
> -    set cmd [list "$ld --help 2>&1 | sed -e '1,/^$emul:/d;/^\[^ \]*:/,\$d'"]
> -    set status [remote_exec host [concat sh -c $cmd]]
> -    if { [lindex $status 0] != 0 } {
> -       verbose -log "$cmd exited with status [lindex $status 0]"
> -    }
> -    set emulopt [lindex $status 1]
> -
> -    if { [string first "dynamic-undefined-weak" $emulopt] >= 0 } {
> -       # -z dynamic-undefined-weak is supported.  Let's see if it works.
> +    # All ELF targets support -z dynamic-undefined-weak
> +    # Let's see if it works.
>
> -       set testname "weak undefined functions in shared lib, no dyn undef weak"
> -       undef_weak_so $testname "--shared -z nodynamic-undefined-weak" 0
> +    set testname "weak undefined functions in shared lib, no dyn undef weak"
> +    undef_weak_so $testname "--shared -z nodynamic-undefined-weak" 0
>
> -       set testname "weak undefined functions in shared lib, dyn undef weak"
> -       undef_weak_so $testname "--shared -z dynamic-undefined-weak" 1
> +    set testname "weak undefined functions in shared lib, dyn undef weak"
> +    undef_weak_so $testname "--shared -z dynamic-undefined-weak" 1
>
> -       set testname "weak undefined functions in dynamic exe, no dyn undef weak"
> -       undef_weak_exe $testname "-z nodynamic-undefined-weak" 0
> +    set testname "weak undefined functions in dynamic exe, no dyn undef weak"
> +    undef_weak_exe $testname "-z nodynamic-undefined-weak" 0
>
> -       set testname "weak undefined functions in dynamic exe, dyn undef weak"
> -       undef_weak_exe $testname "-z dynamic-undefined-weak" 1
> +    set testname "weak undefined functions in dynamic exe, dyn undef weak"
> +    undef_weak_exe $testname "-z dynamic-undefined-weak" 1
>
> -       set testname "weak undefined functions in pie, no dyn undef weak"
> -       undef_weak_exe $testname "-pie -z nodynamic-undefined-weak" 0
> +    set testname "weak undefined functions in pie, no dyn undef weak"
> +    undef_weak_exe $testname "-pie -z nodynamic-undefined-weak" 0
>
> -       set testname "weak undefined functions in pie, dyn undef weak"
> -       undef_weak_exe $testname "-pie -z dynamic-undefined-weak" 1
> -    }
> +    set testname "weak undefined functions in pie, dyn undef weak"
> +    undef_weak_exe $testname "-pie -z dynamic-undefined-weak" 1
>  }
> --
> 2.47.0
>


-- 
H.J.


More information about the Binutils mailing list