[v4] alpha: Properly handle local weak undefined symbols

Message ID CAMe9rOpd9=CWnwa0ZoJ3V03Ktw0t+jGshdxrqGDvA=bGin2RTQ@mail.gmail.com
State New
Headers
Series [v4] alpha: Properly handle local weak undefined symbols |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 fail Test failed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

H.J. Lu May 24, 2026, 5:06 a.m. UTC
  On Sun, May 24, 2026 at 11:55 AM Alan Modra <amodra@gmail.com> wrote:
>
> On Sun, May 24, 2026 at 07:24:46AM +0800, H.J. Lu wrote:
> > 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.  Since the undefined TLS symbol
> > address doesn't map to any TLS storage, it isn't usable.  Also set
> > dtp_base and tp_base to 0 if elf_hash_table (info)->tls_sec == NULL.
> >
> > bfd/
> >
> >       PR ld/34165
> >       * 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): 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/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.
>
> Thanks, this is good.  aarch64-linux and ia64-linux fail the pr34165
> test, exposing similary problems in those backends.
>

It turns out that we need special handling for local weak undefined symbols.
Otherwise, we may get relocation overflow.  Here is the v4 patch to set
the local undefined TLS symbol value to 0 with a new testcase.
  

Comments

Alan Modra May 24, 2026, 11:16 a.m. UTC | #1
On Sun, May 24, 2026 at 01:06:44PM +0800, H.J. Lu wrote:
> It turns out that we need special handling for local weak undefined symbols.
> Otherwise, we may get relocation overflow.  Here is the v4 patch to set
> the local undefined TLS symbol value to 0 with a new testcase.

OK.
  
Alan Modra May 27, 2026, 12:52 p.m. UTC | #2
asan complains "runtime error: member access within null pointer"
for &h->root with NULL h, which is annoying since &h->root is the
same address as h, causing
alpha-linux-gnu  +FAIL: TLS -fpic -shared
alpha-linux-gnu  +FAIL: TLS -fpic and -fno-pic exec
alpha-linux-gnu  +FAIL: TLS -fpic and -fno-pic exec -relax

	* elf64-alpha.c (elf64_alpha_relocate_section): Fix asan
	complaint.

diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 594bfe9a80e..8cc70610c59 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -4648,7 +4648,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		 input_bfd, h->root.root.root.string);
 	      ret_val = false;
 	    }
-	  else if (elf_link_local_undefweak_p (&h->root, info))
+	  else if (elf_link_local_undefweak_p (h ? &h->root : NULL, 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.  */
@@ -4676,7 +4676,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		value = 0;
 	      else
 		{
-		  if (elf_link_local_undefweak_p (&h->root, info))
+		  if (elf_link_local_undefweak_p (h ? &h->root : NULL, 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.  */
  

Patch

From 5d1e883ebe2e71395992ddeb6ff412d6cf5899e4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sat, 23 May 2026 05:12:10 +0800
Subject: [PATCH v4] 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 <hjl.tools@gmail.com>
---
 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(-)
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-undef.d
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-undef.s
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef1.d
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef1.s
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef2.d
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef2.s
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef3.d
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef3.s
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef4.d
 create mode 100644 ld/testsuite/ld-alpha/tlsbin-weak-undef4.s
 create mode 100644 ld/testsuite/ld-alpha/tlspic-undef.d
 create mode 100644 ld/testsuite/ld-alpha/tlspic-undef.s
 create mode 100644 ld/testsuite/ld-alpha/tlspic-weak-undef1.d
 create mode 100644 ld/testsuite/ld-alpha/tlspic-weak-undef1.s
 create mode 100644 ld/testsuite/ld-elf/pr34165.c

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 \
-- 
2.54.0