[PATCH] RISC-V: Also output undefined symbols as dynamic symbols
Vivian Wang
wangruikang@iscas.ac.cn
Mon May 11 04:28:14 GMT 2026
Consider this program, which refers to an undefined symbol foo:
int foo(void);
int main() { foo(); }
If linking with --unresolved-symbols=ignore-in-object-file, what should
happen is the symbol foo is left undefined and left for the dynamic
linker to resolve. (See commit 4295841be439 ("RISC-V: Go PLT for
CALL/JUMP/RVC_JUMP if `h->plt.offset' isn't -1").) Instead, with
binutils 2.46:
1. With -no-pie, ld generates an auipc/jalr call to address 0, crashing
at runtime instead of generating an undefined symbol message.
2. With -pie, ld generates this bogus error message (-fPIC does not
change this, and R_RISCV_CALL_PLT is correct here) and stops, failing
to produce an executable:
ld: relocation R_RISCV_CALL_PLT against `foo' which may bind
externally can not be used when making a shared object; recompile
with -fPIC
Bisection leads to commit 9e10fcf71c11 ("RISC-V: Fix the assert fail
when linking discarded sections under -pie for got"), which stopped
outputting dynamic symbols for non-undefweak symbols. Therefore, in
order to fix the issue, also output undefined symbols as dynamic
symbols.
Fixes test case ld-elf/dwarf.exp, specifically dwarf3, where the bogus
error prevents the second "undefined reference" error from appearing. No
regressions found for the ld tests on riscv64.
bfd/:
* elfnn-riscv.c (allocate_dynrelocs): Also output undefined
symbols as dynamic symbols
Fixes: 9e10fcf71c11 ("RISC-V: Fix the assert fail when linking discarded sections under -pie for got")
---
This is my first patch to binutils. Please advise if I'm doing something wrong. Thanks.
Vivian "dramforever" Wang
---
bfd/elfnn-riscv.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index eb3d7926c..d66c42b78 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -1439,10 +1439,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
&& h->plt.refcount > 0)
{
/* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
+ Undefined and undefweak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
&& !h->forced_local
- && h->root.type == bfd_link_hash_undefweak
+ && (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined)
&& !bfd_elf_link_record_dynamic_symbol (info, h))
return false;
@@ -1500,11 +1501,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
int tls_type = riscv_elf_hash_entry (h)->tls_type;
/* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
+ Undefined and undefweak syms won't yet be marked as dynamic. */
if (dyn
&& h->dynindx == -1
&& !h->forced_local
- && h->root.type == bfd_link_hash_undefweak
+ && (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined)
&& !bfd_elf_link_record_dynamic_symbol (info, h))
return false;
@@ -1611,10 +1613,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|| h->root.type == bfd_link_hash_undefined))))
{
/* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
+ Undefined and undefweak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
&& !h->forced_local
- && h->root.type == bfd_link_hash_undefweak
+ && (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined)
&& !bfd_elf_link_record_dynamic_symbol (info, h))
return false;
--
2.53.0
More information about the Binutils
mailing list