GNU2 TLS descriptors were introduced in 2006 (r0-73091-g5bf5a10b1ccacf)
but were only opt-in with -mtls-dialect=gnu2. They are more efficient
and it's time to enable them by default.
Builds on the --with-tls= machinery from r16-3355-g96a291c4bb0b8a.
We achieve this for GNU/Linux IA-32/X86-64 targets by checking if ld emits
GLIBC_ABI_GNU2_TLS, using its presence to decide if we can default to
-mtls-dialect=gnu2.
For PR ld/33130, newer ld will add GLIBC_ABI_GNU2_TLS if either unconfigured
(auto mode) or if configured with --enable-gnu2-tls-tag. In auto mode,
GLIBC_ABI_GNU2_TLS is only added if glibc provides it. In explicit mode, the
user has asked for this behavior and binaries will depend on GLIBC_ABI_GNU2_TLS
and fixed glibc. Hence the presence of GLIBC_ABI_GNU2_TLS tells us if we can
safely default to GNU2 TLS descriptors. We added GLIBC_ABI_GNU2_TLS in glibc
to indicate that PR dynamic-link/33129 is fixed.
If distributions wish to opt-out of this for systems which meet the above
conditions, they can either configure GCC using --with-tls=gnu, or configure
binutils with --disable-gnu2-tls-tag: if this is necessary, it is recommended
to use --with-tls=gnu instead, to avoid affecting the ecosystem negatively by
having unmarked binaries.
Some implementation notes:
* The readelf check had to be moved earlier because we want
to set `with_tls` before `config.gcc` is processed (which has default
machinery for TLS).
* The check doesn't really handle cross, but I don't see
this as a huge problem. The check is already opportunistic and if it
fails, it falls back to --with-tls=DIALECT if passed, and failing that,
the previous and safe default of 'gnu'.
* The change is only made for glibc systems at this time. Enablement and testing
can be done for other libcs as future work.
* In future, we may do the same thing for ARM if/when appropriate equivalent
machinery is added to glibc and bfd. This makes the separate position of
the check (not with some of the others) a bit more palatable IMO.
gcc/ChangeLog:
PR target/120933
* configure: Regenerate.
* configure.ac (gcc_cv_readelf): Move check earlier.
(gcc_cv_libc_x86_tlsdesc_call): Define to 'yes' if
glibc has the GLIBC_ABI_GNU2_TLS version tag and ld emits it.
(with_tls): Default to 'gnu2' if --with-tls is not passed and
gcc_cv_libc_x86_tlsdesc_call is 'yes'.
---
OK?
gcc/configure | 217 +++++++++++++++++++++++++++++++----------------
gcc/configure.ac | 112 ++++++++++++++++++------
2 files changed, 229 insertions(+), 100 deletions(-)
diff --git a/gcc/configure b/gcc/configure
index 4a751d969bab..ba303469613c 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -737,7 +737,6 @@ libgcc_visibility
ORIGINAL_DSYMUTIL_FOR_TARGET
gcc_cv_dsymutil
gcc_cv_otool
-gcc_cv_readelf
gcc_cv_objdump
ORIGINAL_NM_FOR_TARGET
gcc_cv_nm
@@ -801,6 +800,7 @@ HAVE_AUTO_BUILD
extra_opt_files
extra_modes_file
NATIVE_SYSTEM_HEADER_DIR
+gcc_cv_readelf
objext
manext
LIBICONV_DEP
@@ -12927,6 +12927,145 @@ if test "x$enable_win32_utf8_manifest" != xno; then
host_extra_objs_mingw=utf8-mingw32.o
fi
+
+# Figure out what readelf we will be using.
+if ${gcc_cv_readelf+:} false; then :
+
+else
+
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ # Single tree build which includes binutils.
+ gcc_cv_readelf=../binutils/readelf$build_exeext
+elif test -x readelf$build_exeext; then
+ gcc_cv_readelf=./readelf$build_exeext
+elif ( set dummy $READELF_FOR_TARGET; test -x $2 ); then
+ gcc_cv_readelf="$READELF_FOR_TARGET"
+else
+ # Extract the first word of "$READELF_FOR_TARGET", so it can be a
program name with args.
+set dummy $READELF_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_readelf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_readelf in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_readelf="$gcc_cv_readelf" # Let the user override the test
with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_readelf="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext"
>&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_readelf=$ac_cv_path_gcc_cv_readelf
+if test -n "$gcc_cv_readelf"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_readelf" >&5
+$as_echo "$gcc_cv_readelf" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what readelf to use" >&5
+$as_echo_n "checking what readelf to use... " >&6; }
+if test "$gcc_cv_readelf" = ../binutils/readelf$build_exeext; then
+ # Single tree build which includes binutils.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: newly built readelf"
>&5
+$as_echo "newly built readelf" >&6; }
+elif test x$gcc_cv_readelf = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_readelf" >&5
+$as_echo "$gcc_cv_readelf" >&6; }
+fi
+
+case $target in
+ i[34567]86-*-gnu* | x86_64-*-gnu* )
+ # PR target/120933
+ # For GNU/Linux targets, check if ld emits GLIBC_ABI_GNU2_TLS. For PR
ld/33130,
+ # newer ld will add GLIBC_ABI_GNU2_TLS if either unconfigured (auto
mode) or if
+ # configured with --enable-gnu2-tls-tag. In auto mode,
GLIBC_ABI_GNU2_TLS
+ # is only added if glibc provides it. In explicit mode, the user has
asked
+ # for this behavior and binaries will depend on GLIBC_ABI_GNU2_TLS and
fixed
+ # glibc. Hence the presence of GLIBC_ABI_GNU2_TLS tells us if we can
safely
+ # default to GNU2 TLS descriptors.
+ conftest_S='
+ .section .text.startup,"ax",@progbits
+ .p2align 4
+ .globl main
+ .type main, @function
+ main:
+ #ifdef __x86_64__
+ leaq foo@TLSDESC(%rip), %rax
+ call *foo@TLSCALL(%rax)
+ movl %fs:(%rax), %eax
+ #else
+ leal ld@TLSDESC(%ebx), %eax
+ call *ld@TLSCALL(%eax)
+ addl %gs:0, %eax
+ #endif
+ ret
+ .size main, .-main
+ .section .note.GNU-stack,"",@progbits
+ '
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking libc has
GLIBC_ABI_GNU2_TLS symbol dep and ld emits it" >&5
+$as_echo_n "checking libc has GLIBC_ABI_GNU2_TLS symbol dep and ld emits it...
" >&6; }
+if ${gcc_cv_libc_x86_tlsdesc_call+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ gcc_cv_libc_x86_tlsdesc_call=no
+ echo "$conftest_S" > conftest.S
+ if $CC $CFLAGS conftest.S -o conftest -shared > /dev/null 2>&1;
then
+ if test x$gcc_cv_readelf != x; then
+ if $gcc_cv_readelf --version-info conftest 2>&1
\
+ | grep "GLIBC_ABI_GNU2_TLS" > /dev/null
2>&1; then
+ gcc_cv_libc_x86_tlsdesc_call=yes
+ else
+ gcc_cv_libc_x86_tlsdesc_call=no
+ fi
+ fi
+ fi
+ rm -f conftest.*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result:
$gcc_cv_libc_x86_tlsdesc_call" >&5
+$as_echo "$gcc_cv_libc_x86_tlsdesc_call" >&6; }
+
+ # Set with_tls only if it's not already set via --with-tls=DIALECT
+ case "$gcc_cv_libc_x86_tlsdesc_call" in
+ yes)
+ with_tls=${with_tls:-gnu2}
+ ;;
+ *)
+ with_tls=${with_tls:-gnu}
+ ;;
+ esac
+ ;;
+esac
+
# --------------------------------------------------------
# Build, host, and target specific configuration fragments
# --------------------------------------------------------
@@ -21484,7 +21623,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21487 "configure"
+#line 21626 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -21590,7 +21729,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21593 "configure"
+#line 21732 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -25419,78 +25558,6 @@ else
$as_echo "$gcc_cv_objdump" >&6; }
fi
-# Figure out what readelf we will be using.
-if ${gcc_cv_readelf+:} false; then :
-
-else
-
-if test -f $gcc_cv_binutils_srcdir/configure.ac \
- && test -f ../binutils/Makefile \
- && test x$build = x$host; then
- # Single tree build which includes binutils.
- gcc_cv_readelf=../binutils/readelf$build_exeext
-elif test -x readelf$build_exeext; then
- gcc_cv_readelf=./readelf$build_exeext
-elif ( set dummy $READELF_FOR_TARGET; test -x $2 ); then
- gcc_cv_readelf="$READELF_FOR_TARGET"
-else
- # Extract the first word of "$READELF_FOR_TARGET", so it can be a
program name with args.
-set dummy $READELF_FOR_TARGET; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_gcc_cv_readelf+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $gcc_cv_readelf in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_gcc_cv_readelf="$gcc_cv_readelf" # Let the user override the test
with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_gcc_cv_readelf="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext"
>&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-gcc_cv_readelf=$ac_cv_path_gcc_cv_readelf
-if test -n "$gcc_cv_readelf"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_readelf" >&5
-$as_echo "$gcc_cv_readelf" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what readelf to use" >&5
-$as_echo_n "checking what readelf to use... " >&6; }
-if test "$gcc_cv_readelf" = ../binutils/readelf$build_exeext; then
- # Single tree build which includes binutils.
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: newly built readelf"
>&5
-$as_echo "newly built readelf" >&6; }
-elif test x$gcc_cv_readelf = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_readelf" >&5
-$as_echo "$gcc_cv_readelf" >&6; }
-fi
-
# Figure out what otool we will be using.
if ${gcc_cv_otool+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 4532c5c22fe5..4c268d565d72 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1886,6 +1886,93 @@ if test "x$enable_win32_utf8_manifest" != xno; then
host_extra_objs_mingw=utf8-mingw32.o
fi
+
+# Figure out what readelf we will be using.
+AS_VAR_SET_IF(gcc_cv_readelf,, [
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ # Single tree build which includes binutils.
+ gcc_cv_readelf=../binutils/readelf$build_exeext
+elif test -x readelf$build_exeext; then
+ gcc_cv_readelf=./readelf$build_exeext
+elif ( set dummy $READELF_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_readelf="$READELF_FOR_TARGET"
+else
+ AC_PATH_PROG(gcc_cv_readelf, $READELF_FOR_TARGET)
+fi])
+
+AC_MSG_CHECKING(what readelf to use)
+if test "$gcc_cv_readelf" = ../binutils/readelf$build_exeext; then
+ # Single tree build which includes binutils.
+ AC_MSG_RESULT(newly built readelf)
+elif test x$gcc_cv_readelf = x; then
+ AC_MSG_RESULT(not found)
+else
+ AC_MSG_RESULT($gcc_cv_readelf)
+fi
+
+case $target in
+changequote(,)dnl
+ i[34567]86-*-gnu* | x86_64-*-gnu* )
+changequote([,])dnl
+ # PR target/120933
+ # For GNU/Linux targets, check if ld emits GLIBC_ABI_GNU2_TLS. For PR
ld/33130,
+ # newer ld will add GLIBC_ABI_GNU2_TLS if either unconfigured (auto
mode) or if
+ # configured with --enable-gnu2-tls-tag. In auto mode,
GLIBC_ABI_GNU2_TLS
+ # is only added if glibc provides it. In explicit mode, the user has
asked
+ # for this behavior and binaries will depend on GLIBC_ABI_GNU2_TLS and
fixed
+ # glibc. Hence the presence of GLIBC_ABI_GNU2_TLS tells us if we can
safely
+ # default to GNU2 TLS descriptors.
+ conftest_S='
+ .section .text.startup,"ax",@progbits
+ .p2align 4
+ .globl main
+ .type main, @function
+ main:
+ #ifdef __x86_64__
+ leaq foo@TLSDESC(%rip), %rax
+ call *foo@TLSCALL(%rax)
+ movl %fs:(%rax), %eax
+ #else
+ leal ld@TLSDESC(%ebx), %eax
+ call *ld@TLSCALL(%eax)
+ addl %gs:0, %eax
+ #endif
+ ret
+ .size main, .-main
+ .section .note.GNU-stack,"",@progbits
+ '
+
+ AC_CACHE_CHECK([libc has GLIBC_ABI_GNU2_TLS symbol dep and ld emits it],
+ gcc_cv_libc_x86_tlsdesc_call, [
+ gcc_cv_libc_x86_tlsdesc_call=no
+ echo "$conftest_S" > conftest.S
+ if $CC $CFLAGS conftest.S -o conftest -shared > /dev/null 2>&1;
then
+ if test x$gcc_cv_readelf != x; then
+ if $gcc_cv_readelf --version-info conftest 2>&1
\
+ | grep "GLIBC_ABI_GNU2_TLS" > /dev/null
2>&1; then
+ gcc_cv_libc_x86_tlsdesc_call=yes
+ else
+ gcc_cv_libc_x86_tlsdesc_call=no
+ fi
+ fi
+ fi
+ rm -f conftest.*
+ ])
+
+ # Set with_tls only if it's not already set via --with-tls=DIALECT
+ case "$gcc_cv_libc_x86_tlsdesc_call" in
+ yes)
+ with_tls=${with_tls:-gnu2}
+ ;;
+ *)
+ with_tls=${with_tls:-gnu}
+ ;;
+ esac
+ ;;
+esac
+
# --------------------------------------------------------
# Build, host, and target specific configuration fragments
# --------------------------------------------------------
@@ -2934,31 +3021,6 @@ else
AC_MSG_RESULT($gcc_cv_objdump)
fi
-# Figure out what readelf we will be using.
-AS_VAR_SET_IF(gcc_cv_readelf,, [
-if test -f $gcc_cv_binutils_srcdir/configure.ac \
- && test -f ../binutils/Makefile \
- && test x$build = x$host; then
- # Single tree build which includes binutils.
- gcc_cv_readelf=../binutils/readelf$build_exeext
-elif test -x readelf$build_exeext; then
- gcc_cv_readelf=./readelf$build_exeext
-elif ( set dummy $READELF_FOR_TARGET; test -x $[2] ); then
- gcc_cv_readelf="$READELF_FOR_TARGET"
-else
- AC_PATH_PROG(gcc_cv_readelf, $READELF_FOR_TARGET)
-fi])
-
-AC_MSG_CHECKING(what readelf to use)
-if test "$gcc_cv_readelf" = ../binutils/readelf$build_exeext; then
- # Single tree build which includes binutils.
- AC_MSG_RESULT(newly built readelf)
-elif test x$gcc_cv_readelf = x; then
- AC_MSG_RESULT(not found)
-else
- AC_MSG_RESULT($gcc_cv_readelf)
-fi
-
# Figure out what otool we will be using.
AS_VAR_SET_IF(gcc_cv_otool,, [
if test -x otool$build_exeext; then
--
2.51.0