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

Hakan Candar hakan@envs.net
Wed Jul 16 16:03:21 GMT 2025


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"));
 }
 
 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



More information about the Binutils mailing list