x86-64: Properly align stack in _dl_tlsdesc_dynamic [BZ #20309]

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.
This commit is contained in:
H.J. Lu 2016-07-12 06:29:54 -07:00
parent cf1ad5b3ad
commit 61655555aa
7 changed files with 192 additions and 6 deletions

View File

@ -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]

33
configure vendored
View File

@ -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 :

View 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

View 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

52
elf/tst-gnu2-tls1.c Normal file
View File

@ -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"

56
elf/tst-gnu2-tls1mod.c Normal file
View File

@ -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;
}

View 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