[BZ,#20309] X86-64: Properly align stack in _dl_tlsdesc_dynamic
Commit Message
Since _dl_tlsdesc_dynamic is called via PLT, we need to add 8 bytes
for for push in the PLT entry to align the stack.
Tested on i686 and x86-64. OK for trunk?
H.J.
---
[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.
---
configure | 33 ++++++++++++++++++++++++++
configure.ac | 20 ++++++++++++++++
elf/Makefile | 7 ++++++
elf/tst-gnu2-tls1.c | 52 +++++++++++++++++++++++++++++++++++++++++
elf/tst-gnu2-tls1mod.c | 56 +++++++++++++++++++++++++++++++++++++++++++++
sysdeps/x86_64/dl-tlsdesc.S | 13 ++++++-----
6 files changed, 175 insertions(+), 6 deletions(-)
create mode 100644 elf/tst-gnu2-tls1.c
create mode 100644 elf/tst-gnu2-tls1mod.c
Comments
On Wed, Jun 29, 2016 at 6:24 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> Since _dl_tlsdesc_dynamic is called via PLT, we need to add 8 bytes
> for for push in the PLT entry to align the stack.
>
> Tested on i686 and x86-64. OK for trunk?
If there is no objection by the end of today, I will check it tomorrow.
> H.J.
> ---
> [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.
> ---
> configure | 33 ++++++++++++++++++++++++++
> configure.ac | 20 ++++++++++++++++
> elf/Makefile | 7 ++++++
> elf/tst-gnu2-tls1.c | 52 +++++++++++++++++++++++++++++++++++++++++
> elf/tst-gnu2-tls1mod.c | 56 +++++++++++++++++++++++++++++++++++++++++++++
> sysdeps/x86_64/dl-tlsdesc.S | 13 ++++++-----
> 6 files changed, 175 insertions(+), 6 deletions(-)
> create mode 100644 elf/tst-gnu2-tls1.c
> create mode 100644 elf/tst-gnu2-tls1mod.c
>
> diff --git a/configure.ac b/configure.ac
> index 123f0d2..33bcd62 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 210dde9..593403c 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 0000000..f55de59
> --- /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 0000000..45c4816
> --- /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 3cb7c3d..777f30b 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
> --
> 2.7.4
>
On 11/07/16 16:55, H.J. Lu wrote:
> On Wed, Jun 29, 2016 at 6:24 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
>> Since _dl_tlsdesc_dynamic is called via PLT, we need to add 8 bytes
>> for for push in the PLT entry to align the stack.
>>
>> Tested on i686 and x86-64. OK for trunk?
>
> If there is no objection by the end of today, I will check it tomorrow.
...
>> +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])
>> +
on aarch64 the flag is -mtls-dialect=desc
(it's the default dialect though)
>> --- 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
so this new test won't run on aarch64.
i don't object to the patch, but i think
testing with different tls-dialects may
eventually need a better approach.
On Mon, Jul 11, 2016 at 9:53 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
> On 11/07/16 16:55, H.J. Lu wrote:
>> On Wed, Jun 29, 2016 at 6:24 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
>>> Since _dl_tlsdesc_dynamic is called via PLT, we need to add 8 bytes
>>> for for push in the PLT entry to align the stack.
>>>
>>> Tested on i686 and x86-64. OK for trunk?
>>
>> If there is no objection by the end of today, I will check it tomorrow.
> ...
>>> +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])
>>> +
>
> on aarch64 the flag is -mtls-dialect=desc
> (it's the default dialect though)
>
>>> --- 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
>
> so this new test won't run on aarch64.
>
> i don't object to the patch, but i think
> testing with different tls-dialects may
> eventually need a better approach.
>
I can move -mtls-dialect=gnu2 test to sysdep/x86 if it is x86 specific.
Or we can leave it as is and adapt it to different targets later.
On 11/07/16 18:32, H.J. Lu wrote:
> I can move -mtls-dialect=gnu2 test to sysdep/x86 if it is x86 specific.
> Or we can leave it as is and adapt it to different targets later.
>
arm also has -mtls-dialect=gnu2 so i think it's fine for now.
@@ -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
@@ -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
new file mode 100644
@@ -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"
new file mode 100644
@@ -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;
+}
@@ -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