Message ID | yddr2q8g2s1.fsf@CeBiTec.Uni-Bielefeld.DE |
---|---|
State | New |
Headers | show |
Series | [build,v3] Enable COMDAT group support on Solaris 10 | expand |
Rainer Orth <ro@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
# HG changeset patch # Parent a2aa0e644c08a13add93210418e981320cac0513 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 @@ -379,13 +379,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 @@ -2971,6 +2971,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], @@ -3040,11 +3059,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. @@ -3085,15 +3113,20 @@ case "${target}" in if test $in_tree_ld = yes || echo "$ld_ver" | grep GNU > /dev/null; then hidden_linkonce=yes else + hidden_linkonce=no case "${target}" in + # When COMDAT group support is enabled on Solaris 10, hidden + # linkonce works, too. + *-*-solaris2.10*) + if x$comdat_group = xyes; then + hidden_linkonce=yes + fi + ;; # Full support for hidden thunks in linkonce sections only appeared in # Solaris 11/OpenSolaris. *-*-solaris2.1[[1-9]]*) hidden_linkonce=yes ;; - *) - hidden_linkonce=no - ;; esac fi AC_MSG_RESULT($hidden_linkonce) 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;