[binutils-gdb] alpha: Properly handle local weak undefined symbols

"H.J. Lu via Binutils-cvs" <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ffea43122dc5deaea75374bd2bd928d1d4182f67

commit ffea43122dc5deaea75374bd2bd928d1d4182f67
Author: H.J. Lu <[email protected]>
Date:   Sat May 23 05:12:10 2026 +0800

    alpha: Properly handle local weak undefined symbols
    
    Since the local undefined TLS symbol address isn't mapped to any TLS
    storage, it isn't usable.  Set its value to 0 to avoid relocation overflow.
    When processing TLS relocations, elf_hash_table (info)->tls_sec can be
    NULL if all TLS symbols are weak, hidden and undefined.  Don't assert
    elf_hash_table (info)->tls_sec != NULL.  Always set dtp_base and tp_base
    to 0 if elf_hash_table (info)->tls_sec == NULL.
    
    bfd/
    
            PR ld/34165
            * * elf-bfd.h (elf_link_local_undefweak_p): New function.
            * elf64-alpha.c (elf64_alpha_relax_got_load): Set dtp_base and
            tp_base to 0 if elf_hash_table (info)->tls_sec == NULL.
            (elf64_alpha_relocate_section):  Set the local undefined TLS
            symbol value to 0.  Don't assert elf_hash_table (info)->tls_sec
            != NULL.
    
    ld/
    
            PR ld/34165
            * testsuite/ld-alpha/alpha.exp: Run $srcdir/$subdir/*.d.
            * testsuite/ld-alpha/tlsbin-undef.d: New file.
            * testsuite/ld-alpha/tlsbin-undef.s: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef1.d: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef1.s: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef2.d: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef2.s: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef3.d: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef3.s: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef4.d: Likewise.
            * testsuite/ld-alpha/tlsbin-weak-undef4.s: Likewise.
            * testsuite/ld-alpha/tlspic-undef.d: Likewise.
            * testsuite/ld-alpha/tlspic-undef.s: Likewise.
            * testsuite/ld-alpha/tlspic-weak-undef1.d: Likewise.
            * testsuite/ld-alpha/tlspic-weak-undef1.s: Likewise.
            * testsuite/ld-elf/pr34165.c: Likewise.
            * testsuite/ld-elf/tls.exp: Run PR ld/34165 test.
    
    Signed-off-by: H.J. Lu <[email protected]>

Diff:
---
 bfd/elf-bfd.h                              | 11 ++++++++++
 bfd/elf64-alpha.c                          | 33 ++++++++++++++++++++++--------
 ld/testsuite/ld-alpha/alpha.exp            |  7 +++++++
 ld/testsuite/ld-alpha/tlsbin-undef.d       |  2 ++
 ld/testsuite/ld-alpha/tlsbin-undef.s       | 16 +++++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef1.d | 14 +++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef1.s | 17 +++++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef2.d | 14 +++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef2.s | 17 +++++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef3.d | 14 +++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef3.s | 22 ++++++++++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef4.d | 14 +++++++++++++
 ld/testsuite/ld-alpha/tlsbin-weak-undef4.s | 22 ++++++++++++++++++++
 ld/testsuite/ld-alpha/tlspic-undef.d       |  2 ++
 ld/testsuite/ld-alpha/tlspic-undef.s       | 16 +++++++++++++++
 ld/testsuite/ld-alpha/tlspic-weak-undef1.d | 14 +++++++++++++
 ld/testsuite/ld-alpha/tlspic-weak-undef1.s | 22 ++++++++++++++++++++
 ld/testsuite/ld-elf/pr34165.c              | 14 +++++++++++++
 ld/testsuite/ld-elf/tls.exp                | 11 ++++++++++
 19 files changed, 273 insertions(+), 9 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 41be7232664..12ac3f362c0 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -3558,6 +3558,17 @@ bfd_section_is_ctf (const asection *sec)
   return startswith (name, ".ctf") && (name[4] == 0 || name[4] == '.');
 }
 
+/* Return true if H is local weak undefined.  */
+
+static inline bool
+elf_link_local_undefweak_p (struct elf_link_hash_entry *h,
+			    struct bfd_link_info *info)
+{
+  return (h != NULL
+	  && h->root.type == bfd_link_hash_undefweak
+	  && _bfd_elf_symbol_refs_local_p (h, info, false));
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 91cc7bcaec8..594bfe9a80e 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -3018,9 +3018,13 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
     {
       bfd_vma dtp_base, tp_base;
 
-      BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
-      dtp_base = alpha_get_dtprel_base (info->link_info);
-      tp_base = alpha_get_tprel_base (info->link_info);
+      if (elf_hash_table (info->link_info)->tls_sec != NULL)
+	{
+	  dtp_base = alpha_get_dtprel_base (info->link_info);
+	  tp_base = alpha_get_tprel_base (info->link_info);
+	}
+      else
+	dtp_base = tp_base = 0;
       disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
 
       insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
@@ -4644,10 +4648,17 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		 input_bfd, h->root.root.root.string);
 	      ret_val = false;
 	    }
-	  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
-	  value -= tp_base;
-	  if (r_type == R_ALPHA_TPRELHI)
-	    value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
+	  else if (elf_link_local_undefweak_p (&h->root, info))
+	    /* NB: The local undefined TLS symbol address isn't usable
+	       since it isn't mapped to any TLS storage.  Set it to 0
+	       to avoid relocation overflow.  */
+	    value = 0;
+	  else
+	    {
+	      value -= tp_base;
+	      if (r_type == R_ALPHA_TPRELHI)
+		value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
+	    }
 	  goto default_reloc;
 
 	case R_ALPHA_GOTDTPREL:
@@ -4665,8 +4676,12 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		value = 0;
 	      else
 		{
-		  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
-		  if (r_type == R_ALPHA_GOTDTPREL)
+		  if (elf_link_local_undefweak_p (&h->root, info))
+		    /* NB: The local undefined TLS symbol address isn't
+		       usable since it isn't mapped to any TLS storage.
+		       Set it to 0 to avoid relocation overflow.  */
+		    value = 0;
+		  else if (r_type == R_ALPHA_GOTDTPREL)
 		    value -= dtp_base;
 		  else if (bfd_link_executable (info))
 		    value -= tp_base;
diff --git a/ld/testsuite/ld-alpha/alpha.exp b/ld/testsuite/ld-alpha/alpha.exp
index 540580f3e19..f6b16918927 100644
--- a/ld/testsuite/ld-alpha/alpha.exp
+++ b/ld/testsuite/ld-alpha/alpha.exp
@@ -69,3 +69,10 @@ set alphatests {
 #    {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
 
 run_ld_link_tests $alphatests
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+foreach t $test_list {
+    # We need to strip the ".d", but can leave the dirname.
+    verbose [file rootname $t]
+    run_dump_test [file rootname $t]
+}
diff --git a/ld/testsuite/ld-alpha/tlsbin-undef.d b/ld/testsuite/ld-alpha/tlsbin-undef.d
new file mode 100644
index 00000000000..203d0c424e8
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-undef.d
@@ -0,0 +1,2 @@
+#ld:
+#error: .*: undefined reference to `x'
diff --git a/ld/testsuite/ld-alpha/tlsbin-undef.s b/ld/testsuite/ld-alpha/tlsbin-undef.s
new file mode 100644
index 00000000000..b95f48afd69
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-undef.s
@@ -0,0 +1,16 @@
+	.set noreorder
+	.set volatile
+	.set noat
+	.set nomacro
+	.arch ev4
+	.text
+	.align 4
+	.globl _start
+	.ent _start
+_start:
+	ldq $1,x($29)		!gottprel
+	addq $0,$1,$0
+	ret
+	.end _start
+	.hidden x
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef1.d b/ld/testsuite/ld-alpha/tlsbin-weak-undef1.d
new file mode 100644
index 00000000000..a234b5e4ad1
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef1.d
@@ -0,0 +1,14 @@
+#ld: -z norelro -z nomemory-seal
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	00 80 3d a4 	ldq	t0,-32768\(gp\)
+ +[a-f0-9]+:	00 04 01 40 	addq	v0,t0,v0
+ +[a-f0-9]+:	01 80 fa 6b 	ret
+ +[a-f0-9]+:	00 00 fe 2f 	unop	
+#pass
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef1.s b/ld/testsuite/ld-alpha/tlsbin-weak-undef1.s
new file mode 100644
index 00000000000..7cd447ffb6e
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef1.s
@@ -0,0 +1,17 @@
+	.set noreorder
+	.set volatile
+	.set noat
+	.set nomacro
+	.arch ev4
+	.text
+	.align 4
+	.globl _start
+	.ent _start
+_start:
+	ldq $1,x($29)		!gottprel
+	addq $0,$1,$0
+	ret
+	.end _start
+	.weak x
+	.hidden x
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef2.d b/ld/testsuite/ld-alpha/tlsbin-weak-undef2.d
new file mode 100644
index 00000000000..47fb7336674
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef2.d
@@ -0,0 +1,14 @@
+#ld: -z norelro -z nomemory-seal
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	00 00 00 24 	ldah	v0,0\(v0\)
+ +[a-f0-9]+:	00 00 20 a0 	ldl	t0,0\(v0\)
+ +[a-f0-9]+:	01 80 fa 6b 	ret
+ +[a-f0-9]+:	00 00 fe 2f 	unop	
+#pass
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef2.s b/ld/testsuite/ld-alpha/tlsbin-weak-undef2.s
new file mode 100644
index 00000000000..bf05205bb59
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef2.s
@@ -0,0 +1,17 @@
+	.set noreorder
+	.set volatile
+	.set noat
+	.set nomacro
+	.arch ev4
+	.text
+	.align 4
+	.globl _start
+	.ent _start
+_start:
+	ldah $0,x($0)		!tprelhi
+	ldl $1,x($0)		!tprello
+	ret
+	.end _start
+	.weak x
+	.hidden x
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef3.d b/ld/testsuite/ld-alpha/tlsbin-weak-undef3.d
new file mode 100644
index 00000000000..a234b5e4ad1
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef3.d
@@ -0,0 +1,14 @@
+#ld: -z norelro -z nomemory-seal
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	00 80 3d a4 	ldq	t0,-32768\(gp\)
+ +[a-f0-9]+:	00 04 01 40 	addq	v0,t0,v0
+ +[a-f0-9]+:	01 80 fa 6b 	ret
+ +[a-f0-9]+:	00 00 fe 2f 	unop	
+#pass
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef3.s b/ld/testsuite/ld-alpha/tlsbin-weak-undef3.s
new file mode 100644
index 00000000000..c0a5c0a5808
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef3.s
@@ -0,0 +1,22 @@
+	.set noreorder
+	.set volatile
+	.set noat
+	.set nomacro
+	.arch ev4
+	.text
+	.align 4
+	.globl _start
+	.ent _start
+_start:
+	ldq $1,x($29)		!gottprel
+	addq $0,$1,$0
+	ret
+	.end _start
+	.section .tbss,"awT",@nobits
+	.type	y, @object
+	.size	y, 4
+y:
+	.zero	4
+	.weak x
+	.hidden x
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef4.d b/ld/testsuite/ld-alpha/tlsbin-weak-undef4.d
new file mode 100644
index 00000000000..47fb7336674
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef4.d
@@ -0,0 +1,14 @@
+#ld: -z norelro -z nomemory-seal
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	00 00 00 24 	ldah	v0,0\(v0\)
+ +[a-f0-9]+:	00 00 20 a0 	ldl	t0,0\(v0\)
+ +[a-f0-9]+:	01 80 fa 6b 	ret
+ +[a-f0-9]+:	00 00 fe 2f 	unop	
+#pass
diff --git a/ld/testsuite/ld-alpha/tlsbin-weak-undef4.s b/ld/testsuite/ld-alpha/tlsbin-weak-undef4.s
new file mode 100644
index 00000000000..0684a9cbf32
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlsbin-weak-undef4.s
@@ -0,0 +1,22 @@
+	.set noreorder
+	.set volatile
+	.set noat
+	.set nomacro
+	.arch ev4
+	.text
+	.align 4
+	.globl _start
+	.ent _start
+_start:
+	ldah $0,x($0)		!tprelhi
+	ldl $1,x($0)		!tprello
+	ret
+	.end _start
+	.section .tbss,"awT",@nobits
+	.type	y, @object
+	.size	y, 4
+y:
+	.zero	4
+	.weak x
+	.hidden x
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-alpha/tlspic-undef.d b/ld/testsuite/ld-alpha/tlspic-undef.d
new file mode 100644
index 00000000000..e6907997ada
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlspic-undef.d
@@ -0,0 +1,2 @@
+#ld: -shared
+#error: .*: undefined reference to `x'
diff --git a/ld/testsuite/ld-alpha/tlspic-undef.s b/ld/testsuite/ld-alpha/tlspic-undef.s
new file mode 100644
index 00000000000..c4b091fc834
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlspic-undef.s
@@ -0,0 +1,16 @@
+	.set noreorder
+	.set volatile
+	.set noat
+	.set nomacro
+	.arch ev4
+	.text
+	.align 4
+	.globl _start
+	.ent _start
+_start:
+	ldq $1,x($29)		!gotdtprel
+	addq $0,$1,$1
+	ret
+	.end _start
+	.hidden x
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-alpha/tlspic-weak-undef1.d b/ld/testsuite/ld-alpha/tlspic-weak-undef1.d
new file mode 100644
index 00000000000..626da576d66
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlspic-weak-undef1.d
@@ -0,0 +1,14 @@
+#ld: -shared -z norelro -z nomemory-seal
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	00 80 3d a4 	ldq	t0,-32768\(gp\)
+ +[a-f0-9]+:	01 04 01 40 	addq	v0,t0,t0
+ +[a-f0-9]+:	01 80 fa 6b 	ret
+ +[a-f0-9]+:	00 00 fe 2f 	unop	
+#pass
diff --git a/ld/testsuite/ld-alpha/tlspic-weak-undef1.s b/ld/testsuite/ld-alpha/tlspic-weak-undef1.s
new file mode 100644
index 00000000000..bcbe5a173b3
--- /dev/null
+++ b/ld/testsuite/ld-alpha/tlspic-weak-undef1.s
@@ -0,0 +1,22 @@
+	.set noreorder
+	.set volatile
+	.set noat
+	.set nomacro
+	.arch ev4
+	.text
+	.align 4
+	.globl _start
+	.ent _start
+_start:
+	ldq $1,x($29)		!gotdtprel
+	addq $0,$1,$1
+	ret
+	.end _start
+	.section .tbss,"awT",@nobits
+	.type	y, @object
+	.size	y, 4
+y:
+	.zero	4
+	.weak x
+	.hidden x
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-elf/pr34165.c b/ld/testsuite/ld-elf/pr34165.c
new file mode 100644
index 00000000000..3793dda4403
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr34165.c
@@ -0,0 +1,14 @@
+extern __thread int x
+__attribute__((visibility("hidden")))
+__attribute__((weak));
+extern __thread int x_used
+__attribute__((visibility("hidden")))
+__attribute__((weak));
+
+int
+main (void)
+{
+  if (!x_used)
+    x++;
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/tls.exp b/ld/testsuite/ld-elf/tls.exp
index 515824b7f12..d149c3a41df 100644
--- a/ld/testsuite/ld-elf/tls.exp
+++ b/ld/testsuite/ld-elf/tls.exp
@@ -62,6 +62,17 @@ run_ld_link_tests [list \
     ] \
 ]
 
+run_cc_link_tests [list \
+    [list \
+	"pr34165" \
+	"" \
+	"-O2 $NOSANITIZE_CFLAGS" \
+	{ pr34165.c } \
+	{} \
+	"pr34165" \
+    ] \
+]
+
 if [file exists tmpdir/pr22263-1] {
     run_ld_link_tests [list \
 	[list \
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.