aarch64: Skip traditional GD/LD TLS which are unsupported by Clang and LLD [BZ #28205]

Message ID 20210806224126.643993-1-maskray@google.com
State Superseded
Delegated to: Szabolcs Nagy
Headers
Series aarch64: Skip traditional GD/LD TLS which are unsupported by Clang and LLD [BZ #28205] |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Fangrui Song Aug. 6, 2021, 10:41 p.m. UTC
  TLSDESC is the default on aarch64.  Clang doesn't support
-mtls-dialect=trad.  Its integrated assembler doesn't support the
marker.  LLD's doesn't support R_AARCH64_TLSGD_*/R_AARCH64_TLSLD_*
relocations.  Just skip the tests.

With https://sourceware.org/pipermail/libc-alpha/2021-August/129904.html
("aarch64: Make elf_machine_{load_address, dynamic} robust [BZ #28203]"),
if we allow LLD in configure.ac,
`make check` test results of LLD are on par with GNU ld.
---
 config.h.in       |  3 +++
 configure         | 38 ++++++++++++++++++++++++++++++++++++++
 configure.ac      | 24 ++++++++++++++++++++++++
 elf/tst-tls1.c    |  7 +++++--
 elf/tst-tls2.c    |  6 ++++--
 elf/tst-tls3.c    |  8 ++++----
 elf/tst-tlsmod1.c |  6 ++++--
 elf/tst-tlsmod2.c |  4 +++-
 elf/tst-tlsmod3.c |  5 ++++-
 elf/tst-tlsmod4.c |  4 +++-
 10 files changed, 92 insertions(+), 13 deletions(-)
  

Comments

Szabolcs Nagy Aug. 10, 2021, 11:20 a.m. UTC | #1
The 08/06/2021 15:41, Fangrui Song via Libc-alpha wrote:
> TLSDESC is the default on aarch64.  Clang doesn't support
> -mtls-dialect=trad.  Its integrated assembler doesn't support the
> marker.  LLD's doesn't support R_AARCH64_TLSGD_*/R_AARCH64_TLSLD_*
> relocations.  Just skip the tests.
> 
> With https://sourceware.org/pipermail/libc-alpha/2021-August/129904.html
> ("aarch64: Make elf_machine_{load_address, dynamic} robust [BZ #28203]"),
> if we allow LLD in configure.ac,
> `make check` test results of LLD are on par with GNU ld.
> ---
>  config.h.in       |  3 +++
>  configure         | 38 ++++++++++++++++++++++++++++++++++++++
>  configure.ac      | 24 ++++++++++++++++++++++++
>  elf/tst-tls1.c    |  7 +++++--
>  elf/tst-tls2.c    |  6 ++++--
>  elf/tst-tls3.c    |  8 ++++----
>  elf/tst-tlsmod1.c |  6 ++++--
>  elf/tst-tlsmod2.c |  4 +++-
>  elf/tst-tlsmod3.c |  5 ++++-
>  elf/tst-tlsmod4.c |  4 +++-
>  10 files changed, 92 insertions(+), 13 deletions(-)
> 
> diff --git a/config.h.in b/config.h.in
> index 8b45a3a61d..f65605d4bd 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -198,6 +198,9 @@
>  /* Define if CC supports attribute retain.  */
>  #undef HAVE_GNU_RETAIN
>  
> +/* Define if CC and LD support -mtls-dialect=trad.  */
> +#undef HAVE_MTLS_DIALECT_TRAD
> +
>  /* Define if the linker defines __ehdr_start.  */
>  #undef HAVE_EHDR_START
>  
> diff --git a/configure.ac b/configure.ac
> index 5632277f9c..c73e271cc8 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1501,6 +1501,30 @@ rm -f conftest*])
>  AC_SUBST(libc_cv_mtls_dialect_gnu2)
>  LIBC_CONFIG_VAR([have-mtls-dialect-gnu2], [$libc_cv_mtls_dialect_gnu2])
>  
> +AC_CACHE_CHECK([for -mtls-dialect=trad], libc_cv_mtls_dialect_trad,
> +[dnl
> +cat > conftest.c <<EOF
> +extern __thread int i;
> +void foo (void)
> +{
> +  i = 10;
> +}
> +EOF
> +if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
> +			-fPIC -mtls-dialect=trad -shared -o conftest.so conftest.c
> +			1>&AS_MESSAGE_LOG_FD])
> +then
> +  libc_cv_mtls_dialect_trad=yes
> +else
> +  libc_cv_mtls_dialect_trad=no
> +fi
> +rm -f conftest*])
> +if test $libc_cv_mtls_dialect_trad = yes; then
> +  AC_DEFINE(HAVE_MTLS_DIALECT_TRAD)
> +fi
> +AC_SUBST(libc_cv_mtls_dialect_trad)
> +LIBC_CONFIG_VAR([have-mtls-dialect-trad], [$libc_cv_mtls_dialect_trad])

this is a possible way, but i think it's nicer to have

#define HAVE_TRAD_TLS 1

in config.h.in, and then in sysdeps/aarch64/configure.ac

AC_DEFINE(HAVE_TRAD_TLS, 0, [Only TLSDESC is supported])

(haven't tested, but i think it would work)

(-mtls-dialect=trad is aarch64 specific flag, so it's
not nice in the generic configure and the tests don't
actually care about this flag but whether the assembler
and linker would work)
  

Patch

diff --git a/config.h.in b/config.h.in
index 8b45a3a61d..f65605d4bd 100644
--- a/config.h.in
+++ b/config.h.in
@@ -198,6 +198,9 @@ 
 /* Define if CC supports attribute retain.  */
 #undef HAVE_GNU_RETAIN
 
+/* Define if CC and LD support -mtls-dialect=trad.  */
+#undef HAVE_MTLS_DIALECT_TRAD
+
 /* Define if the linker defines __ehdr_start.  */
 #undef HAVE_EHDR_START
 
diff --git a/configure b/configure
index 050f1a29cf..13e2a7374d 100755
--- a/configure
+++ b/configure
@@ -622,6 +622,7 @@  LIBGD
 libc_cv_cc_loop_to_function
 libc_cv_cc_submachine
 libc_cv_cc_nofma
+libc_cv_mtls_dialect_trad
 libc_cv_mtls_dialect_gnu2
 fno_unit_at_a_time
 libc_cv_has_glob_dat
@@ -6336,6 +6337,43 @@  $as_echo "$libc_cv_mtls_dialect_gnu2" >&6; }
 config_vars="$config_vars
 have-mtls-dialect-gnu2 = $libc_cv_mtls_dialect_gnu2"
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -mtls-dialect=trad" >&5
+$as_echo_n "checking for -mtls-dialect=trad... " >&6; }
+if ${libc_cv_mtls_dialect_trad+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.c <<EOF
+extern __thread int i;
+void foo (void)
+{
+  i = 10;
+}
+EOF
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
+			-fPIC -mtls-dialect=trad -shared -o conftest.so conftest.c
+			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_trad=yes
+else
+  libc_cv_mtls_dialect_trad=no
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mtls_dialect_trad" >&5
+$as_echo "$libc_cv_mtls_dialect_trad" >&6; }
+if test $libc_cv_mtls_dialect_trad = yes; then
+  $as_echo "#define HAVE_MTLS_DIALECT_TRAD 1" >>confdefs.h
+
+fi
+
+config_vars="$config_vars
+have-mtls-dialect-trad = $libc_cv_mtls_dialect_trad"
+
 { $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; }
 if ${libc_cv_have_section_quotes+:} false; then :
diff --git a/configure.ac b/configure.ac
index 5632277f9c..c73e271cc8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1501,6 +1501,30 @@  rm -f conftest*])
 AC_SUBST(libc_cv_mtls_dialect_gnu2)
 LIBC_CONFIG_VAR([have-mtls-dialect-gnu2], [$libc_cv_mtls_dialect_gnu2])
 
+AC_CACHE_CHECK([for -mtls-dialect=trad], libc_cv_mtls_dialect_trad,
+[dnl
+cat > conftest.c <<EOF
+extern __thread int i;
+void foo (void)
+{
+  i = 10;
+}
+EOF
+if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
+			-fPIC -mtls-dialect=trad -shared -o conftest.so conftest.c
+			1>&AS_MESSAGE_LOG_FD])
+then
+  libc_cv_mtls_dialect_trad=yes
+else
+  libc_cv_mtls_dialect_trad=no
+fi
+rm -f conftest*])
+if test $libc_cv_mtls_dialect_trad = yes; then
+  AC_DEFINE(HAVE_MTLS_DIALECT_TRAD)
+fi
+AC_SUBST(libc_cv_mtls_dialect_trad)
+LIBC_CONFIG_VAR([have-mtls-dialect-trad], [$libc_cv_mtls_dialect_trad])
+
 AC_CACHE_CHECK(whether cc puts quotes around section names,
 	       libc_cv_have_section_quotes,
 	       [cat > conftest.c <<EOF
diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c
index c31da56ce9..bfd6f81a29 100644
--- a/elf/tst-tls1.c
+++ b/elf/tst-tls1.c
@@ -39,7 +39,8 @@  do_test (void)
       result = 1;
     }
 
-
+  /* Clang and LLD do not support traditional GD/LD TLS on aarch64. */
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
   /* Get variables using local dynamic model.  */
   fputs ("get sum of foo and bar (LD)", stdout);
   ap = TLS_LD (foo);
@@ -56,8 +57,9 @@  do_test (void)
       printf ("bar = %d\n", *bp);
       result = 1;
     }
+#endif
 
-
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
   /* Get variables using generic dynamic model.  */
   fputs ("get sum of foo and bar (GD)", stdout);
   ap = TLS_GD (foo);
@@ -74,6 +76,7 @@  do_test (void)
       printf ("bar = %d\n", *bp);
       result = 1;
     }
+#endif
 
   return result;
 }
diff --git a/elf/tst-tls2.c b/elf/tst-tls2.c
index 963b8d6c88..0b5615a0ba 100644
--- a/elf/tst-tls2.c
+++ b/elf/tst-tls2.c
@@ -39,7 +39,7 @@  do_test (void)
       result = 1;
     }
 
-
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
   /* Get variables using local dynamic model.  */
   fputs ("get sum of foo and bar (LD)", stdout);
   ap = TLS_LD (foo);
@@ -56,8 +56,9 @@  do_test (void)
       printf ("bar = %d\n", *bp);
       result = 1;
     }
+#endif
 
-
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
   /* Get variables using generic dynamic model.  */
   fputs ("get sum of foo and bar (GD)", stdout);
   ap = TLS_GD (foo);
@@ -74,6 +75,7 @@  do_test (void)
       printf ("bar = %d\n", *bp);
       result = 1;
     }
+#endif
 
   return result;
 }
diff --git a/elf/tst-tls3.c b/elf/tst-tls3.c
index 7e0abb4c58..4dd6377b24 100644
--- a/elf/tst-tls3.c
+++ b/elf/tst-tls3.c
@@ -17,8 +17,7 @@  static int
 do_test (void)
 {
   int result = 0;
-  int *ap, *bp, *cp;
-
+  int *ap, *bp;
 
   /* Set the variable using the local exec model.  */
   puts ("set baz to 3 (LE)");
@@ -33,7 +32,8 @@  do_test (void)
   bp = TLS_IE (bar);
   *bp = 2;
 
-
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
+  int *cp;
   /* Get variables using local dynamic model.  */
   fputs ("get sum of foo, bar (GD) and baz (LD)", stdout);
   ap = TLS_GD (foo);
@@ -56,7 +56,7 @@  do_test (void)
       printf ("baz = %d\n", *cp);
       result = 1;
     }
-
+#endif
 
   result |= in_dso ();
 
diff --git a/elf/tst-tlsmod1.c b/elf/tst-tlsmod1.c
index 8d9156791b..00fb26ace0 100644
--- a/elf/tst-tlsmod1.c
+++ b/elf/tst-tlsmod1.c
@@ -14,7 +14,7 @@  int
 in_dso (void)
 {
   int result = 0;
-  int *ap, *bp, *cp;
+  int *ap, *bp;
 
   /* Get variables using initial exec model.  */
   fputs ("get sum of foo and bar (IE)", stdout);
@@ -34,7 +34,8 @@  in_dso (void)
       result = 1;
     }
 
-
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
+  int *cp;
   /* Get variables using generic dynamic model.  */
   fputs ("get sum of foo and bar and baz (GD)", stdout);
   ap = TLS_GD (foo);
@@ -57,6 +58,7 @@  in_dso (void)
       printf ("baz = %d\n", *cp);
       result = 1;
     }
+#endif
 
   return result;
 }
diff --git a/elf/tst-tlsmod2.c b/elf/tst-tlsmod2.c
index 40eb1407f8..ead3e97b1d 100644
--- a/elf/tst-tlsmod2.c
+++ b/elf/tst-tlsmod2.c
@@ -9,9 +9,10 @@  COMMON_INT_DEF(foo);
 int
 in_dso (int n, int *caller_foop)
 {
-  int *foop;
   int result = 0;
 
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
+  int *foop;
   puts ("foo");			/* Make sure PLT is used before macros.  */
   asm ("" ::: "memory");
 
@@ -29,6 +30,7 @@  in_dso (int n, int *caller_foop)
     }
 
   *foop = 16;
+#endif
 
   return result;
 }
diff --git a/elf/tst-tlsmod3.c b/elf/tst-tlsmod3.c
index 6d186c47ee..4dfdfe19f7 100644
--- a/elf/tst-tlsmod3.c
+++ b/elf/tst-tlsmod3.c
@@ -12,8 +12,10 @@  COMMON_INT_DEF(comm_n);
 int
 in_dso2 (void)
 {
-  int *foop;
   int result = 0;
+
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
+  int *foop;
   static int n;
   int *np;
 
@@ -32,6 +34,7 @@  in_dso2 (void)
   result |= in_dso (*foop = 42 + n++, foop);
 
   *foop = 16;
+#endif
 
   return result;
 }
diff --git a/elf/tst-tlsmod4.c b/elf/tst-tlsmod4.c
index 86889aac7e..ca1afd4390 100644
--- a/elf/tst-tlsmod4.c
+++ b/elf/tst-tlsmod4.c
@@ -9,9 +9,10 @@  COMMON_INT_DEF(baz);
 int
 in_dso (int n, int *caller_bazp)
 {
-  int *bazp;
   int result = 0;
 
+#if !defined (__aarch64__) || defined (HAVE_MTLS_DIALECT_TRAD)
+  int *bazp;
   puts ("foo");			/* Make sure PLT is used before macros.  */
   asm ("" ::: "memory");
 
@@ -29,6 +30,7 @@  in_dso (int n, int *caller_bazp)
     }
 
   *bazp = 16;
+#endif
 
   return result;
 }