diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-06-29 04:01:58 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-06-29 07:38:22 -0700 |
commit | 14dbd01a991fc8cc6d7bc2762bfc8d2ad1da2cdf (patch) | |
tree | 2e5fcc77d9407bdf52ecbc1dfbdaa687547efa4b | |
parent | e402823ef3852704296cd775c58e4bc633c07f20 (diff) | |
download | glibc-hjl/pr20309/master.tar.gz |
X86-64: Properly align stack in _dl_tlsdesc_dynamichjl/pr20309/master
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.
-rwxr-xr-x | configure | 33 | ||||
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | elf/Makefile | 7 | ||||
-rw-r--r-- | elf/tst-gnu2-tls1.c | 52 | ||||
-rw-r--r-- | elf/tst-gnu2-tls1mod.c | 56 | ||||
-rw-r--r-- | sysdeps/x86_64/dl-tlsdesc.S | 13 |
6 files changed, 175 insertions, 6 deletions
@@ -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 : diff --git a/configure.ac b/configure.ac index 123f0d26ee..33bcd62180 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/elf/Makefile b/elf/Makefile index 210dde941c..593403c640 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -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 index 0000000000..f55de59fc7 --- /dev/null +++ b/elf/tst-gnu2-tls1.c @@ -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 index 0000000000..45c48164b2 --- /dev/null +++ b/elf/tst-gnu2-tls1mod.c @@ -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; +} diff --git a/sysdeps/x86_64/dl-tlsdesc.S b/sysdeps/x86_64/dl-tlsdesc.S index 3cb7c3d031..777f30beab 100644 --- a/sysdeps/x86_64/dl-tlsdesc.S +++ b/sysdeps/x86_64/dl-tlsdesc.S @@ -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 |