This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [build, v3] Enable COMDAT group support on Solaris 10
- From: Rainer Orth <ro at CeBiTec dot Uni-Bielefeld dot DE>
- To: gcc-patches at gcc dot gnu dot org
- Cc: libstdc++ at gcc dot gnu dot org, Jakub Jelinek <jakub at redhat dot com>, Jonathan Wakely <jwakely at redhat dot com>
- Date: Tue, 06 Feb 2018 19:47:37 +0100
- Subject: Re: [build, v3] Enable COMDAT group support on Solaris 10
- Authentication-results: sourceware.org; auth=none
- References: <yddr2q8g2s1.fsf@CeBiTec.Uni-Bielefeld.DE>
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
--
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
2018-01-28 Rainer Orth <ro@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}