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