Rainer Orth <r...@cebitec.uni-bielefeld.de> writes: > While investigating PR bootstrap/84017, it turned out that it *is* > possible to enable COMDAT group support on Solaris 10 with Solaris ld in > some circumstances. I'm posting my findings and the resulting patch > here for reference only; this is certainly not GCC 8 material. > > Besides, there's a abi_check failure in libstdc++ which makes it unclear > if this desirable at all. > > So here's the deal: I remembered that Solaris ld has a -z relaxreloc > option, documented as > > -z relaxreloc > > ld normally issues a fatal error upon encountering a > relocation using a symbol that references an eliminated > COMDAT section. If -z relaxreloc is enabled, ld instead > redirects such relocations to the equivalent symbol in > the COMDAT section that was kept. -z relaxreloc is a > specialized option, mainly of interest to compiler > authors, and is not intended for general use. > > It was only introduced in Solaris 10 Update 10, so won't help on earlier > versions. > > When ld supports that option, I always pass it when linking and enable > comdat_group (and hidden_linkonce) in configure.ac. > > Test results are astonishingly good: > > * On Solaris 10/x86, I get three tests where ld SEGVs with -flto > (skipped/xfailed in the present patch). > > * On both Solaris 10/SPARC and x86, libstdc++-abi/abi_check FAILs: > > # of added symbols: 2 > # of missing symbols: 0 > # of undesignated symbols: 0 > # of incompatible symbols: 2 > > 2 added symbols > 0 > _ZNSt7__cxx1115basic_stringbufIwSt11char_traitsIwESaIwEED2Ev > std::__cxx11::basic_stringbuf<wchar_t, std::char_traits<wchar_t>, > std::allocator<wchar_t> >::~basic_stringbuf() > version status: incompatible > GLIBCXX_3.4.21 > type: function > status: added > > 1 > _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED2Ev > std::__cxx11::basic_stringbuf<char, std::char_traits<char>, > std::allocator<char> >::~basic_stringbuf() > version status: incompatible > GLIBCXX_3.4.21 > type: function > status: added > > > 2 incompatible symbols > 0 > _ZNSt7__cxx1115basic_stringbufIwSt11char_traitsIwESaIwEED2Ev > std::__cxx11::basic_stringbuf<wchar_t, std::char_traits<wchar_t>, > std::allocator<wchar_t> >::~basic_stringbuf() > version status: incompatible > GLIBCXX_3.4.21 > type: function > status: added > > > 1 > _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED2Ev > std::__cxx11::basic_stringbuf<char, std::char_traits<char>, > std::allocator<char> >::~basic_stringbuf() > version status: incompatible > GLIBCXX_3.4.21 > type: function > status: added > > Those symbols are present in the Solaris 11 baselines (where COMDAT > group always works), which is also used with Solaris 10 and GNU ld. > > I'm not yet sure how to deal with this: we'd have to introduce 3 > baselines: > > * Solaris 10 without COMDAT group support > * Solaris 10 with COMDAT group support > * Solaris 11 > > Seems like a lot of trouble to me actually. I've not done anything > about this yet, so as is the patch shows the abi_check failures.
I've now revised the patch a bit, especially for the abi_check failure: * Since Solaris 10 with gld (which already did support COMDAT group) already used the *-solaris2.11 baselines, I've extended that to any Solaris 10 configuration with COMDAT group support. This needed a configure test in libstdc++-v3/acinclude.m4 matching what the comdat_group effective-target keyword does. However, I couldn't use a simple AC_TRY_COMPILE with -S added to CXXFLAGS: that will always fail since the macro checks for the existence of conftest.o as first indication of success, which of course doesn't exist with -S. * I've also tried to enable USE_HIDDEN_LINKONCE on Solaris 10/x86 with COMDAT group, but that leads to four more testcases where ld SEGVs, so I've left it disabled. Otherwise, nothing remarkable: bootstrapped without regressions on i386-pc-solaris2.10 and sparc-sun-solaris2.10 (both as/ld and gas/ld) without and with --disable-comdat; also bootstrapped on some *-*-solaris2.11 configurations, no regressions. I'm just posting this for comment here; I may or may not commit this in the GCC 9 timeframe. Rainer -- ----------------------------------------------------------------------------- Rainer Orth, Center for Biotechnology, Bielefeld University 2018-01-28 Rainer Orth <r...@cebitec.uni-bielefeld.de> libstdc++-v3: * acinclude.m4 (GLIBCXX_CONFIGURE): Check for COMDAT group support. * configure: Regenerate. * configure.host (*-*-solaris2.1[0-9])): Check $comdat_group to select baselines. gcc/testsuite: * g++.dg/lto/pr65475c_0.C: Skip on Solaris 10/x86 with ld/comdat. * g++.dg/lto/pr68057_0.C: Likewise. * gcc.dg/debug/pr41893-1.c: Xfail on Solaris 10/x86 with ld/comdat for -gdwarf-2 -g3. gcc: * configure.ac (gcc_cv_ld_relaxreloc): New test. (comdat_group): Enable on Solaris 10 if ld -z relaxreloc is present. * configure: Regenerate. * config.in: Regenerate. * config/sol2.h (LINK_RELAXRELOC_SPEC): Define. (LINK_SPEC): Use it.
# HG changeset patch # Parent 9ebcf04c4cd938f58f5ae28f2daff24e1be7ffa1 Enable comdat on Solaris 10 diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -380,13 +380,20 @@ along with GCC; see the file COPYING3. #define LINK_CLEARCAP_SPEC "" #endif +/* Relax linker COMDAT checks. Necessary to support COMDAT on Solaris 10. */ +#ifdef HAVE_LD_RELAXRELOC +#define LINK_RELAXRELOC_SPEC " -z relaxreloc" +#else +#define LINK_RELAXRELOC_SPEC "" +#endif + #undef LINK_SPEC #define LINK_SPEC \ "%{h*} %{v:-V} \ %{!shared:%{!static:%{rdynamic: " RDYNAMIC_SPEC "}}} \ %{static:-dn -Bstatic} \ %{shared:-G -dy %{!mimpure-text:-z text}} " \ - LINK_LIBGCC_MAPFILE_SPEC LINK_CLEARCAP_SPEC " \ + LINK_LIBGCC_MAPFILE_SPEC LINK_CLEARCAP_SPEC LINK_RELAXRELOC_SPEC " \ %{symbolic:-Bsymbolic -G -dy -z text} \ %(link_arch) \ %{Qy:} %{!Qn:-Qy}" diff --git a/gcc/configure.ac b/gcc/configure.ac --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2978,6 +2978,25 @@ gcc_GAS_CHECK_FEATURE([stabs directive], [AC_DEFINE(HAVE_AS_STABS_DIRECTIVE, 1, [Define if your assembler supports .stabs.])]) +case "$target" in + # Solaris 10 Update 10 added ld support for relaxing COMDAT checks. The + # option later got renamed/generalized to -z relax=comdat. Only check on + # Solaris 10, though. It isn't needed/desirable on later Solaris releases. + *-*-solaris2.10*) + AC_MSG_CHECKING(linker -z relaxreloc option) + if $gcc_cv_ld -z help 2>&1 | grep relaxreloc > /dev/null; then + gcc_cv_ld_relaxreloc=yes + else + gcc_cv_ld_relaxreloc=no + fi + if test x"$gcc_cv_ld_relaxreloc" = xyes; then + AC_DEFINE(HAVE_LD_RELAXRELOC, 1, + [Define if your linker supports -z relaxreloc.]) + fi + AC_MSG_RESULT($gcc_cv_ld_relaxreloc) + ;; +esac + gcc_GAS_CHECK_FEATURE([COMDAT group support (GNU as)], gcc_cv_as_comdat_group, [elf,2,16,0], [--fatal-warnings], @@ -3047,11 +3066,20 @@ elif echo "$ld_ver" | grep GNU > /dev/nu else changequote(,)dnl case "${target}" in + *-*-solaris2.10*) + # On Solaris 10, the -z relaxreloc option allows to override some + # checks and make COMDAT group work. + if test x"$gcc_cv_ld_relaxreloc" = xyes; then + comdat_group=yes + else + comdat_group=no + fi + ;; *-*-solaris2.1[1-9]*) comdat_group=no # Sun ld has COMDAT group support since Solaris 9, but it doesn't - # interoperate with GNU as until Solaris 11 build 130, i.e. ld - # version 1.688. + # interoperate out of the box with GNU as until Solaris 11 build 130, + # i.e. ld version 1.688. # # If using Sun as for COMDAT group as emitted by GCC, one needs at # least ld version 1.2267. diff --git a/gcc/testsuite/g++.dg/lto/pr65475c_0.C b/gcc/testsuite/g++.dg/lto/pr65475c_0.C --- a/gcc/testsuite/g++.dg/lto/pr65475c_0.C +++ b/gcc/testsuite/g++.dg/lto/pr65475c_0.C @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */ /* { dg-lto-options { "-O2 -w -Wno-return-type" } } */ +/* { dg-skip-if "Solaris 10/x86 ld SEGVs" { { i?86-*-solaris2.10* x86_64-*-solaris2.10* } && { comdat_group && { ! gld } } } } */ namespace std { diff --git a/gcc/testsuite/g++.dg/lto/pr68057_0.C b/gcc/testsuite/g++.dg/lto/pr68057_0.C --- a/gcc/testsuite/g++.dg/lto/pr68057_0.C +++ b/gcc/testsuite/g++.dg/lto/pr68057_0.C @@ -1,5 +1,6 @@ // { dg-lto-do link } /* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */ +/* { dg-skip-if "Solaris 10/x86 ld SEGVs" { { i?86-*-solaris2.10* x86_64-*-solaris2.10* } && { comdat_group && { ! gld } } } } */ struct SPxPricer; struct SoPlex { virtual void setPricer(SPxPricer *); diff --git a/gcc/testsuite/gcc.dg/debug/pr41893-1.c b/gcc/testsuite/gcc.dg/debug/pr41893-1.c --- a/gcc/testsuite/gcc.dg/debug/pr41893-1.c +++ b/gcc/testsuite/gcc.dg/debug/pr41893-1.c @@ -3,6 +3,7 @@ /* { dg-require-effective-target lto } */ /* { dg-options "-flto -fwhole-program -O" } */ /* { dg-additional-sources "pr41893-2.c" } */ +/* { dg-xfail-if "Solaris 10/x86 ld SEGVs" { { i?86-*-solaris2.10* x86_64-*-solaris2.10* } && { comdat_group && { ! gld } } } { "-gdwarf-2 -g3" } } */ struct S { int v; }; struct S s; diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -113,6 +113,34 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [ #endif ], bionic=yes, bionic=no) + # Check for COMDAT group support. + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + old_CXXFLAGS="$CXXFLAGS" + AC_MSG_CHECKING([for COMDAT group support]) + CXXFLAGS='-S' + + # Fake what AC_TRY_COMPILE does. + cat > conftest.$ac_ext << EOF +inline int foo () { return 1; } +int (*fn) () = foo; +EOF + + if AC_TRY_EVAL(ac_compile); then + if $EGREP '\.section.*,comdat|\.group.*,#comdat' conftest.s > /dev/null 2>&1; then + comdat_group=yes + else + comdat_group=no + fi + else + comdat_group=no + fi + rm -f conftest* + + AC_MSG_RESULT($comdat_group) + CXXFLAGS="$old_CXXFLAGS" + AC_LANG_RESTORE + # Find platform-specific directories containing configuration info. # Also possibly modify flags used elsewhere, as needed by the platform. GLIBCXX_CHECK_HOST diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host --- a/libstdc++-v3/configure.host +++ b/libstdc++-v3/configure.host @@ -367,18 +367,11 @@ case "${host}" in port_specific_symbol_files="\$(srcdir)/../config/os/bsd/darwin/ppc-extra.ver" ;; *-*-solaris2.1[0-9]) - # On Solaris 10 with Solaris ld, there's no COMDAT support. GNU ld always - # provides it, as does Solaris ld since Solaris 11, leading to different - # baselines. - case "${host_os}:${with_gnu_ld}" in - # with_gnu_ld may either be unset (default) or no (with --without-gnu-ld). - solaris2.10: | solaris2.10:no) - abi_baseline_pair=solaris2.10 - ;; - *) - abi_baseline_pair=solaris2.11 - ;; - esac + if test "$comdat_group" = yes; then + abi_baseline_pair=solaris2.11 + else + abi_baseline_pair=solaris2.10 + fi case "${host_cpu}" in i?86 | x86_64) abi_baseline_pair=i386-${abi_baseline_pair}