diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2025-07-04 08:39:03 +0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2025-08-20 13:53:32 -0700 |
commit | 0d1e88f8bfb0e62f37bf8a89172cd91373ace5e6 (patch) | |
tree | 48053196a0e72a9cf2402883f5ac5f42bd4742e7 /ld/testsuite | |
parent | cf03cf4e8879bbfe6b90160ff3fda63feb2a898f (diff) | |
download | binutils-0d1e88f8bfb0e62f37bf8a89172cd91373ace5e6.zip binutils-0d1e88f8bfb0e62f37bf8a89172cd91373ace5e6.tar.gz binutils-0d1e88f8bfb0e62f37bf8a89172cd91373ace5e6.tar.bz2 |
x86: Add GLIBC_ABI_GNU2_TLS version dependency
On Linux/x86, programs and shared libraries compiled with
-mtls-dialect=gnu2 may fail silently at run-time against glibc without
the GNU2 TLS run-time fixes for:
https://sourceware.org/bugzilla/show_bug.cgi?id=31501
https://sourceware.org/bugzilla/show_bug.cgi?id=31372
A version tag, GLIBC_ABI_GNU2_TLS, has been added to glibc to indicate
that glibc has the working GNU2 TLS run-time. Add the --gnu2-tls-tag
option to i386/x86-64 ELF linker to add the GLIBC_ABI_GNU2_TLS version
dependency in output programs and shared libraries when linking against
glibc if input relocatable object files have R_386_TLS_DESC_CALL or
R_X86_64_TLSDESC_CALL relocation. The output will fail to load and run
at run-time against glibc which doesn't define the GLIBC_ABI_GNU2_TLS
version.
Add the --enable-gnu2-tls-tag configure option to enable --gnu2-tls-tag
by default. If unspecified, linker will add the GLIBC_ABI_GNU2_TLS
version dependency if input object files have R_386_TLS_DESC_CALL or
R_X86_64_TLSDESC_CALL relocation and libc.so defines the GLIBC_ABI_GNU2_TLS
version.
Update elf_link_add_glibc_verneed to properly add the GLIBC_2.36 version
dependency when -z mark-plt -z nopack-relative-relocs passed to x86-64
ELF linker.
bfd/
PR ld/33130
* elf-bfd.h (_bfd_elf_link_add_glibc_version_dependency): Add
a pointer to bool argument.
* elf-linker-x86.h (elf_linker_x86_params): Add
gnu2_tls_version_tag.
* elf32-i386.c (elf_i386_scan_relocs): Set has_tls_desc_call to
1 for R_386_TLS_DESC_CALL.
(elf_i386_add_glibc_version_dependency): New. Undef before
FreeBSD support.
* elf64-x86-64.c (elf_x86_64_scan_relocs): Set has_tls_desc_call
to 1 for R_X86_64_TLSDESC_CALL.
(elf_x86_64_add_glibc_version_dependency): Add GLIBC_ABI_GNU2_TLS
version dependency if GLIBC_ABI_GNU2_TLS dependency isn't disabled
and has_tlsdesc_call isn't 0.
(elf_backend_add_glibc_version_dependency): Undef before FreeBSD
support and redefine for elf32-x86-64.
* elflink.c (elf_link_add_glibc_verneed): Changed to return bool.
Remove the pointer to elf_find_verdep_info argument. Add a
pointer to bool argument, auto_version. Return true if linked
against glibc. Otherwise return false. If the version dependency
is added, set *auto_version to true. If *auto_version is true,
add the version dependency only if libc.so defines the version.
(_bfd_elf_link_add_glibc_version_dependency): Add a pointer to
bool argument and pass it to elf_link_add_glibc_verneed.
(_bfd_elf_link_add_dt_relr_dependency): Pass NULL to
_bfd_elf_link_add_glibc_version_dependency.
* elfxx-x86.h (elf_x86_link_hash_table): Add has_tls_desc_call.
ld/
PR ld/33130
* NEWS: Mention --gnu2-tls-tag, --no-gnu2-tls-tag and
--enable-gnu2-tls-tag.
* config.in: Regenerated.
* configure: Likewise.
* configure.ac: Add --enable-gnu2-tls-tag.
* ld.texi: Document --gnu2-tls-tag/--no-gnu2-tls-tag.
* ldlex.h (option_values): Add OPTION_GNU2_TLS_VERSION_TAG and
OPTION_NO_GNU2_TLS_VERSION_TAG.
* emulparams/elf32_x86_64.sh (EXTRA_EM_FILE): Changed to
"elf-x86-64-glibc".
* emulparams/elf_i386.sh (EXTRA_EM_FILE): Set to "elf-i386-glibc".
* emulparams/elf_i386_fbsd.sh (EXTRA_EM_FILE): New. Set to
"elf-x86".
* emulparams/elf_i386_haiku.sh (EXTRA_EM_FILE): Likewise.
* emulparams/elf_x86_64.sh (EXTRA_EM_FILE): Likewise.
* emulparams/elf_x86_64_fbsd.sh (EXTRA_EM_FILE): New. Set to
"elf-x86-64".
* emulparams/elf_x86_64_haiku.sh (EXTRA_EM_FILE): Likewise.
* (EXTRA_EM_FILE): Likewise.
* (EXTRA_EM_FILE): Likewise.
* emultempl/elf-i386-glibc.em: New file.
* emultempl/elf-x86-64-glibc.em: Likewise.
* emultempl/elf-x86-64.em: Likewise.
* emultempl/elf-x86-glibc.em: Likewise.
* emultempl/elf-x86.em (elf_x86_64_before_parse): Removed.
(LDEMUL_BEFORE_PARSE): Likewise.
(elf_x86_64_before_allocation): Likewise.
(LDEMUL_BEFORE_ALLOCATION): Likewise.
* emultempl/solaris2-x86-64.em: New file.
* testsuite/ld-i386/gnu2-tls-1.s: Likewise.
* testsuite/ld-i386/gnu2-tls-1a.rd: Likewise.
* testsuite/ld-i386/gnu2-tls-1b.rd: Likewise.
* testsuite/ld-x86-64/gnu2-tls-1.s: Likewise.
* testsuite/ld-x86-64/gnu2-tls-1a.rd: Likewise.
* testsuite/ld-x86-64/gnu2-tls-1b.rd: Likewise.
* testsuite/ld-x86-64/mark-plt-2.rd: Likewise.
* testsuite/ld-x86-64/mark-plt-2.s: Likewise.
* testsuite/ld-i386/i386.exp: Run GLIBC_ABI_GNU2_TLS tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'ld/testsuite')
-rw-r--r-- | ld/testsuite/ld-i386/gnu2-tls-1.s | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/gnu2-tls-1a.rd | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/gnu2-tls-1b.rd | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/i386.exp | 23 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/gnu2-tls-1.s | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/gnu2-tls-1a.rd | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/gnu2-tls-1b.rd | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-2.rd | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-2.s | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/x86-64.exp | 26 |
10 files changed, 112 insertions, 1 deletions
diff --git a/ld/testsuite/ld-i386/gnu2-tls-1.s b/ld/testsuite/ld-i386/gnu2-tls-1.s new file mode 100644 index 0000000..e3841c7 --- /dev/null +++ b/ld/testsuite/ld-i386/gnu2-tls-1.s @@ -0,0 +1,11 @@ + .section .text.startup,"ax",@progbits + .p2align 4 + .globl main + .type main, @function +main: + leal ld@TLSDESC(%ebx), %eax + call *ld@TLSCALL(%eax) + addl %gs:0, %eax + ret + .size main, .-main + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-i386/gnu2-tls-1a.rd b/ld/testsuite/ld-i386/gnu2-tls-1a.rd new file mode 100644 index 0000000..3eb926a --- /dev/null +++ b/ld/testsuite/ld-i386/gnu2-tls-1a.rd @@ -0,0 +1,7 @@ +#... +Version needs section '.gnu.version_r' contains 1 entry: + Addr: 0x[0-9a-f]+ +Offset: 0x[0-9a-f]+ +Link: +[0-9]+ +\(.dynstr\) + +0+: Version: 1 +File: libc\.so\.6(|\.1) +Cnt: +[0-9]+ +#... + 0x[a-f0-9]+: Name: GLIBC_ABI_GNU2_TLS Flags: none Version: [0-9]+ +#pass diff --git a/ld/testsuite/ld-i386/gnu2-tls-1b.rd b/ld/testsuite/ld-i386/gnu2-tls-1b.rd new file mode 100644 index 0000000..33ef8ac --- /dev/null +++ b/ld/testsuite/ld-i386/gnu2-tls-1b.rd @@ -0,0 +1,4 @@ +#failif +#... + 0x[a-f0-9]+: Name: GLIBC_ABI_GNU2_TLS Flags: none Version: [0-9]+ +#... diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 8633a66..622c06e 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -1519,6 +1519,29 @@ run_ld_link_tests [list \ ] \ ] +# The musl C library does not support --gnu2-tls-tag. +if { ![istarget *-*-musl] + && [check_compiler_available] } { + run_cc_link_tests [list \ + [list \ + "Build gnu2-tls-1a.so" \ + "-shared -Wl,--no-as-needed,--gnu2-tls-tag" \ + "-fPIC" \ + { gnu2-tls-1.s } \ + {{readelf {-W --version-info} gnu2-tls-1a.rd}} \ + "gnu2-tls-1a.so" \ + ] \ + [list \ + "Build gnu2-tls-1b.so" \ + "-shared -Wl,--no-as-needed,--no-gnu2-tls-tag" \ + "-fPIC" \ + { gnu2-tls-1.s } \ + {{readelf {-W --version-info} gnu2-tls-1b.rd}} \ + "gnu2-tls-1b.so" \ + ] \ + ] +} + # Linux only tests run_dump_test "pltgot-1" run_dump_test "pltgot-2" diff --git a/ld/testsuite/ld-x86-64/gnu2-tls-1.s b/ld/testsuite/ld-x86-64/gnu2-tls-1.s new file mode 100644 index 0000000..eca788c --- /dev/null +++ b/ld/testsuite/ld-x86-64/gnu2-tls-1.s @@ -0,0 +1,11 @@ + .section .text.startup,"ax",@progbits + .p2align 4 + .globl main + .type main, @function +main: + leaq foo@TLSDESC(%rip), %rax + call *foo@TLSCALL(%rax) + movl %fs:(%rax), %eax + ret + .size main, .-main + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/gnu2-tls-1a.rd b/ld/testsuite/ld-x86-64/gnu2-tls-1a.rd new file mode 100644 index 0000000..3eb926a --- /dev/null +++ b/ld/testsuite/ld-x86-64/gnu2-tls-1a.rd @@ -0,0 +1,7 @@ +#... +Version needs section '.gnu.version_r' contains 1 entry: + Addr: 0x[0-9a-f]+ +Offset: 0x[0-9a-f]+ +Link: +[0-9]+ +\(.dynstr\) + +0+: Version: 1 +File: libc\.so\.6(|\.1) +Cnt: +[0-9]+ +#... + 0x[a-f0-9]+: Name: GLIBC_ABI_GNU2_TLS Flags: none Version: [0-9]+ +#pass diff --git a/ld/testsuite/ld-x86-64/gnu2-tls-1b.rd b/ld/testsuite/ld-x86-64/gnu2-tls-1b.rd new file mode 100644 index 0000000..33ef8ac --- /dev/null +++ b/ld/testsuite/ld-x86-64/gnu2-tls-1b.rd @@ -0,0 +1,4 @@ +#failif +#... + 0x[a-f0-9]+: Name: GLIBC_ABI_GNU2_TLS Flags: none Version: [0-9]+ +#... diff --git a/ld/testsuite/ld-x86-64/mark-plt-2.rd b/ld/testsuite/ld-x86-64/mark-plt-2.rd new file mode 100644 index 0000000..b0ed702 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-2.rd @@ -0,0 +1,7 @@ +#... +Version needs section '.gnu.version_r' contains 1 entry: + Addr: 0x[0-9a-f]+ +Offset: 0x[0-9a-f]+ +Link: +[0-9]+ +\(.dynstr\) + +0+: Version: 1 +File: libc\.so\.6(|\.1) +Cnt: +[0-9]+ +#... + 0x[a-f0-9]+: Name: (GLIBC_2.36|GLIBC_ABI_DT_X86_64_PLT) Flags: none Version: [0-9]+ +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-2.s b/ld/testsuite/ld-x86-64/mark-plt-2.s new file mode 100644 index 0000000..c816567 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-2.s @@ -0,0 +1,13 @@ + .text + .globl foo + .type foo, @function +foo: + subq $8, %rsp + leaq xxx@TLSDESC(%rip), %rax + .nops 10 + call *xxx@TLSCALL(%rax) + movl %fs:(%rax), %eax + addq $8, %rsp + call bar + ret + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 9d97531..63cf1e4 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -2360,7 +2360,7 @@ run_dump_test "ibt-plt-3b-x32" run_dump_test "ibt-plt-3c-x32" run_dump_test "ibt-plt-3d-x32" -# Skip -z mark-plt tests on MUSL. +# Skip -z mark-plt and --gnu2-tls-tag tests on MUSL. if { [istarget "x86_64-*-musl*"]} { set ASFLAGS "$saved_ASFLAGS" return @@ -2386,6 +2386,30 @@ if { [check_compiler_available] } { {readelf {-W --version-info} mark-plt-1b.rd}} \ "mark-plt-1.so" \ ] \ + [list \ + "Build mark-plt-2.so" \ + "-shared -Wl,--no-as-needed,-z,mark-plt,-z,nopack-relative-relocs" \ + "-fPIC" \ + { mark-plt-2.s } \ + {{readelf {-W --version-info} mark-plt-2.rd}} \ + "mark-plt-2.so" \ + ] \ + [list \ + "Build gnu2-tls-1a.so" \ + "-shared -Wl,--no-as-needed,--gnu2-tls-tag" \ + "-fPIC" \ + { gnu2-tls-1.s } \ + {{readelf {-W --version-info} gnu2-tls-1a.rd}} \ + "gnu2-tls-1a.so" \ + ] \ + [list \ + "Build gnu2-tls-1b.so" \ + "-shared -Wl,--no-as-needed,--no-gnu2-tls-tag" \ + "-fPIC" \ + { gnu2-tls-1.s } \ + {{readelf {-W --version-info} gnu2-tls-1b.rd}} \ + "gnu2-tls-1b.so" \ + ] \ ] } |