Additional TLS test cases

Resolves: RHEL-58989
This commit is contained in:
Frédéric Bérat 2025-01-10 18:56:25 +01:00
parent 19df5781cb
commit 0c05a36bc6
3 changed files with 729 additions and 1 deletions

228
glibc-RHEL-58989-1.patch Normal file
View File

@ -0,0 +1,228 @@
commit 3d53d18fc71c5d9ef4773b8bce04d54b80181926
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Mar 12 13:21:20 2024 -0300
elf: Enable TLS descriptor tests on aarch64
The aarch64 uses 'trad' for traditional tls and 'desc' for tls
descriptors, but unlike other targets it defaults to 'desc'. The
gnutls2 configure check does not set aarch64 as an ABI that uses
TLS descriptors, which then disable somes stests.
Also rename the internal machinery fron gnu2 to tls descriptors.
Checked on aarch64-linux-gnu.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Conflicts:
configure (regenerated)
configure.ac (fixed context)
elf/Makefile (fixed context)
sysdeps/arm/Makefile (fixed context)
diff --git a/configure b/configure
index afa094324cdcf96d..605309159db1e2a0 100755
--- a/configure
+++ b/configure
@@ -619,7 +619,7 @@ LIBGD
libc_cv_cc_loop_to_function
libc_cv_cc_submachine
libc_cv_cc_nofma
-libc_cv_mtls_dialect_gnu2
+libc_cv_mtls_descriptor
fno_unit_at_a_time
libc_cv_has_glob_dat
libc_cv_hashstyle
@@ -3896,6 +3896,9 @@ libc_config_ok=no
# whether to use such directories.
with_fp_cond=1
+# A preconfigure script may define another name to TLS descriptor variant
+mtls_descriptor=gnu2
+
if frags=`ls -d $srcdir/sysdeps/*/preconfigure 2> /dev/null`
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysdeps preconfigure fragments" >&5
@@ -6162,9 +6165,9 @@ else
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -mtls-dialect=gnu2" >&5
-$as_echo_n "checking for -mtls-dialect=gnu2... " >&6; }
-if ${libc_cv_mtls_dialect_gnu2+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for tls descriptor support" >&5
+$as_echo_n "checking for tls descriptor support... " >&6; }
+if ${libc_cv_mtls_descriptor+:} false; then :
$as_echo_n "(cached) " >&6
else
cat > conftest.c <<EOF
@@ -6174,25 +6177,25 @@ void foo (void)
i = 10;
}
EOF
-if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S -fPIC -mtls-dialect=gnu2
- conftest.c 1>&5'
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_descriptor -nostdlib -nostartfiles
+ -shared conftest.c -o conftest 1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
- libc_cv_mtls_dialect_gnu2=yes
+ libc_cv_mtls_descriptor=$mtls_descriptor
else
- libc_cv_mtls_dialect_gnu2=no
+ libc_cv_mtls_descriptor=no
fi
rm -f conftest*
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mtls_dialect_gnu2" >&5
-$as_echo "$libc_cv_mtls_dialect_gnu2" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mtls_descriptor" >&5
+$as_echo "$libc_cv_mtls_descriptor" >&6; }
config_vars="$config_vars
-have-mtls-dialect-gnu2 = $libc_cv_mtls_dialect_gnu2"
+have-mtls-descriptor = $libc_cv_mtls_descriptor"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc puts quotes around section names" >&5
$as_echo_n "checking whether cc puts quotes around section names... " >&6; }
diff --git a/configure.ac b/configure.ac
index 85ea64f9f5f4fd35..d18d8bdff9a7849d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -533,6 +533,9 @@ libc_config_ok=no
# whether to use such directories.
with_fp_cond=1
+# A preconfigure script may define another name to TLS descriptor variant
+mtls_descriptor=gnu2
+
dnl Let sysdeps/*/preconfigure act here.
LIBC_PRECONFIGURE([$srcdir], [for sysdeps])
@@ -1429,7 +1432,7 @@ else
fi
AC_SUBST(fno_unit_at_a_time)
-AC_CACHE_CHECK([for -mtls-dialect=gnu2], libc_cv_mtls_dialect_gnu2,
+AC_CACHE_CHECK([for tls descriptor support], libc_cv_mtls_descriptor,
[dnl
cat > conftest.c <<EOF
__thread int i;
@@ -1438,16 +1441,16 @@ void foo (void)
i = 10;
}
EOF
-if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -S -fPIC -mtls-dialect=gnu2
- conftest.c 1>&AS_MESSAGE_LOG_FD])
+if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_descriptor -nostdlib -nostartfiles
+ -shared conftest.c -o conftest 1>&AS_MESSAGE_LOG_FD])
then
- libc_cv_mtls_dialect_gnu2=yes
+ libc_cv_mtls_descriptor=$mtls_descriptor
else
- libc_cv_mtls_dialect_gnu2=no
+ libc_cv_mtls_descriptor=no
fi
rm -f conftest*])
-AC_SUBST(libc_cv_mtls_dialect_gnu2)
-LIBC_CONFIG_VAR([have-mtls-dialect-gnu2], [$libc_cv_mtls_dialect_gnu2])
+AC_SUBST(libc_cv_mtls_descriptor)
+LIBC_CONFIG_VAR([have-mtls-descriptor], [$libc_cv_mtls_descriptor])
AC_CACHE_CHECK(whether cc puts quotes around section names,
libc_cv_have_section_quotes,
diff --git a/elf/Makefile b/elf/Makefile
index 7d686ca7d190c921..65eb3b9b28183821 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -944,13 +944,13 @@ modules-names-tests = $(filter-out ifuncmod% tst-tlsmod% \
tst-hash-collision3-mod,\
$(modules-names))
-ifeq (yes,$(have-mtls-dialect-gnu2))
+ifneq (no,$(have-mtls-descriptor))
tests += tst-gnu2-tls1
modules-names += tst-gnu2-tls1mod
$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
tst-gnu2-tls1mod.so-no-z-defs = yes
-CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
-endif # $(have-mtls-dialect-gnu2)
+CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=$(have-mtls-descriptor)
+endif # $(have-mtls-descriptor)
ifeq (yes,$(have-protected-data))
modules-names += tst-protected1moda tst-protected1modb
@@ -2719,11 +2719,11 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \
$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-audit-tlsdesc-mod2.so \
$(shared-thread-library)
-ifeq (yes,$(have-mtls-dialect-gnu2))
+ifneq (no,$(have-mtls-descriptor))
# The test is valid for all TLS types, but we want to exercise GNU2
# TLS if possible.
-CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
-CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
+CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=$(have-mtls-descriptor)
endif
$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
@@ -2763,10 +2763,14 @@ $(objpfx)tst-tlsgap.out: \
$(objpfx)tst-tlsgap-mod0.so \
$(objpfx)tst-tlsgap-mod1.so \
$(objpfx)tst-tlsgap-mod2.so
-ifeq (yes,$(have-mtls-dialect-gnu2))
-CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=gnu2
-CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
-CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
+
+ifneq (no,$(have-mtls-descriptor))
+CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-gnu2-tls2mod0.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-gnu2-tls2mod1.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-gnu2-tls2mod2.c += -mtls-dialect=$(have-mtls-descriptor)
endif
$(objpfx)tst-recursive-tls: $(objpfx)tst-recursive-tlsmallocmod.so
diff --git a/sysdeps/aarch64/preconfigure b/sysdeps/aarch64/preconfigure
index d9bd1f8558a079cb..19657b627bc84c4e 100644
--- a/sysdeps/aarch64/preconfigure
+++ b/sysdeps/aarch64/preconfigure
@@ -2,5 +2,6 @@ case "$machine" in
aarch64*)
base_machine=aarch64
machine=aarch64
+ mtls_descriptor=desc
;;
esac
diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile
index fb4164f0d9cf71fa..efe08b15e16ccda4 100644
--- a/sysdeps/arm/Makefile
+++ b/sysdeps/arm/Makefile
@@ -18,15 +18,15 @@ $(objpfx)libgcc-stubs.a: $(objpfx)aeabi_unwind_cpp_pr1.os
lib-noranlib: $(objpfx)libgcc-stubs.a
ifeq ($(build-shared),yes)
-ifeq ($(have-arm-tls-desc),yes)
+ifneq (no,$(have-mtls-descriptor))
tests += tst-armtlsdescloc tst-armtlsdescextnow tst-armtlsdescextlazy
modules-names += tst-armtlsdesclocmod
modules-names += tst-armtlsdescextlazymod tst-armtlsdescextnowmod
CPPFLAGS-tst-armtlsdescextnowmod.c += -Dstatic=
CPPFLAGS-tst-armtlsdescextlazymod.c += -Dstatic=
-CFLAGS-tst-armtlsdesclocmod.c += -mtls-dialect=gnu2
-CFLAGS-tst-armtlsdescextnowmod.c += -mtls-dialect=gnu2
-CFLAGS-tst-armtlsdescextlazymod.c += -mtls-dialect=gnu2
+CFLAGS-tst-armtlsdesclocmod.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-armtlsdescextnowmod.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-armtlsdescextlazymod.c += -mtls-dialect=$(have-mtls-descriptor)
LDFLAGS-tst-armtlsdescextnowmod.so += -Wl,-z,now
tst-armtlsdescloc-ENV = LD_BIND_NOW=1
tst-armtlsdescextnow-ENV = LD_BIND_NOW=1

495
glibc-RHEL-58989-2.patch Normal file
View File

@ -0,0 +1,495 @@
commit 9b5f2eb9fc5d3cf4b984f6002e69aac43296e922
Author: Joseph Myers <josmyers@redhat.com>
Date: Thu Dec 5 09:53:47 2024 +0000
Add further test of TLS
Add an additional test of TLS variables, with different alignment,
accessed from different modules. The idea of the alignment test is
similar to tst-tlsalign and the same code is shared for setting up
test variables, but unlike the tst-tlsalign code, there are multiple
threads and variables are accessed from multiple objects to verify
that they get a consistent notion of the address of an object within a
thread. Threads are repeatedly created and shut down to verify proper
initialization in each new thread. The test is also repeated with TLS
descriptors when supported. (However, only initial-exec TLS is
covered in this test.)
Tested for x86_64.
Conflicts:
elf/Makefile (fixup context)
diff --git a/elf/Makefile b/elf/Makefile
index 4a9c983686126adf..9d48e408de0a67a4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -454,6 +454,8 @@ tests += \
tst-tls19 \
tst-tls20 \
tst-tls21 \
+ tst-tls22 \
+ tst-tls22-gnu2 \
tst-tls4 \
tst-tls5 \
tst-tlsalign \
@@ -592,9 +594,15 @@ tst-tls-many-dynamic-modules-dep-bad = \
extra-test-objs += \
$(tlsmod17a-modules:=.os) \
$(tlsmod18a-modules:=.os) \
+ tst-tls22-mod1-vars.os \
+ tst-tls22-mod2-vars.os \
+ tst-tls22-vars.o \
tst-tlsalign-vars.o \
# extra-test-objs
test-extras += \
+ tst-tls22-mod1-vars \
+ tst-tls22-mod2-vars \
+ tst-tls22-vars \
tst-tlsalign-vars \
tst-tlsmod17a \
tst-tlsmod18a \
@@ -840,6 +848,10 @@ modules-names = \
tst-tls19mod3 \
tst-tls20mod-bad \
tst-tls21mod \
+ tst-tls22-mod1 \
+ tst-tls22-mod1-gnu2 \
+ tst-tls22-mod2 \
+ tst-tls22-mod2-gnu2 \
tst-tlsalign-lib \
tst-tlsgap-mod0 \
tst-tlsgap-mod1 \
@@ -2822,3 +2834,27 @@ $(objpfx)tst-hash-collision2-sysv: $(objpfx)tst-hash-collision2-mod1-sysv.so \
LDFLAGS-tst-hash-collision3-mod.so = \
-Wl,--version-script=tst-hash-collision3-mod.map
$(objpfx)tst-hash-collision3: $(objpfx)tst-hash-collision3-mod.so
+
+$(objpfx)tst-tls22: $(objpfx)tst-tls22-vars.o $(objpfx)tst-tls22-mod1.so \
+ $(objpfx)tst-tls22-mod2.so $(shared-thread-library)
+$(objpfx)tst-tls22-mod1.so: $(objpfx)tst-tls22-mod1.os \
+ $(objpfx)tst-tls22-mod1-vars.os $(objpfx)tst-tls22-mod2.so
+$(objpfx)tst-tls22-mod2.so: $(objpfx)tst-tls22-mod2.os \
+ $(objpfx)tst-tls22-mod2-vars.os
+$(objpfx)tst-tls22-gnu2: $(objpfx)tst-tls22-vars.o \
+ $(objpfx)tst-tls22-mod1-gnu2.so $(objpfx)tst-tls22-mod2-gnu2.so \
+ $(shared-thread-library)
+$(objpfx)tst-tls22-mod1-gnu2.so: $(objpfx)tst-tls22-mod1-gnu2.os \
+ $(objpfx)tst-tls22-mod1-vars.os $(objpfx)tst-tls22-mod2-gnu2.so
+$(objpfx)tst-tls22-mod2-gnu2.so: $(objpfx)tst-tls22-mod2-gnu2.os \
+ $(objpfx)tst-tls22-mod2-vars.os
+ifneq (no,$(have-mtls-descriptor))
+CFLAGS-tst-tls22-gnu2.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-tls22-mod1-gnu2.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-tls22-mod2-gnu2.c += -mtls-dialect=$(have-mtls-descriptor)
+endif
+# These reference symbols from the main executable.
+tst-tls22-mod1.so-no-z-defs = yes
+tst-tls22-mod1-gnu2.so-no-z-defs = yes
+tst-tls22-mod2.so-no-z-defs = yes
+tst-tls22-mod2-gnu2.so-no-z-defs = yes
diff --git a/elf/tst-tls22-gnu2.c b/elf/tst-tls22-gnu2.c
new file mode 100644
index 0000000000000000..d9ce6df0b2bcc201
--- /dev/null
+++ b/elf/tst-tls22-gnu2.c
@@ -0,0 +1 @@
+#include <tst-tls22.c>
diff --git a/elf/tst-tls22-mod1-gnu2.c b/elf/tst-tls22-mod1-gnu2.c
new file mode 100644
index 0000000000000000..0b085fe175b74962
--- /dev/null
+++ b/elf/tst-tls22-mod1-gnu2.c
@@ -0,0 +1 @@
+#include <tst-tls22-mod1.c>
diff --git a/elf/tst-tls22-mod1-vars.c b/elf/tst-tls22-mod1-vars.c
new file mode 100644
index 0000000000000000..bdb7358287a325ee
--- /dev/null
+++ b/elf/tst-tls22-mod1-vars.c
@@ -0,0 +1,9 @@
+#include <tst-tls22.h>
+
+#define tdata1 mod1_tdata1
+#define tdata2 mod1_tdata2
+#define tdata3 mod1_tdata3
+#define tbss1 mod1_tbss1
+#define tbss2 mod1_tbss2
+#define tbss3 mod1_tbss3
+#include <tst-tlsalign-vars.c>
diff --git a/elf/tst-tls22-mod1.c b/elf/tst-tls22-mod1.c
new file mode 100644
index 0000000000000000..3a47d7bbc6cd16c2
--- /dev/null
+++ b/elf/tst-tls22-mod1.c
@@ -0,0 +1,27 @@
+/* Test TLS with varied alignment and multiple modules and threads.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <tst-tls22.h>
+
+void
+test_mod1 (struct one_thread_data *data, int base_val)
+{
+ STORE_ADDRS (&data->mod1_self, mod1);
+ STORE_ADDRS (&data->exe_from_mod1, exe);
+ STORE_ADDRS (&data->mod2_from_mod1, mod2);
+}
diff --git a/elf/tst-tls22-mod2-gnu2.c b/elf/tst-tls22-mod2-gnu2.c
new file mode 100644
index 0000000000000000..a5260e0616d8b595
--- /dev/null
+++ b/elf/tst-tls22-mod2-gnu2.c
@@ -0,0 +1 @@
+#include <tst-tls22-mod2.c>
diff --git a/elf/tst-tls22-mod2-vars.c b/elf/tst-tls22-mod2-vars.c
new file mode 100644
index 0000000000000000..9ef3452bba56e829
--- /dev/null
+++ b/elf/tst-tls22-mod2-vars.c
@@ -0,0 +1,9 @@
+#include <tst-tls22.h>
+
+#define tdata1 mod2_tdata1
+#define tdata2 mod2_tdata2
+#define tdata3 mod2_tdata3
+#define tbss1 mod2_tbss1
+#define tbss2 mod2_tbss2
+#define tbss3 mod2_tbss3
+#include <tst-tlsalign-vars.c>
diff --git a/elf/tst-tls22-mod2.c b/elf/tst-tls22-mod2.c
new file mode 100644
index 0000000000000000..5d26d592b0262b1e
--- /dev/null
+++ b/elf/tst-tls22-mod2.c
@@ -0,0 +1,26 @@
+/* Test TLS with varied alignment and multiple modules and threads.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <tst-tls22.h>
+
+void
+test_mod2 (struct one_thread_data *data, int base_val)
+{
+ STORE_ADDRS (&data->mod2_self, mod2);
+ STORE_ADDRS (&data->exe_from_mod2, exe);
+}
diff --git a/elf/tst-tls22-vars.c b/elf/tst-tls22-vars.c
new file mode 100644
index 0000000000000000..2ad3ee7a3b6ac980
--- /dev/null
+++ b/elf/tst-tls22-vars.c
@@ -0,0 +1,9 @@
+#include <tst-tls22.h>
+
+#define tdata1 exe_tdata1
+#define tdata2 exe_tdata2
+#define tdata3 exe_tdata3
+#define tbss1 exe_tbss1
+#define tbss2 exe_tbss2
+#define tbss3 exe_tbss3
+#include <tst-tlsalign-vars.c>
diff --git a/elf/tst-tls22.c b/elf/tst-tls22.c
new file mode 100644
index 0000000000000000..35a8cd82b22462ff
--- /dev/null
+++ b/elf/tst-tls22.c
@@ -0,0 +1,147 @@
+/* Test TLS with varied alignment and multiple modules and threads.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xthread.h>
+#include <tst-tls22.h>
+
+static void
+check_addrs_align (const struct obj_addrs *addrs)
+{
+ TEST_COMPARE (addrs->addr_tdata1 & (__alignof__ (int) - 1), 0);
+ TEST_COMPARE (addrs->addr_tdata2 & 0xf, 0);
+ TEST_COMPARE (addrs->addr_tdata3 & 0xfff, 0);
+ TEST_COMPARE (addrs->addr_tbss1 & (__alignof__ (int) - 1), 0);
+ TEST_COMPARE (addrs->addr_tbss2 & 0xf, 0);
+ TEST_COMPARE (addrs->addr_tbss3 & 0xfff, 0);
+}
+
+static void
+check_addrs_same (const struct obj_addrs *addrs1,
+ const struct obj_addrs *addrs2)
+{
+ TEST_COMPARE (addrs1->addr_tdata1, addrs2->addr_tdata1);
+ TEST_COMPARE (addrs1->addr_tdata2, addrs2->addr_tdata2);
+ TEST_COMPARE (addrs1->addr_tdata3, addrs2->addr_tdata3);
+ TEST_COMPARE (addrs1->addr_tbss1, addrs2->addr_tbss1);
+ TEST_COMPARE (addrs1->addr_tbss2, addrs2->addr_tbss2);
+ TEST_COMPARE (addrs1->addr_tbss3, addrs2->addr_tbss3);
+}
+
+static void
+check_vals_before (const struct obj_values *vals)
+{
+ TEST_COMPARE (vals->val_tdata1, 1);
+ TEST_COMPARE (vals->val_tdata2, 2);
+ TEST_COMPARE (vals->val_tdata3, 4);
+ TEST_COMPARE (vals->val_tbss1, 0);
+ TEST_COMPARE (vals->val_tbss2, 0);
+ TEST_COMPARE (vals->val_tbss3, 0);
+}
+
+static void
+check_vals_after (const struct obj_values *vals, int base_val)
+{
+ TEST_COMPARE (vals->val_tdata1, base_val);
+ TEST_COMPARE (vals->val_tdata2, base_val + 1);
+ TEST_COMPARE (vals->val_tdata3, base_val + 2);
+ TEST_COMPARE (vals->val_tbss1, base_val + 3);
+ TEST_COMPARE (vals->val_tbss2, base_val + 4);
+ TEST_COMPARE (vals->val_tbss3, base_val + 5);
+}
+
+static void
+check_one_thread (const struct one_thread_data *data, int base_val)
+{
+ check_vals_before (&data->exe_before);
+ check_vals_before (&data->mod1_before);
+ check_vals_before (&data->mod2_before);
+ check_vals_after (&data->exe_after, base_val);
+ check_vals_after (&data->mod1_after, base_val);
+ check_vals_after (&data->mod2_after, base_val);
+ check_addrs_align (&data->exe_self);
+ check_addrs_same (&data->exe_self, &data->exe_from_mod1);
+ check_addrs_same (&data->exe_self, &data->exe_from_mod2);
+ check_addrs_align (&data->mod1_self);
+ check_addrs_same (&data->mod1_self, &data->mod1_from_exe);
+ check_addrs_align (&data->mod2_self);
+ check_addrs_same (&data->mod2_self, &data->mod2_from_exe);
+ check_addrs_same (&data->mod2_self, &data->mod2_from_mod1);
+}
+
+static void *
+thread_func (void *arg)
+{
+ int base_val = (int) (intptr_t) arg + 10;
+ struct one_thread_data data;
+ /* Record the addresses of variables as seen from the main
+ executable (which should be the same as seen from the other
+ modules), and their initial values. */
+ STORE_ADDRS (&data.exe_self, exe);
+ STORE_ADDRS (&data.mod1_from_exe, mod1);
+ STORE_ADDRS (&data.mod2_from_exe, mod2);
+ STORE_VALUES (&data.exe_before, exe);
+ STORE_VALUES (&data.mod1_before, mod1);
+ STORE_VALUES (&data.mod2_before, mod2);
+ /* Overwrite the value of variables. */
+ OVERWRITE_VALUES (exe, base_val);
+ OVERWRITE_VALUES (mod1, base_val);
+ OVERWRITE_VALUES (mod2, base_val);
+ /* Record the addresses of variables as seen from other modules. */
+ test_mod1 (&data, base_val);
+ test_mod2 (&data, base_val);
+ /* Record the overwritten values (thus making sure that no other
+ thread running in parallel has changed this thread's values). */
+ STORE_VALUES (&data.exe_after, exe);
+ STORE_VALUES (&data.mod1_after, mod1);
+ STORE_VALUES (&data.mod2_after, mod2);
+ /* Check all the addresses and values recorded. */
+ check_one_thread (&data, base_val);
+ return NULL;
+}
+
+#define NUM_ITERS 50
+#define NUM_THREADS 16
+
+/* For NUM_ITERS iterations, repeatedly create NUM_THREADS threads.
+ In each thread, we determine the addresses of TLS objects (both
+ from the module defining those objects and from other modules), and
+ their initial values, and store in values that are then read back;
+ we check that each object's address is the same regardless of the
+ module in which it is determined, that alignment of objects is as
+ required, and that the values of objects are as expected. */
+
+static int
+do_test (void)
+{
+ for (size_t i = 0; i < NUM_ITERS; i++)
+ {
+ pthread_t threads[NUM_THREADS];
+ for (size_t j = 0; j < NUM_THREADS; j++)
+ threads[j] = xpthread_create (NULL, thread_func, (void *) j);
+ /* Also run checks in the main thread, but only once because
+ those values don't get reinitialized. */
+ if (i == 0)
+ thread_func ((void *) NUM_THREADS);
+ for (size_t j = 0; j < NUM_THREADS; j++)
+ xpthread_join (threads[j]);
+ }
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-tls22.h b/elf/tst-tls22.h
new file mode 100644
index 0000000000000000..24b2e0a0b6af4d45
--- /dev/null
+++ b/elf/tst-tls22.h
@@ -0,0 +1,115 @@
+/* Test TLS with varied alignment and multiple modules and threads: header.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef TST_TLS22_H
+#define TST_TLS22_H
+
+#include <stdint.h>
+
+extern __thread int exe_tdata1 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int exe_tdata2 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int exe_tdata3 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int exe_tbss1 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int exe_tbss2 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int exe_tbss3 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod1_tdata1 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod1_tdata2 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod1_tdata3 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod1_tbss1 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod1_tbss2 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod1_tbss3 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod2_tdata1 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod2_tdata2 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod2_tdata3 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod2_tbss1 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod2_tbss2 __attribute__ ((tls_model ("initial-exec")));
+extern __thread int mod2_tbss3 __attribute__ ((tls_model ("initial-exec")));
+
+/* Structure to store the addresses of one set of TLS objects in one
+ thread, as seen by one module in the program. */
+struct obj_addrs
+{
+ uintptr_t addr_tdata1, addr_tdata2, addr_tdata3;
+ uintptr_t addr_tbss1, addr_tbss2, addr_tbss3;
+};
+
+/* Structure to store the values of one set of TLS objects in one
+ thread. */
+struct obj_values
+{
+ uintptr_t val_tdata1, val_tdata2, val_tdata3;
+ uintptr_t val_tbss1, val_tbss2, val_tbss3;
+};
+
+/* Structure to store all the data about TLS objects in one
+ thread. */
+struct one_thread_data
+{
+ struct obj_addrs exe_self, exe_from_mod1, exe_from_mod2;
+ struct obj_addrs mod1_self, mod1_from_exe;
+ struct obj_addrs mod2_self, mod2_from_exe, mod2_from_mod1;
+ struct obj_values exe_before, mod1_before, mod2_before;
+ struct obj_values exe_after, mod1_after, mod2_after;
+};
+
+/* Store the addresses of variables prefixed by PFX in the structure
+ pointed to by DST. */
+#define STORE_ADDRS(DST, PFX) \
+ do \
+ { \
+ (DST)->addr_tdata1 = (uintptr_t) &PFX ## _tdata1; \
+ (DST)->addr_tdata2 = (uintptr_t) &PFX ## _tdata2; \
+ (DST)->addr_tdata3 = (uintptr_t) &PFX ## _tdata3; \
+ (DST)->addr_tbss1 = (uintptr_t) &PFX ## _tbss1; \
+ (DST)->addr_tbss2 = (uintptr_t) &PFX ## _tbss2; \
+ (DST)->addr_tbss3 = (uintptr_t) &PFX ## _tbss3; \
+ } \
+ while (0)
+
+/* Store the values of variables prefixed by PFX in the structure
+ pointed to by DST. */
+#define STORE_VALUES(DST, PFX) \
+ do \
+ { \
+ (DST)->val_tdata1 = PFX ## _tdata1; \
+ (DST)->val_tdata2 = PFX ## _tdata2; \
+ (DST)->val_tdata3 = PFX ## _tdata3; \
+ (DST)->val_tbss1 = PFX ## _tbss1; \
+ (DST)->val_tbss2 = PFX ## _tbss2; \
+ (DST)->val_tbss3 = PFX ## _tbss3; \
+ } \
+ while (0)
+
+/* Overwrite the values of variables prefixed by PFX with values
+ starting with VAL. */
+#define OVERWRITE_VALUES(PFX, VAL) \
+ do \
+ { \
+ PFX ## _tdata1 = (VAL); \
+ PFX ## _tdata2 = (VAL) + 1; \
+ PFX ## _tdata3 = (VAL) + 2; \
+ PFX ## _tbss1 = (VAL) + 3; \
+ PFX ## _tbss2 = (VAL) + 4; \
+ PFX ## _tbss3 = (VAL) + 5; \
+ } \
+ while (0)
+
+void test_mod1 (struct one_thread_data *data, int base_val);
+void test_mod2 (struct one_thread_data *data, int base_val);
+
+#endif /* TST_TLS22_H */

View File

@ -157,7 +157,7 @@ end \
Summary: The GNU libc libraries
Name: glibc
Version: %{glibcversion}
Release: 151%{?dist}
Release: 152%{?dist}
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
# libraries.
@ -1067,6 +1067,8 @@ Patch759: glibc-RHEL-65358-2.patch
Patch760: glibc-RHEL-65358-3.patch
Patch761: glibc-RHEL-65358-4.patch
Patch762: glibc-RHEL-65358-5.patch
Patch763: glibc-RHEL-58989-1.patch
Patch764: glibc-RHEL-58989-2.patch
##############################################################################
# Continued list of core "glibc" package information:
@ -3060,6 +3062,9 @@ update_gconv_modules_cache ()
%endif
%changelog
* Fri Jan 10 2025 Frédéric Bérat <fberat@redhat.com> - 2.34-152
- Additional TLS test cases (RHEL-58989)
* Fri Jan 10 2025 Frédéric Bérat <fberat@redhat.com> - 2.34-151
- Lock all stdio streams during exit
- Support concurrent calls to exit (RHEL-65358)