Patchwork [build,libgcc] Ensure libgcc_s unwinder is always used on 64-bit Solaris 10+/x86 (PR target/59788)

login
register
mail settings
Submitter Rainer Orth
Date Jan. 17, 2014, 2:21 p.m.
Message ID <ydd38kmbsem.fsf@lokon.CeBiTec.Uni-Bielefeld.DE>
Download mbox | patch
Permalink /patch/312087/
State New
Headers show

Comments

Rainer Orth - Jan. 17, 2014, 2:21 p.m.
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  <ro@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*.
Rainer Orth - Jan. 20, 2014, 12:29 p.m.
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> 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 accepted upstream now.

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

Given that there were no other comments, I'd like to install the patch
now.  Ian, could you please install the ltmain.sh patch in libgo/config,
or should I do so myself?

Thanks.
        Rainer
Paolo Bonzini - Jan. 20, 2014, 12:32 p.m.
Il 17/01/2014 15:21, Rainer Orth ha scritto:
> 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  <ro@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*.
> 
> 
> 
> 

Thanks for getting the patch upstream!

Paolo
Ian Taylor - Jan. 20, 2014, 6:45 p.m.
On Mon, Jan 20, 2014 at 4:29 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
>
> Given that there were no other comments, I'd like to install the patch
> now.  Ian, could you please install the ltmain.sh patch in libgo/config,
> or should I do so myself?

I'll do it.  Thanks.

Ian
Rainer Orth - Feb. 3, 2014, 10:55 a.m.
Ian Lance Taylor <iant@google.com> writes:

> On Mon, Jan 20, 2014 at 4:29 AM, Rainer Orth
> <ro@cebitec.uni-bielefeld.de> wrote:
>>
>> Given that there were no other comments, I'd like to install the patch
>> now.  Ian, could you please install the ltmain.sh patch in libgo/config,
>> or should I do so myself?
>
> I'll do it.  Thanks.

Could you please take care of that, provided the RMs approve?  The patch
was ok two weeks ago and is completely Solaris-specific, so I'd like to
get it into the 4.9.0 release.

Thanks.
        Rainer
Ian Taylor - Feb. 3, 2014, 5:40 p.m.
On Mon, Feb 3, 2014 at 2:55 AM, Rainer Orth <ro@cebitec.uni-bielefeld.de> wrote:
> Ian Lance Taylor <iant@google.com> writes:
>
>> On Mon, Jan 20, 2014 at 4:29 AM, Rainer Orth
>> <ro@cebitec.uni-bielefeld.de> wrote:
>>>
>>> Given that there were no other comments, I'd like to install the patch
>>> now.  Ian, could you please install the ltmain.sh patch in libgo/config,
>>> or should I do so myself?
>>
>> I'll do it.  Thanks.
>
> Could you please take care of that, provided the RMs approve?  The patch
> was ok two weeks ago and is completely Solaris-specific, so I'd like to
> get it into the 4.9.0 release.

I was just waiting for you to commit it elsewhere.

The patch to libgo/ltmain.sh is now committed to mainline.

Ian
Rainer Orth - Feb. 4, 2014, 9:36 a.m.
Ian Lance Taylor <iant@google.com> writes:

>> Could you please take care of that, provided the RMs approve?  The patch
>> was ok two weeks ago and is completely Solaris-specific, so I'd like to
>> get it into the 4.9.0 release.
>
> I was just waiting for you to commit it elsewhere.

And I was waiting for you to commit the libgo part since doing it the
other way round would have broken the amd64 libgo.

> The patch to libgo/ltmain.sh is now committed to mainline.

I've now committed the rest, thanks.

Btw., what's the procedure for syncing the toplevel ltmain.sh these
days?  AFAIK there's both the old CVS src repo as well as the new
binutils-gdb git repo.  Does the patch need to go to both?

	Rainer
Joseph S. Myers - Feb. 4, 2014, 3:45 p.m.
On Tue, 4 Feb 2014, Rainer Orth wrote:

> > The patch to libgo/ltmain.sh is now committed to mainline.
> 
> I've now committed the rest, thanks.
> 
> Btw., what's the procedure for syncing the toplevel ltmain.sh these
> days?  AFAIK there's both the old CVS src repo as well as the new
> binutils-gdb git repo.  Does the patch need to go to both?

Yes, shared files and directories should be kept in sync between all three 
repositories (the src repository is still used for newlib).  It looks like 
some (e.g. configure.ac) have been getting out of sync lately.
Rainer Orth - Feb. 6, 2014, 10:08 a.m.
"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Tue, 4 Feb 2014, Rainer Orth wrote:
>
>> > The patch to libgo/ltmain.sh is now committed to mainline.
>> 
>> I've now committed the rest, thanks.
>> 
>> Btw., what's the procedure for syncing the toplevel ltmain.sh these
>> days?  AFAIK there's both the old CVS src repo as well as the new
>> binutils-gdb git repo.  Does the patch need to go to both?
>
> Yes, shared files and directories should be kept in sync between all three 
> repositories (the src repository is still used for newlib).  It looks like 
> some (e.g. configure.ac) have been getting out of sync lately.

Committed to both now.  Thanks for the info.

	Rainer

Patch

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