This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]