[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