summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-07-05 04:46:45 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-07-05 06:18:48 -0700
commited9e8b00cd277979c6368467f93947e45eb8fc30 (patch)
treebdef0eafcf4bb5f12ddfac148da54f7e56e1c2f8
parent639d0d5203cc112dc775d030ad794217a8d34025 (diff)
downloadglibc-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/Makefile4
-rw-r--r--sysdeps/x86_64/configure83
-rw-r--r--sysdeps/x86_64/configure.ac47
-rw-r--r--sysdeps/x86_64/tls_get_addr.h23
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