Patchwork PATCH: PR debug/54568: --eh-frame-hdr should also be enabled for static executable

login
register
mail settings
Submitter H.J. Lu
Date Sept. 14, 2012, 2:46 a.m.
Message ID <20120914024652.GA661@intel.com>
Download mbox | patch
Permalink /patch/183788/
State New
Headers show

Comments

H.J. Lu - Sept. 14, 2012, 2:46 a.m.
Hi,

There is no reason why --eh-frame-hdr can't be used with static
executable on Linux.  This patch enables --eh-frame-hdr for static
executable on Linux and adds an exception test for static executable.
Other platforms may also work correctly.  But I can't verify it.

Tested on Linux/x86-64.  OK to install?

Thanks.


H.J.
----
gcc/

2012-09-13  H.J. Lu  <hongjiu.lu@intel.com>

	PR debug/54568
	* config/gnu-user.h (USE_LD_EH_FRAME_HDR_FOR_STATIC): Defined
	if HAVE_LD_EH_FRAME_HDR is defined.
	(LINK_EH_SPEC): Drop "!static".

gcc/testsuite/

2012-09-13  H.J. Lu  <hongjiu.lu@intel.com>

	PR debug/54568
	* g++.dg/eh/spec3-static.C: New test.

libgcc/

2012-09-13  H.J. Lu  <hongjiu.lu@intel.com>

	PR debug/54568
	* crtstuff.c (USE_PT_GNU_EH_FRAME): Check CRTSTUFFT_O together
	with USE_LD_EH_FRAME_HDR_FOR_STATIC.
Jakub Jelinek - Sept. 14, 2012, 9:41 a.m.
On Thu, Sep 13, 2012 at 07:46:52PM -0700, H.J. Lu wrote:
> There is no reason why --eh-frame-hdr can't be used with static
> executable on Linux.  This patch enables --eh-frame-hdr for static

Well, there is.  For more than 2 years after the addition of --eh-frame-hdr
support dl_iterate_phdr in libc.a would simply always fail, you aren't
adding any kind of check that old glibc (2001-2003ish) isn't used.
Even in newer glibcs, it relies on AT_* aux vector values provided by the
kernel, if they are not provided for whatever reason, it would fail.

	Jakub
H.J. Lu - Sept. 14, 2012, 12:12 p.m.
On Fri, Sep 14, 2012 at 2:41 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Thu, Sep 13, 2012 at 07:46:52PM -0700, H.J. Lu wrote:
>> There is no reason why --eh-frame-hdr can't be used with static
>> executable on Linux.  This patch enables --eh-frame-hdr for static
>
> Well, there is.  For more than 2 years after the addition of --eh-frame-hdr
> support dl_iterate_phdr in libc.a would simply always fail, you aren't
> adding any kind of check that old glibc (2001-2003ish) isn't used.
> Even in newer glibcs, it relies on AT_* aux vector values provided by the
> kernel, if they are not provided for whatever reason, it would fail.
>
>         Jakub

It was implemented in

http://sourceware.org/ml/libc-alpha/2003-10/msg00098.html

for glibc 2.3.0 and we can check

AT_PHDR:         0x400040
AT_PHNUM:        10

with LD_SHOW_AUXV.
Jakub Jelinek - Sept. 14, 2012, 12:26 p.m.
On Fri, Sep 14, 2012 at 05:12:19AM -0700, H.J. Lu wrote:
> On Fri, Sep 14, 2012 at 2:41 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> > Well, there is.  For more than 2 years after the addition of --eh-frame-hdr
> > support dl_iterate_phdr in libc.a would simply always fail, you aren't
> > adding any kind of check that old glibc (2001-2003ish) isn't used.
> > Even in newer glibcs, it relies on AT_* aux vector values provided by the
> > kernel, if they are not provided for whatever reason, it would fail.

> It was implemented in
> 
> http://sourceware.org/ml/libc-alpha/2003-10/msg00098.html
> 
> for glibc 2.3.0 and we can check

Yeah, I know, but that is still later than 2001 when it was implemented for
dynamically linked executables.
USE_PT_GNU_EH_FRAME is defined even for glibc 2.2.something (if DT_CONFIG
macro is defined in headers).

> AT_PHDR:         0x400040
> AT_PHNUM:        10
> 
> with LD_SHOW_AUXV.

I was worried about some loaders that wouldn't pass the aux vector down.
E.g. valgrind's loader does, but perhaps others wouldn't need to.

Anyway, IMHO statically linked binaries aren't something one should spend
too much time on, they shouldn't be used (with very few exceptions) at all.

	Jakub
H.J. Lu - Sept. 14, 2012, 1:59 p.m.
On Fri, Sep 14, 2012 at 5:26 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Fri, Sep 14, 2012 at 05:12:19AM -0700, H.J. Lu wrote:
>> On Fri, Sep 14, 2012 at 2:41 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> > Well, there is.  For more than 2 years after the addition of --eh-frame-hdr
>> > support dl_iterate_phdr in libc.a would simply always fail, you aren't
>> > adding any kind of check that old glibc (2001-2003ish) isn't used.
>> > Even in newer glibcs, it relies on AT_* aux vector values provided by the
>> > kernel, if they are not provided for whatever reason, it would fail.
>
>> It was implemented in
>>
>> http://sourceware.org/ml/libc-alpha/2003-10/msg00098.html
>>
>> for glibc 2.3.0 and we can check
>
> Yeah, I know, but that is still later than 2001 when it was implemented for
> dynamically linked executables.
> USE_PT_GNU_EH_FRAME is defined even for glibc 2.2.something (if DT_CONFIG
> macro is defined in headers).

Here is a patch to add an option to use --eh-frame-hdr on static.
It won't enable it for uclibc since it is > glibc 2.2.

>> AT_PHDR:         0x400040
>> AT_PHNUM:        10
>>
>> with LD_SHOW_AUXV.
>
> I was worried about some loaders that wouldn't pass the aux vector down.
> E.g. valgrind's loader does, but perhaps others wouldn't need to.

Those loaders are broken for binaries, static or dynamic, which use AUXV,
independent of this change, and they should be fixed.  It shouldn't block
using --eh-frame-hdr for -static.

> Anyway, IMHO statically linked binaries aren't something one should spend
> too much time on, they shouldn't be used (with very few exceptions) at all.
>

Android doesn't need those legacy stuff.  We have to keep it
since GCC doesn't pass --eh-frame-hdr for -static.  At minimum,
I'd like a configure option to use --eh-frame-hdr for -static, even if
it is off by default.

OK to install?

Thanks.
Joseph S. Myers - Sept. 14, 2012, 4:26 p.m.
On Fri, 14 Sep 2012, H.J. Lu wrote:

> +# Only support for glibc 2.3.0 or higher with AT_PHDR/AT_PHNUM from
> +# Linux kernel.
> +   [[if test x$host = x$build -a x$host = x$target &&
> +       ldd --version 2>&1 >/dev/null &&

Could we please stop adding this sort of native-only test?  There is 
various existing code that examines headers to determine glibc features, 
which is more cross-compile friendly.  This should probably be factored 
out into an autoconf macro to determine values from target headers, used 
once in configure.ac to get the glibc version for tools with glibc 
targets, and the --enable-gnu-unique-object test should be changed to use 
the version from the headers like other tests do.

Patch

diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h
index cb45749..aa4e78d 100644
--- a/gcc/config/gnu-user.h
+++ b/gcc/config/gnu-user.h
@@ -82,7 +82,8 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define LIB_SPEC GNU_USER_TARGET_LIB_SPEC
 
 #if defined(HAVE_LD_EH_FRAME_HDR)
-#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+#define USE_LD_EH_FRAME_HDR_FOR_STATIC
+#define LINK_EH_SPEC "--eh-frame-hdr "
 #endif
 
 #undef LINK_GCC_C_SEQUENCE_SPEC
diff --git a/gcc/testsuite/g++.dg/eh/spec3-static.C b/gcc/testsuite/g++.dg/eh/spec3-static.C
new file mode 100644
index 0000000..15408ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/spec3-static.C
@@ -0,0 +1,25 @@ 
+// PR c++/4381
+// Test that exception-specs work properly for classes with virtual bases.
+
+// { dg-do run }
+// { dg-options "-static" }
+
+class Base {};
+
+struct A : virtual public Base
+{
+  A() {}
+};
+
+struct B {};
+
+void func() throw (B,A)
+{
+  throw A();
+}
+
+int main(void)
+{
+  try {	func(); }
+  catch (A& a) { }
+}
diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c
index 973956a..01cf254 100644
--- a/libgcc/crtstuff.c
+++ b/libgcc/crtstuff.c
@@ -84,7 +84,8 @@  call_ ## FUNC (void)					\
 #if defined(OBJECT_FORMAT_ELF) \
     && !defined(OBJECT_FORMAT_FLAT) \
     && defined(HAVE_LD_EH_FRAME_HDR) \
-    && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+    && !defined(inhibit_libc) \
+    && (defined(USE_LD_EH_FRAME_HDR_FOR_STATIC) || !defined(CRTSTUFFT_O)) \
     && defined(__FreeBSD__) && __FreeBSD__ >= 7
 #include <link.h>
 # define USE_PT_GNU_EH_FRAME
@@ -93,7 +94,8 @@  call_ ## FUNC (void)					\
 #if defined(OBJECT_FORMAT_ELF) \
     && !defined(OBJECT_FORMAT_FLAT) \
     && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR) \
-    && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+    && !defined(inhibit_libc) \
+    && (defined(USE_LD_EH_FRAME_HDR_FOR_STATIC) || !defined(CRTSTUFFT_O)) \
     && defined(__sun__) && defined(__svr4__)
 #include <link.h>
 # define USE_PT_GNU_EH_FRAME
@@ -102,7 +104,8 @@  call_ ## FUNC (void)					\
 #if defined(OBJECT_FORMAT_ELF) \
     && !defined(OBJECT_FORMAT_FLAT) \
     && defined(HAVE_LD_EH_FRAME_HDR) \
-    && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+    && !defined(inhibit_libc) \
+    && (defined(USE_LD_EH_FRAME_HDR_FOR_STATIC) || !defined(CRTSTUFFT_O)) \
     && defined(__GLIBC__) && __GLIBC__ >= 2
 #include <link.h>
 /* uClibc pretends to be glibc 2.2 and DT_CONFIG is defined in its link.h.
@@ -117,7 +120,7 @@  call_ ## FUNC (void)					\
 #if defined(OBJECT_FORMAT_ELF) \
     && !defined(OBJECT_FORMAT_FLAT) \
     && defined(HAVE_LD_EH_FRAME_HDR) \
-    && !defined(CRTSTUFFT_O) \
+    && (defined(USE_LD_EH_FRAME_HDR_FOR_STATIC) || !defined(CRTSTUFFT_O)) \
     && defined(inhibit_libc) \
     && (defined(__GLIBC__) || defined(__gnu_linux__) || defined(__GNU__))
 /* On systems using glibc, an inhibit_libc build of libgcc is only