[binutils-gdb] alpha: Properly handle local weak undefined symbols
H.J. Lu
hjl@sourceware.org
Sun May 24 22:49:42 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ffea43122dc5deaea75374bd2bd928d1d4182f67
commit ffea43122dc5deaea75374bd2bd928d1d4182f67
Author: H.J. Lu <hjl.tools@gmail.com>
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 <hjl.tools@gmail.com>
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 \
More information about the Binutils-cvs
mailing list