As described in the PR, the 64-bit Solaris 10+/x86 libc contains an
implementation of those _Unwind_* functions required by the AMD64 ABI,
i.e. those contained in libgcc_s.so.1 at version GCC_3.0.

If by some circumstance (use of -Bdirect, -z lazyload, maybe others)
libc.so.1 happens to be searched by ld.so.1 before libgcc_s.so.1 and
some library (e.g. libstdc++.so.6) uses functions both from GCC_3.0
(then resolved from libc.so.1) and others (resolved from libgcc_s.so.1),
crashes result due to mixing those different implementations with
different internal data structures.

To avoid this, I suggest linking libgcc_s.so.1 with a mapfile that
enforces direct binding to the libgcc_s.so.1 implementation to avoid
that mixture.

The following patch does just that.  Initially, I tried to only use the
mapfile when -lgcc_s is used, but libtool often links shared objects
with -shared -nostdlib, adding -lgcc_s -lc -lgcc_s itself (for whatever
reason it deems appropriate to second-guess the compiler driver here).
Therefore I'm keying the mapfile use off -shared resp. -shared-libgcc
instead.

Unfortunately, the patch needs a change to the bundled ltmain.sh: by
default, libtool `optimizes' -lgcc_s -lc -lgcc_s into -lc -lgcc_s.
Combined with direct binding, this lead to exactly the failure the patch
intends to avoid.  The libtool bug has already been reported and a patch
proposed:

        http://lists.gnu.org/archive/html/libtool-patches/2014-01/msg00005.html

The patch has been tested on i386-pc-solaris2.{9,10,11} and
sparc-sun-solaris2.{9,10,11} with Sun as/ld and on i386-pc-solaris2.10
with Sun as/GNU ld.

I don't need approval for the Solaris specific parts, but another pair
of eyes would certainly be helpful.

One potential issue would be a version of gcc containing the patch used
with a libtool without the change.  The last libtool release was almost
two years ago, so this is quite a likely condition.  Fortunately,
problems would only ensure if some 64-bit Solaris/x86 program/library
uses the gcc extensions to the AMD64 unwinder.  According to a code
search, uses of those functions are very rare outside of gcc, and the
problem can be worked around by invoking libtool with
--preserve-dup-deps, so I consider this risk acceptable.

        Rainer


2014-01-14  Rainer Orth  <r...@cebitec.uni-bielefeld.de>

        gcc:
        PR target/59788
        * config/sol2.h (LINK_LIBGCC_MAPFILE_SPEC): Define.
        (LINK_SPEC): Use it for -shared, -shared-libgcc.

        libgcc:
        PR target/59788
        * config/t-slibgcc-sld (libgcc-unwind.map): New target.
        (install-libgcc-unwind-map-forbuild): New target.
        (all): Depend on install-libgcc-unwind-map-forbuild.
        (install-libgcc-unwind-map): New target.
        (install): Depend on install-libgcc-unwind-map.

        gcc/testsuite:
        PR target/59788
        * g++.dg/eh/unwind-direct.C: New test.

        libgo:
        PR target/59788
        * config/ltmain.sh (opt_duplicate_compiler_generated_deps): Enable on
        *solaris2*.

        toplevel:
        PR target/59788
        * ltmain.sh (opt_duplicate_compiler_generated_deps): Enable on
        *solaris2*.

# HG changeset patch
# Parent a6e6484e3cdf3a53d0e325f3faf34e291f8469fb
Ensure libgcc_s unwinder is always used on 64-bit Solaris 10+/x86 (PR target/59788)

diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -174,12 +174,21 @@ along with GCC; see the file COPYING3.  
 #define RDYNAMIC_SPEC "--export-dynamic"
 #endif
 
+#ifndef USE_GLD
+/* With Sun ld, use mapfile to enforce direct binding to libgcc_s unwinder.  */
+#define LINK_LIBGCC_MAPFILE_SPEC \
+  "%{shared|shared-libgcc:-M %slibgcc-unwind.map}"
+#else
+/* GNU ld doesn't support direct binding.  */
+#define LINK_LIBGCC_MAPFILE_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}} \
+   %{shared:-G -dy %{!mimpure-text:-z text}} " LINK_LIBGCC_MAPFILE_SPEC " \
    %{symbolic:-Bsymbolic -G -dy -z text} \
    %(link_arch) \
    %{Qy:} %{!Qn:-Qy}"
diff --git a/gcc/testsuite/g++.dg/eh/unwind-direct.C b/gcc/testsuite/g++.dg/eh/unwind-direct.C
new file mode 100644
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/unwind-direct.C
@@ -0,0 +1,15 @@
+// PR target/59788
+// { dg-do run { target { *-*-solaris2* && { ! gld } } } }
+// { dg-options "-Wl,-Bdirect" }
+
+#include <stdexcept>
+
+int
+main(void)
+{
+  try
+    { throw std::runtime_error( "Catch me if you can!"); }
+  catch(...)
+    { return 0; }
+  return 1;
+}
diff --git a/libgcc/config/t-slibgcc-sld b/libgcc/config/t-slibgcc-sld
--- a/libgcc/config/t-slibgcc-sld
+++ b/libgcc/config/t-slibgcc-sld
@@ -3,3 +3,26 @@
 
 SHLIB_LDFLAGS = -Wl,-h,$(SHLIB_SONAME) -Wl,-z,text -Wl,-z,defs \
 	-Wl,-M,$(SHLIB_MAP)
+
+# Linker mapfile to enforce direct binding to libgcc_s unwinder
+# (PR target/59788).
+libgcc-unwind.map: libgcc-std.ver
+	@(echo "{";				\
+	for f in `grep _Unwind_ $< | sort`; do	\
+	  echo "	$$f = EXTERN DIRECT;";	\
+	done;					\
+	echo "};" ) > $@
+
+# Copy libgcc-unwind.map to the place where gcc will look for it at build-time.
+install-libgcc-unwind-map-forbuild: libgcc-unwind.map
+	dest=$(gcc_objdir)/tmp$$$$-$<; \
+	cp $< $$dest; \
+	chmod a+r $$dest; \
+	sh $(srcdir)/../move-if-change $$dest $(gcc_objdir)/$<
+
+all: install-libgcc-unwind-map-forbuild
+
+install-libgcc-unwind-map: libgcc-unwind.map
+	$(INSTALL_DATA) $< $(DESTDIR)$(slibdir)
+
+install: install-libgcc-unwind-map
diff --git a/libgo/config/ltmain.sh b/libgo/config/ltmain.sh
--- a/libgo/config/ltmain.sh
+++ b/libgo/config/ltmain.sh
@@ -976,7 +976,7 @@ func_enable_tag ()
 
 
   case $host in
-    *cygwin* | *mingw* | *pw32* | *cegcc*)
+    *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* )
       # don't eliminate duplications in $postdeps and $predeps
       opt_duplicate_compiler_generated_deps=:
       ;;
diff --git a/ltmain.sh b/ltmain.sh
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -976,7 +976,7 @@ func_enable_tag ()
 
 
   case $host in
-    *cygwin* | *mingw* | *pw32* | *cegcc*)
+    *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* )
       # don't eliminate duplications in $postdeps and $predeps
       opt_duplicate_compiler_generated_deps=:
       ;;
-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

Reply via email to