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