x86-64: Properly align stack in _dl_tlsdesc_dynamic [BZ #20309]
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 12 Jul 2016 13:29:54 +0000 (06:29 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 12 Jul 2016 13:30:08 +0000 (06:30 -0700)
Since _dl_tlsdesc_dynamic is called via PLT, we need to add 8 bytes for
push in the PLT entry to align the stack.

[BZ #20309]
* configure.ac (have-mtls-dialect-gnu2): Set to yes if
-mtls-dialect=gnu2 works.
* configure: Regenerated.
* elf/Makefile [have-mtls-dialect-gnu2 = yes]
(tests): Add tst-gnu2-tls1.
(modules-names): Add tst-gnu2-tls1mod.
($(objpfx)tst-gnu2-tls1): New.
(tst-gnu2-tls1mod.so-no-z-defs): Likewise.
(CFLAGS-tst-gnu2-tls1mod.c): Likewise.
* elf/tst-gnu2-tls1.c: New file.
* elf/tst-gnu2-tls1mod.c: Likewise.
* sysdeps/x86_64/dl-tlsdesc.S (_dl_tlsdesc_dynamic): Add 8
bytes for push in the PLT entry to align the stack.

ChangeLog
configure
configure.ac
elf/Makefile
elf/tst-gnu2-tls1.c [new file with mode: 0644]
elf/tst-gnu2-tls1mod.c [new file with mode: 0644]
sysdeps/x86_64/dl-tlsdesc.S

index 8ef71cc..af245d9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2016-07-12  H.J. Lu  <hongjiu.lu@intel.com>
+
+       [BZ #20309]
+       * configure.ac (have-mtls-dialect-gnu2): Set to yes if
+       -mtls-dialect=gnu2 works.
+       * configure: Regenerated.
+       * elf/Makefile [have-mtls-dialect-gnu2 = yes]
+       (tests): Add tst-gnu2-tls1.
+       (modules-names): Add tst-gnu2-tls1mod.
+       ($(objpfx)tst-gnu2-tls1): New.
+       (tst-gnu2-tls1mod.so-no-z-defs): Likewise.
+       (CFLAGS-tst-gnu2-tls1mod.c): Likewise.
+       * elf/tst-gnu2-tls1.c: New file.
+       * elf/tst-gnu2-tls1mod.c: Likewise.
+       * sysdeps/x86_64/dl-tlsdesc.S (_dl_tlsdesc_dynamic): Add 8
+       bytes for push in the PLT entry to align the stack.
+
 2016-07-11  H.J. Lu  <hongjiu.lu@intel.com>
 
        [BZ #20349]
index 19a4829..17625e1 100755 (executable)
--- a/configure
+++ b/configure
@@ -619,6 +619,7 @@ LIBGD
 libc_cv_cc_loop_to_function
 libc_cv_cc_submachine
 libc_cv_cc_nofma
+libc_cv_mtls_dialect_gnu2
 stack_protector
 fno_unit_at_a_time
 libc_cv_output_format
@@ -5824,6 +5825,38 @@ elif test "$libc_cv_ssp" = "yes"; then
 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_n "(cached) " >&6
+else
+  cat > conftest.c <<EOF
+__thread int i;
+void foo (void)
+{
+  i = 10;
+}
+EOF
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S -fPIC -mtls-dialect=gnu2
+                  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_gnu2=yes
+else
+  libc_cv_mtls_dialect_gnu2=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; }
+
+config_vars="$config_vars
+have-mtls-dialect-gnu2 = $libc_cv_mtls_dialect_gnu2"
+
 { $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 :
index 123f0d2..33bcd62 100644 (file)
@@ -1412,6 +1412,26 @@ elif test "$libc_cv_ssp" = "yes"; then
 fi
 AC_SUBST(stack_protector)
 
+AC_CACHE_CHECK([for -mtls-dialect=gnu2], libc_cv_mtls_dialect_gnu2,
+[dnl
+cat > conftest.c <<EOF
+__thread int i;
+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])
+then
+  libc_cv_mtls_dialect_gnu2=yes
+else
+  libc_cv_mtls_dialect_gnu2=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_CACHE_CHECK(whether cc puts quotes around section names,
               libc_cv_have_section_quotes,
               [cat > conftest.c <<EOF
index 210dde9..593403c 100644 (file)
@@ -224,6 +224,13 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
                tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
                tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \
                tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12
+ifeq (yes,$(have-mtls-dialect-gnu2))
+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
 ifeq (yes,$(have-protected-data))
 modules-names += tst-protected1moda tst-protected1modb
 tests += tst-protected1a tst-protected1b
diff --git a/elf/tst-gnu2-tls1.c b/elf/tst-gnu2-tls1.c
new file mode 100644 (file)
index 0000000..f55de59
--- /dev/null
@@ -0,0 +1,52 @@
+/* Test local and global dynamic models for GNU2 TLS.
+   Copyright (C) 2016 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int * get_gd (void);
+extern void set_gd (int);
+extern int test_gd (int);
+extern int * get_ld (void);
+extern void set_ld (int);
+extern int test_ld (int);
+
+__thread int gd = 1;
+
+static int
+do_test (void)
+{
+  int *p;
+
+  p = get_gd ();
+  set_gd (3);
+  if (*p != 3 || !test_gd (3))
+    abort ();
+
+  p = get_ld ();
+  set_ld (4);
+  if (*p != 4 || !test_ld (4))
+    abort ();
+
+  printf ("PASS\n");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-gnu2-tls1mod.c b/elf/tst-gnu2-tls1mod.c
new file mode 100644 (file)
index 0000000..45c4816
--- /dev/null
@@ -0,0 +1,56 @@
+/* DSO used by tst-gnu2-tls1.
+   Copyright (C) 2016 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
+   <http://www.gnu.org/licenses/>.  */
+
+static __thread int ld;
+
+int *
+get_ld (void)
+{
+  return &ld;
+}
+
+void
+set_ld (int i)
+{
+  ld = i;
+}
+
+int
+test_ld (int i)
+{
+  return ld == i;
+}
+extern __thread int gd;
+
+int *
+get_gd (void)
+{
+  return &gd;
+}
+
+void
+set_gd (int i)
+{
+  gd = i;
+}
+
+int
+test_gd (int i)
+{
+  return gd == i;
+}
index 3cb7c3d..777f30b 100644 (file)
@@ -163,14 +163,15 @@ _dl_tlsdesc_dynamic:
        /* The PLT entry will have pushed the link_map pointer.  */
 _dl_tlsdesc_resolve_rela:
        cfi_adjust_cfa_offset (8)
-       /* Save all call-clobbered registers.  */
-       subq    $72, %rsp
-       cfi_adjust_cfa_offset (72)
+       /* Save all call-clobbered registers.  Add 8 bytes for push in
+          the PLT entry to align the stack.  */
+       subq    $80, %rsp
+       cfi_adjust_cfa_offset (80)
        movq    %rax, (%rsp)
        movq    %rdi, 8(%rsp)
        movq    %rax, %rdi      /* Pass tlsdesc* in %rdi.  */
        movq    %rsi, 16(%rsp)
-       movq    72(%rsp), %rsi  /* Pass link_map* in %rsi.  */
+       movq    80(%rsp), %rsi  /* Pass link_map* in %rsi.  */
        movq    %r8, 24(%rsp)
        movq    %r9, 32(%rsp)
        movq    %r10, 40(%rsp)
@@ -187,8 +188,8 @@ _dl_tlsdesc_resolve_rela:
        movq    48(%rsp), %r11
        movq    56(%rsp), %rdx
        movq    64(%rsp), %rcx
-       addq    $80, %rsp
-       cfi_adjust_cfa_offset (-80)
+       addq    $88, %rsp
+       cfi_adjust_cfa_offset (-88)
        jmp     *(%rax)
        cfi_endproc
        .size   _dl_tlsdesc_resolve_rela, .-_dl_tlsdesc_resolve_rela