Since "6fbec038f7a Use SHF_GNU_RETAIN to preserve symbol definitions", GCC could create sections with the 'R' flag, which GAS would map to SHF_GNU_RETAIN.
SHF_GNU_RETAIN support was not available in gold until Binutils commit ff4bc37d77, on 2020-12-14. Until the support was added, invalid binaries could be created if some special sections, such as .init_array, had SHF_GNU_RETAIN set. HAVE_GAS_SHF_GNU_RETAIN is now disabled if a version of gold without SHF_GNU_RETAIN support is detected. I tested that HAVE_GAS_SHF_GNU_RETAIN was enabled/disabled as appropriate in a number of configurations, using both in-tree and out-of-tree Binutils: - Before the Binutils gold patch: * gold disabled == SHF_GNU_RETAIN enabled * gold enabled == SHF_GNU_RETAIN disabled - After the Binutils gold patch: * gold disabled == SHF_GNU_RETAIN enabled * gold enabled == SHF_GNU_RETAIN enabled Successfully bootstrapped for x86_64-pc-linux-gnu. Ok to apply?
>From af3000bbacc6d8ca57581c11790032b73ea944ac Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz <joze...@mittosystems.com> Date: Wed, 16 Dec 2020 18:33:54 +0000 Subject: [PATCH] configure: Extend SHF_GNU_RETAIN conftest to check for unsupported gold Since "6fbec038f7a Use SHF_GNU_RETAIN to preserve symbol definitions", GCC could create sections with the 'R' flag, which GAS would map to SHF_GNU_RETAIN. SHF_GNU_RETAIN support was not available in gold until Binutils commit ff4bc37d77, on 2020-12-14. Until the support was added, invalid binaries could be created if some special sections, such as .init_array, had SHF_GNU_RETAIN set. HAVE_GAS_SHF_GNU_RETAIN is now disabled if a version of gold without SHF_GNU_RETAIN support is detected. gcc/ChangeLog: PR target/98210 * configure: Regenerate. * configure.ac (gcc_cv_as_shf_gnu_retain): Disable HAVE_GAS_SHF_GNU_RETAIN for gold versions that do not support it. --- gcc/configure | 60 ++++++++++++++++++++++++++++++++++++++++++++- gcc/configure.ac | 64 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/gcc/configure b/gcc/configure index 9a27e459f14..544ec92463e 100755 --- a/gcc/configure +++ b/gcc/configure @@ -24442,7 +24442,63 @@ case "${target}" in gcc_cv_as_shf_gnu_retain=no ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5 + # gold did not support SHF_GNU_RETAIN until 2.35.50.20201215. + # Support for SHF_GNU_RETAIN in GCC was only added on 2020-12-01, so rather + # than only disabling the GCC functionality if gold is the default, disable + # it if a gold without the support has been built at all. + + ld_gold=`which ${gcc_cv_ld}.gold` + check_gold_ver=no + if test x$ld_is_gold = xyes; then + # Always check_gold_ver when gold is the default linker. + check_gold_ver=yes + gold_date=$ld_date + elif test -f ../gold/ld-new$build_exeext; then + # Always check_gold_ver when gold has been built in-tree. + check_gold_ver=yes + gold_ver=`../gold/ld-new$build_exeext --version 2>/dev/null | sed 1q` + gold_date=`echo $gold_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)\(-*\)\([01][0-9]\)\2\([0-3][0-9]\).*$,\1\3\4,p'` + elif test -n "$ld_gold"; then + gold_ver=`${gcc_cv_ld}.gold --version 2>/dev/null | sed 1q` + gold_vers=`echo $gold_ver | sed -n \ + -e 's,^[^)]*[ ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'` + gold_date=`echo $gold_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)\(-*\)\([01][0-9]\)\2\([0-3][0-9]\).*$,\1\3\4,p'` + gold_vers_major=`expr "$gold_vers" : '\([0-9]*\)'` + gold_vers_minor=`expr "$gold_vers" : '[0-9]*\.\([0-9]*\)'` + gold_vers_patch=`expr "$gold_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'` + + # If gold exists but is not the default linker, we assume that it is + # still intended to be used if the version matches the default ld. + if test 0"$gold_vers_major" -eq 0"$ld_vers_major" \ + && test 0"$gold_vers_minor" -eq 0"$ld_vers_minor" \ + && test 0"$gold_vers_patch" -eq 0"$ld_vers_patch" \ + && test 0"$gold_date" -eq 0"$ld_date"; then + check_gold_ver=yes + fi + fi + + # To test for the period of time when the SHF_GNU_RETAIN flag is supported + # in ld, but not in gold, check the date in the version string. If there + # is no date, then we let gcc_GAS_CHECK_FEATURE make the correct + # choice. + if test $check_gold_ver = yes && test -n "$gold_date" \ + && test 0"$gold_date" -lt 20201215; then + gcc_cv_as_shf_gnu_retain=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking gold support for SHF_GNU_RETAIN" >&5 +$as_echo_n "checking gold support for SHF_GNU_RETAIN... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_shf_gnu_retain" >&5 +$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; } + else + # Versions of Binutils with SHF_GNU_RETAIN support do not directly + # correspond to a maj.min.patchlevel version, so even for in-tree GAS we + # always want to run the assembly test to check for support it, rather + # than looking at the version. Temporarily overriding in_tree_gas allows + # the assembly test to run. + # The first version of Binutils with SHF_GNU_RETAIN support is + # 2.35.50.20201118. + saved_in_tree_gas=$in_tree_gas + in_tree_gas=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5 $as_echo_n "checking assembler for section 'R' flag... " >&6; } if ${gcc_cv_as_shf_gnu_retain+:} false; then : $as_echo_n "(cached) " >&6 @@ -24475,6 +24531,8 @@ fi $as_echo "$gcc_cv_as_shf_gnu_retain" >&6; } + in_tree_gas=$saved_in_tree_gas + fi ;; esac diff --git a/gcc/configure.ac b/gcc/configure.ac index 062f57fa12b..dd92d9bfb8f 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3340,10 +3340,68 @@ case "${target}" in gcc_cv_as_shf_gnu_retain=no ;; *) - gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain, - [elf,2,36,0], [--fatal-warnings], - [.section .foo,"awR",%progbits + # gold did not support SHF_GNU_RETAIN until 2.35.50.20201215. + # Support for SHF_GNU_RETAIN in GCC was only added on 2020-12-01, so rather + # than only disabling the GCC functionality if gold is the default, disable + # it if a gold without the support has been built at all. + changequote(,)dnl + + ld_gold=`which ${gcc_cv_ld}.gold` + check_gold_ver=no + if test x$ld_is_gold = xyes; then + # Always check_gold_ver when gold is the default linker. + check_gold_ver=yes + gold_date=$ld_date + elif test -f ../gold/ld-new$build_exeext; then + # Always check_gold_ver when gold has been built in-tree. + check_gold_ver=yes + gold_ver=`../gold/ld-new$build_exeext --version 2>/dev/null | sed 1q` + gold_date=`echo $gold_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)\(-*\)\([01][0-9]\)\2\([0-3][0-9]\).*$,\1\3\4,p'` + elif test -n "$ld_gold"; then + gold_ver=`${gcc_cv_ld}.gold --version 2>/dev/null | sed 1q` + gold_vers=`echo $gold_ver | sed -n \ + -e 's,^[^)]*[ ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'` + gold_date=`echo $gold_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)\(-*\)\([01][0-9]\)\2\([0-3][0-9]\).*$,\1\3\4,p'` + gold_vers_major=`expr "$gold_vers" : '\([0-9]*\)'` + gold_vers_minor=`expr "$gold_vers" : '[0-9]*\.\([0-9]*\)'` + gold_vers_patch=`expr "$gold_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'` + + # If gold exists but is not the default linker, we assume that it is + # still intended to be used if the version matches the default ld. + if test 0"$gold_vers_major" -eq 0"$ld_vers_major" \ + && test 0"$gold_vers_minor" -eq 0"$ld_vers_minor" \ + && test 0"$gold_vers_patch" -eq 0"$ld_vers_patch" \ + && test 0"$gold_date" -eq 0"$ld_date"; then + check_gold_ver=yes + fi + fi + changequote([,])dnl + + # To test for the period of time when the SHF_GNU_RETAIN flag is supported + # in ld, but not in gold, check the date in the version string. If there + # is no date, then we let gcc_GAS_CHECK_FEATURE make the correct + # choice. + if test $check_gold_ver = yes && test -n "$gold_date" \ + && test 0"$gold_date" -lt 20201215; then + gcc_cv_as_shf_gnu_retain=no + AC_MSG_CHECKING(gold support for SHF_GNU_RETAIN) + AC_MSG_RESULT($gcc_cv_as_shf_gnu_retain) + else + # Versions of Binutils with SHF_GNU_RETAIN support do not directly + # correspond to a maj.min.patchlevel version, so even for in-tree GAS we + # always want to run the assembly test to check for support it, rather + # than looking at the version. Temporarily overriding in_tree_gas allows + # the assembly test to run. + # The first version of Binutils with SHF_GNU_RETAIN support is + # 2.35.50.20201118. + saved_in_tree_gas=$in_tree_gas + in_tree_gas=no + gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain, + [elf,2,36,0], [--fatal-warnings], + [.section .foo,"awR",%progbits .byte 0]) + in_tree_gas=$saved_in_tree_gas + fi ;; esac AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN, -- 2.29.2