diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-07-05 04:46:45 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-07-05 06:18:48 -0700 |
commit | ed9e8b00cd277979c6368467f93947e45eb8fc30 (patch) | |
tree | bdef0eafcf4bb5f12ddfac148da54f7e56e1c2f8 | |
parent | 639d0d5203cc112dc775d030ad794217a8d34025 (diff) | |
download | glibc-hjl/pr21609/master.tar.gz |
x86-64: Redirect __tls_get_addr to ___tls_get_addrhjl/pr21609/master
On x86-64, __tls_get_addr realigns stack to support GCC older than GCC
4.9.4:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
___tls_get_addr is the alternative x86-64 runtime interface to TLS with
aligned stack. If linker treats ___tls_get_addr just like __tls_get_addr
and the weakref assembly directive is extended to redirect __tls_get_addr
to ___tls_get_addr, we can replace reference to __tls_get_addr with
___tls_get_addr if GCC aligns stack for __tls_get_addr, but doesn't
support ___tls_get_addr.
* sysdeps/x86_64/Makefile (+cflags): New. Add
-include $(..)sysdeps/x86_64/tls_get_addr.h if __tls_get_addr
can be redireted to ___tls_get_addr.
* sysdeps/x86_64/configure.ac: Check if GCC supports
___tls_get_addr. If not, check if __tls_get_addr to
___tls_get_addr redirection works.
* sysdeps/x86_64/configure: Regenerated.
* sysdeps/x86_64/tls_get_addr.h: New file.
-rw-r--r-- | sysdeps/x86_64/Makefile | 4 | ||||
-rw-r--r-- | sysdeps/x86_64/configure | 83 | ||||
-rw-r--r-- | sysdeps/x86_64/configure.ac | 47 | ||||
-rw-r--r-- | sysdeps/x86_64/tls_get_addr.h | 23 |
4 files changed, 157 insertions, 0 deletions
diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile index 132470d9cb..93424e97ec 100644 --- a/sysdeps/x86_64/Makefile +++ b/sysdeps/x86_64/Makefile @@ -122,3 +122,7 @@ endif ifeq ($(subdir),csu) gen-as-const-headers += tlsdesc.sym rtld-offsets.sym endif + +ifeq (yes,$(have-___tls_get_addr)) ++cflags += -include $(..)sysdeps/x86_64/tls_get_addr.h +endif diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure index efef46b1b7..8b23f40a8b 100644 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -81,6 +81,89 @@ if test $libc_cv_asm_mpx = yes; then fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ___tls_get_addr" >&5 +$as_echo_n "checking for ___tls_get_addr... " >&6; } +if ${libc_cv_cc____tls_get_addr+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<\EOF +__thread int x; +int +_start (void) +{ + return x; +} +EOF +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -O2 $no_ssp -fPIC -c conftest.c' + { { 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; }; } \ + && { ac_try='$NM -u conftest.o | grep -q "U ___tls_get_addr"' + { { 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_cc____tls_get_addr=yes +else + libc_cv_cc____tls_get_addr=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc____tls_get_addr" >&5 +$as_echo "$libc_cv_cc____tls_get_addr" >&6; } + +if test $libc_cv_cc____tls_get_addr = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __tls_get_addr -> ___tls_get_addr redirection" >&5 +$as_echo_n "checking for __tls_get_addr -> ___tls_get_addr redirection... " >&6; } +if ${libc_cv____tls_get_addr+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<\EOF +__thread int x; +asm (".weakref __tls_get_addr, ___tls_get_addr"); + +int +_start (void) +{ + return x; +} +EOF +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -O2 $no_ssp -fPIC -c conftest.c' + { { 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; }; } \ + && { ac_try='$NM -u conftest.o | grep -q "U ___tls_get_addr"' + { { 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; }; } \ + && $OBJDUMP -dw conftest.o | grep -E "sub[lq]? +\\\$0x8,%[re]sp" 1>&5 \ + && { ac_try='${CC-cc} $LDFLAGS -nostdlib -nostartfiles conftest.o -o conftest' + { { 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____tls_get_addr=yes +else + libc_cv____tls_get_addr=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv____tls_get_addr" >&5 +$as_echo "$libc_cv____tls_get_addr" >&6; } +else + libc_cv____tls_get_addr=no +fi +config_vars="$config_vars +have-___tls_get_addr = $libc_cv____tls_get_addr" + if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index fa86e953ee..a4435b1787 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -40,6 +40,53 @@ if test $libc_cv_asm_mpx = yes; then AC_DEFINE(HAVE_MPX_SUPPORT) fi +dnl Check for ___tls_get_addr. +AC_CACHE_CHECK(for ___tls_get_addr, + libc_cv_cc____tls_get_addr, [dnl +cat > conftest.c <<\EOF +__thread int x; +int +_start (void) +{ + return x; +} +EOF +if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -O2 $no_ssp -fPIC -c conftest.c) \ + && AC_TRY_COMMAND($NM -u conftest.o | grep -q "U ___tls_get_addr"); then + libc_cv_cc____tls_get_addr=yes +else + libc_cv_cc____tls_get_addr=no +fi +rm -f conftest*]) + +if test $libc_cv_cc____tls_get_addr = no; then + dnl Check if __tls_get_addr -> ___tls_get_addr redirection works. + AC_CACHE_CHECK(for __tls_get_addr -> ___tls_get_addr redirection, + libc_cv____tls_get_addr, [dnl +cat > conftest.c <<\EOF +__thread int x; +asm (".weakref __tls_get_addr, ___tls_get_addr"); + +int +_start (void) +{ + return x; +} +EOF +if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -O2 $no_ssp -fPIC -c conftest.c) \ + && AC_TRY_COMMAND($NM -u conftest.o | grep -q "U ___tls_get_addr") \ + && $OBJDUMP -dw conftest.o | grep -E "sub[[lq]]? +\\\$0x8,%[[re]]sp" 1>&AS_MESSAGE_LOG_FD \ + && AC_TRY_COMMAND(${CC-cc} $LDFLAGS -nostdlib -nostartfiles conftest.o -o conftest); then + libc_cv____tls_get_addr=yes +else + libc_cv____tls_get_addr=no +fi +rm -f conftest*]) +else + libc_cv____tls_get_addr=no +fi +LIBC_CONFIG_VAR([have-___tls_get_addr], [$libc_cv____tls_get_addr]) + if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi diff --git a/sysdeps/x86_64/tls_get_addr.h b/sysdeps/x86_64/tls_get_addr.h new file mode 100644 index 0000000000..68bbcb55f1 --- /dev/null +++ b/sysdeps/x86_64/tls_get_addr.h @@ -0,0 +1,23 @@ +/* __tls_get_addr -> ___tls_get_addr redirection. + Copyright (C) 2017 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/>. */ + +#ifndef __ASSEMBLER__ + +__asm__ (".weakref __tls_get_addr, ___tls_get_addr"); + +#endif |