[PATCH 0/3] ELF: Improve undefined symbol retention for strong symbols
Hakan Candar
hakan@envs.net
Wed Jul 16 16:03:20 GMT 2025
Hi all,
This patch series improves undefined symbol retention in ELF links for
strong symbols, specifically when `-z dynamic-undefined-weak` is given.
Today, `ld.bfd` inconsistently handles undefined strong symbols across
targets, even with `--unresolved-symbols=ignore-all` and
`-z dynamic-undefined-weak`. While some targets treat strong undefineds
like weaks (emitting dynamic relocations), others prune them completely.
This behavior differs from LLD, which consistently retains both.
After an earlier RFC [1] and a round of testing, I’ve narrowed the scope
of the patch significantly. Rather than centralizing backend behavior
entirely, we now only:
1. Move `-z dynamic-undefined-weak` flag handling into ELF shared code
(from individual emulparams).
2. Extend undefined symbol retention logic in `elflink.c` to include
strong undefineds (in addition to weaks).
3. Add a test case to ensure that strong undefined symbols are
preserved when explicitly allowed.
This change has no effect unless `-z dynamic-undefined-weak` is used,
and does not touch backend-specific pruning logic.
To validate the patch, I tested symbol retention under various targets.
The table below shows behavior when the flag is explicitly passed:
Target | Version | Keeps Weak (-z dyn) | Keeps Strong (-z dyn) | Keeps Weak (-z nodyn) | Keeps Strong (-z nodyn) | Accepts -z dyn-und-weak
--------------+--------------------+----------------------+------------------------+------------------------+--------------------------+-------------------------
x86_64 | 2.44.50.20250716 | Yes | Yes | No | No | Yes
i386 | 2.44.50.20250716 | Yes | Yes | No | No | Yes
aarch64 | 2.44.50.20250716 | Yes | Yes | No | No | Yes
arm | 2.44.50.20250716 | Yes | Yes | No | No | Yes
ppc64le | 2.44.50.20250716 | Yes | Yes | No | No | Yes
ppc | 2.44.50.20250716 | Yes | Yes | No | No | Yes
riscv64 | 2.44.50.20250716 | Yes | Yes | No | No | Yes
mips64 | 2.44.50.20250716 | Yes | Yes | Fail* (--shared) | Fail* (--shared) | Yes
hppa | 2.44.50.20250716 | Yes | Yes | No | Fail** | Yes
ia64 | 2.44.50.20250716 | Yes | Broken** | No | No | Yes
m68k | 2.44.50.20250716 | No | No | No | No | Yes
sh4 | 2.44.50.20250716 | No | No | No | No | Yes
*: MIPS asserts and exits when it comes across a relocation against
an undefined symbol, only when generating a shared library and
-z nodynamic-undefined-weak is specified.
**: HPPA currently errors out on non-dynamic strong undefined symbol,
whereas it should have resolved to zero. This will later be addressed.
*** IA-64 generates PLT for strong undefined symbol, and the dynamic
relocation is preserved, but the PLT is not called.
Notably, `m68k`, and `sh4` prune symbols even when the user
explicitly requests retention. This contradicts the intent of the `-z`
flag and the gABI. I investigated `sh4` in particular and managed to
correct retention locally, but encountered unrelated regressions in the
testsuite, so I’ve moved that fix out of scope for now. I plan to send
incremental patches for those backends after this series.
This patch is intentionally minimal and should be low-risk. It brings
`ld.bfd` behavior closer to LLD and improves consistency for developers
relying on dynamic symbol resolution across targets.
Thanks for your time and feedback.
Best regards,
Hakan Candar
[1] https://sourceware.org/pipermail/binutils/2025-July/142081.html
Hakan Candar (3):
ld/ELF: Move -z dynamic-undefined-weak flag handling to elf.em
bfd/ELF: Retain strong undefined symbols under -z
dynamic-undefined-weak
ld/testsuite: Add shared test logic for undefined symbol retention
bfd/bfd-in2.h | 8 ++
bfd/elf-bfd.h | 10 +++
bfd/elflink.c | 2 +-
bfd/linker.c | 9 ++
ld/NEWS | 10 +++
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 | 9 +-
ld/lexsup.c | 3 +
ld/testsuite/ld-undefined/fundef.s | 4 +
ld/testsuite/ld-undefined/undef-common.tcl | 96 ++++++++++++++++++++++
ld/testsuite/ld-undefined/undefined.exp | 73 ++++++++++++----
ld/testsuite/ld-undefined/weak-fundef.s | 3 +
ld/testsuite/ld-undefined/weak-undef.exp | 94 ++++-----------------
22 files changed, 231 insertions(+), 120 deletions(-)
delete mode 100644 ld/emulparams/dynamic_undefined_weak.sh
create mode 100644 ld/testsuite/ld-undefined/undef-common.tcl
--
2.47.0
More information about the Binutils
mailing list