diff mbox series

[build,v3] Enable COMDAT group support on Solaris 10

Message ID yddr2q8g2s1.fsf@CeBiTec.Uni-Bielefeld.DE
State New
Headers show
Series [build,v3] Enable COMDAT group support on Solaris 10 | expand

Commit Message

Rainer Orth Jan. 29, 2018, 2:25 p.m. UTC
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.

	Rainer

Comments

Rainer Orth Feb. 6, 2018, 6:47 p.m. UTC | #1
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
diff mbox series

Patch

# 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;