about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2024-03-12 13:21:19 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2024-03-19 14:53:30 -0300
commit64c7e344289ed085517c2227d8e3b06388242c13 (patch)
tree3978be8526aa1137ce5420c32d74b6f5ce656b32 /elf
parent968b0ca9440040a2b31248a572891f0e55c1ab10 (diff)
downloadglibc-64c7e344289ed085517c2227d8e3b06388242c13.tar.gz
glibc-64c7e344289ed085517c2227d8e3b06388242c13.tar.xz
glibc-64c7e344289ed085517c2227d8e3b06388242c13.zip
arm: Update _dl_tlsdesc_dynamic to preserve caller-saved registers (BZ 31372)
ARM _dl_tlsdesc_dynamic slow path has two issues:

  * The ip/r12 is defined by AAPCS as a scratch register, and gcc is
    used to save the stack pointer before on some function calls.  So it
    should also be saved/restored as well.  It fixes the tst-gnu2-tls2.

  * None of the possible VFP registers are saved/restored.  ARM has the
    additional complexity to have different VFP bank sizes (depending of
    VFP support by the chip).

The tst-gnu2-tls2 test is extended to check for VFP registers, although
only for hardfp builds.  Different than setcontext, _dl_tlsdesc_dynamic
does not have  HWCAP_ARM_IWMMXT (I don't have a way to properly test
it and it is almost a decade since newer hardware was released).

With this patch there is no need to mark tst-gnu2-tls2 as XFAIL.

Checked on arm-linux-gnueabihf.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile4
-rw-r--r--elf/tst-gnu2-tls2.h4
-rw-r--r--elf/tst-gnu2-tls2mod0.c3
-rw-r--r--elf/tst-gnu2-tls2mod1.c3
-rw-r--r--elf/tst-gnu2-tls2mod2.c3
5 files changed, 10 insertions, 7 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 520a270f0f..393a27ef2a 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -3059,10 +3059,6 @@ $(objpfx)tst-gnu2-tls2.out: \
   $(objpfx)tst-gnu2-tls2mod2.so
 
 ifeq (yes,$(have-mtls-dialect-gnu2))
-# This test fails if dl_tlsdesc_dynamic doesn't preserve all caller-saved
-# registers.  See https://sourceware.org/bugzilla/show_bug.cgi?id=31372
-test-xfail-tst-gnu2-tls2 = yes
-
 CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=gnu2
 CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
 CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
diff --git a/elf/tst-gnu2-tls2.h b/elf/tst-gnu2-tls2.h
index 77964a57a3..1ade8151e2 100644
--- a/elf/tst-gnu2-tls2.h
+++ b/elf/tst-gnu2-tls2.h
@@ -27,6 +27,10 @@ extern struct tls *apply_tls (struct tls *);
 
 /* An architecture can define them to verify that clobber caller-saved
    registers aren't changed by the implicit TLSDESC call.  */
+#ifndef INIT_TLSDESC_CALL
+# define INIT_TLSDESC_CALL()
+#endif
+
 #ifndef BEFORE_TLSDESC_CALL
 # define BEFORE_TLSDESC_CALL()
 #endif
diff --git a/elf/tst-gnu2-tls2mod0.c b/elf/tst-gnu2-tls2mod0.c
index 45556a0e17..3fe3c14277 100644
--- a/elf/tst-gnu2-tls2mod0.c
+++ b/elf/tst-gnu2-tls2mod0.c
@@ -16,13 +16,14 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include "tst-gnu2-tls2.h"
+#include <tst-gnu2-tls2.h>
 
 __thread struct tls tls_var0 __attribute__ ((visibility ("hidden")));
 
 struct tls *
 apply_tls (struct tls *p)
 {
+  INIT_TLSDESC_CALL ();
   BEFORE_TLSDESC_CALL ();
   tls_var0 = *p;
   struct tls *ret = &tls_var0;
diff --git a/elf/tst-gnu2-tls2mod1.c b/elf/tst-gnu2-tls2mod1.c
index e10b9dbc0a..e210538468 100644
--- a/elf/tst-gnu2-tls2mod1.c
+++ b/elf/tst-gnu2-tls2mod1.c
@@ -16,13 +16,14 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include "tst-gnu2-tls2.h"
+#include <tst-gnu2-tls2.h>
 
 __thread struct tls tls_var1[100] __attribute__ ((visibility ("hidden")));
 
 struct tls *
 apply_tls (struct tls *p)
 {
+  INIT_TLSDESC_CALL ();
   BEFORE_TLSDESC_CALL ();
   tls_var1[1] = *p;
   struct tls *ret = &tls_var1[1];
diff --git a/elf/tst-gnu2-tls2mod2.c b/elf/tst-gnu2-tls2mod2.c
index 141af51e55..6d3031dc5f 100644
--- a/elf/tst-gnu2-tls2mod2.c
+++ b/elf/tst-gnu2-tls2mod2.c
@@ -16,13 +16,14 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include "tst-gnu2-tls2.h"
+#include <tst-gnu2-tls2.h>
 
 __thread struct tls tls_var2 __attribute__ ((visibility ("hidden")));
 
 struct tls *
 apply_tls (struct tls *p)
 {
+  INIT_TLSDESC_CALL ();
   BEFORE_TLSDESC_CALL ();
   tls_var2 = *p;
   struct tls *ret = &tls_var2;