Patchwork [update] Support .eh_frame in crt1 x86_64 glibc (PR libgcc/57280, libc/15407)

login
register
mail settings
Submitter Jan Kratochvil
Date May 14, 2013, 7:12 p.m.
Message ID <20130514191244.GA12530@host2.jankratochvil.net>
Download mbox | patch
Permalink /patch/243804/
State New
Headers show

Comments

Jan Kratochvil - May 14, 2013, 7:12 p.m.
Added its gcc/doc/ part.  Previous pending post was:
http://gcc.gnu.org/ml/gcc-patches/2013-05/msg00275.html
Message-ID: <20130506172221.GA21105@host2.jankratochvil.net>
------------------------------------------------------------------------------
Hi,

since
	[patch] x86_64: CFI unwinding stop in _start
	http://sourceware.org/ml/libc-alpha/2012-03/msg00573.html

there is a regression reproducible with gold:
	http://sourceware.org/bugzilla/show_bug.cgi?id=15407
	http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57280 (GCC tracker)

as .eh_frame is created before the __EH_FRAME_BEGIN__ marker.  Linking order:
	/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crt1.o
	^^^ .eh_frame is used here
	/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crti.o
	/usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtbegin.o
	^^^ __EH_FRAME_BEGIN__ marker here

Therefore proposing to move the __EH_FRAME_BEGIN__ marker earlier:
	/usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtbegin1.o
	^^^ __EH_FRAME_BEGIN__ marker here
	/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crt1.o
	^^^ .eh_frame is used here
	/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crti.o
	/usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtbegin.o

It is questionable which all targets should this change affect.  If find it
a needless + untestable change to split crtbegin.o for very every target.
I have split it for every glibc x86_64 target (I hope) even if the one uses
PT_GNU_EH_FRAME (for which the __EH_FRAME_BEGIN__ marker is not needed),
it does not hurt and it was easier (possible?) that way.

I have split it also for the non-Linux glibc i386 + x86_64 targets as AFAIK
they are also affected the same way by the glibc change.

I had to split also i386 despite the glibc change affects only x86_64.  It was
needed for the case of --target=i686-pc-linux-gnu --enable-targets=all where:

gcc/config.gcc:
i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
[...]
                if test x$enable_targets = xall; then
                        tm_file="${tm_file} i386/x86-64.h i386/gnu-user-common.h i386/gnu-user64.h i386/linux-common.h i386/linux64.h"

Here the x86_64 *.h files get included even for the i386 target configuration
so it is no longer possible to make the spec change different for i386.

No regressions for Fedora 19 x86_64 GCC 4.9.0 20130504
and for gcc-4.8.0-3.fc19.{x86_64,i686}.

The x$enable_targets = xall case was tested on Debian 7.0 i386 with:
  --enable-languages=c --without-cloog --disable-libquadmath --enable-targets=all

It would be good to test also on some of the *BSD hosts, I will try some from
the GCC Compile Farm if this patch gets approved.


Thanks,
Jan


gcc/
2013-05-14  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* config/i386/gnu-user-common.h (USE_CRT_BEGIN1)
	(GNU_USER_TARGET_BEGIN1_SPEC, STARTFILE_SPEC): New.
	* config/i386/linux-common.h (STARTFILE_SPEC): Use also
	GNU_USER_TARGET_BEGIN1_SPEC.
	* doc/fragments.texi (Target Fragment): Mention also crtbeginS1.o for
	CRTSTUFF_T_CFLAGS_S.
	* doc/tm.texi.in (Initialization): Add crtbegin1.o to the example.
	Mention also crtbeginS1.o for crtstuff.c.
	(Exception Region Output): Add USE_CRT_BEGIN1.
	* doc/tm.texi: Regenerated.

libgcc/
2013-05-06  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* Makefile.in (crtbegin1$(objext), crtbeginS1$(objext))
	(crtbeginT1$(objext)): New.
	* config.host (i[34567]86-*-linux*, i[34567]86-*-kfreebsd*-gnu)
	(i[34567]86-*-knetbsd*-gnu, i[34567]86-*-gnu*)
	(i[34567]86-*-kopensolaris*-gnu, x86_64-*-linux*)
	(x86_64-*-kfreebsd*-gnu, x86_64-*-knetbsd*-gnu): Add crtbegin1.o,
	crtbeginS1.o and crtbeginT1.o.
	* crtstuff.c: New block for CRT_BEGIN1.  Copy __EH_FRAME_BEGIN__ there
	and also move it to the start of CRT_BEGIN block.

Patch

diff --git a/gcc/config/i386/gnu-user-common.h b/gcc/config/i386/gnu-user-common.h
index e28483d..7848906 100644
--- a/gcc/config/i386/gnu-user-common.h
+++ b/gcc/config/i386/gnu-user-common.h
@@ -45,6 +45,14 @@  along with GCC; see the file COPYING3.  If not see
 #undef CC1_SPEC
 #define CC1_SPEC GNU_USER_TARGET_CC1_SPEC
 
+#undef USE_CRT_BEGIN1
+#define USE_CRT_BEGIN1
+#define GNU_USER_TARGET_BEGIN1_SPEC \
+  "%{static:crtbeginT1.o%s;shared|pie:crtbeginS1.o%s;:crtbegin1.o%s}"
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC GNU_USER_TARGET_BEGIN1_SPEC " " \
+		       GNU_USER_TARGET_STARTFILE_SPEC
+
 /* Similar to standard GNU userspace, but adding -ffast-math support.  */
 #define GNU_USER_TARGET_MATHFILE_SPEC \
   "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h
index 1e8bf6b..a442bb1 100644
--- a/gcc/config/i386/linux-common.h
+++ b/gcc/config/i386/linux-common.h
@@ -44,7 +44,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #undef  STARTFILE_SPEC
 #define STARTFILE_SPEC \
-  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_STARTFILE_SPEC, \
+  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_BEGIN1_SPEC " " \
+		       GNU_USER_TARGET_STARTFILE_SPEC, \
 		       ANDROID_STARTFILE_SPEC)
 
 #undef  ENDFILE_SPEC
diff --git a/gcc/doc/fragments.texi b/gcc/doc/fragments.texi
index b9a0c34..1741a4d 100644
--- a/gcc/doc/fragments.texi
+++ b/gcc/doc/fragments.texi
@@ -56,8 +56,8 @@  Special flags used when compiling @file{crtstuff.c}.
 @findex CRTSTUFF_T_CFLAGS_S
 @item CRTSTUFF_T_CFLAGS_S
 Special flags used when compiling @file{crtstuff.c} for shared
-linking.  Used if you use @file{crtbeginS.o} and @file{crtendS.o}
-in @code{EXTRA-PARTS}.
+linking.  Used if you use @file{crtbeginS.o}, @file{crtendS.o} and
+possibly @file{crtbeginS1.o} in @code{EXTRA-PARTS}.
 @xref{Initialization}.
 
 @findex MULTILIB_OPTIONS
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 611d681..e1e9ef8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -8186,7 +8186,8 @@  parts of @file{crtstuff.c} are compiled into that section.  The
 program is linked by the @command{gcc} driver like this:
 
 @smallexample
-ld -o @var{output_file} crti.o crtbegin.o @dots{} -lgcc crtend.o crtn.o
+ld -o @var{output_file} crtbegin1.o crti.o crtbegin.o @dots{} \
+   -lgcc crtend.o crtn.o
 @end smallexample
 
 The prologue of a function (@code{__init}) appears in the @code{.init}
@@ -8195,12 +8196,13 @@  for the function @code{__fini} in the @dfn{.fini} section.  Normally these
 files are provided by the operating system or by the GNU C library, but
 are provided by GCC for a few targets.
 
-The objects @file{crtbegin.o} and @file{crtend.o} are (for most targets)
-compiled from @file{crtstuff.c}.  They contain, among other things, code
-fragments within the @code{.init} and @code{.fini} sections that branch
-to routines in the @code{.text} section.  The linker will pull all parts
-of a section together, which results in a complete @code{__init} function
-that invokes the routines we need at startup.
+The objects @file{crtbegin1.o}, @file{crtbegin.o} and @file{crtend.o}
+are (for most targets) compiled from @file{crtstuff.c}.  They contain,
+among other things, code fragments within the @code{.init} and
+@code{.fini} sections that branch to routines in the @code{.text}
+section.  The linker will pull all parts of a section together, which
+results in a complete @code{__init} function that invokes the routines
+we need at startup.
 
 To use this variant, you must define the @code{INIT_SECTION_ASM_OP}
 macro properly.
@@ -8765,6 +8767,15 @@  runtime relocation, but the linker may not support merging read-only
 and read-write sections into a single read-write section.
 @end defmac
 
+@defmac USE_CRT_BEGIN1
+If defined, exception handling frame unwind information start marker
+will be placed in separate file @file{crtbeginS1.o}.
+@file{crtbeginS1.o} needs to be also requested in @code{EXTRA-PARTS} of
+the libgcc @file{config.host}.  @file{crtbeginS1.o} should be linked as
+the very first file before startup files like @file{crti.o} so that they
+can also produce frame unwind information.
+@end defmac
+
 @defmac MASK_RETURN_ADDR
 An rtx used to mask the return address found via @code{RETURN_ADDR_RTX}, so
 that it does not contain any extraneous set bits in it.
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 990cd49..5a8d834 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -953,6 +953,9 @@  ifeq ($(CUSTOM_CRTSTUFF),)
 # Compile two additional files that are linked with every program
 # linked using GCC on systems using COFF or ELF, for the sake of C++
 # constructors.
+crtbegin1$(objext): $(srcdir)/crtstuff.c
+	$(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN1
+
 crtbegin$(objext): $(srcdir)/crtstuff.c
 	$(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN
 
@@ -960,6 +963,9 @@  crtend$(objext): $(srcdir)/crtstuff.c
 	$(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_END
 
 # These are versions of crtbegin and crtend for shared libraries.
+crtbeginS1$(objext): $(srcdir)/crtstuff.c
+	$(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< -DCRT_BEGIN1 -DCRTSTUFFS_O
+
 crtbeginS$(objext): $(srcdir)/crtstuff.c
 	$(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< -DCRT_BEGIN -DCRTSTUFFS_O
 
@@ -967,6 +973,9 @@  crtendS$(objext): $(srcdir)/crtstuff.c
 	$(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< -DCRT_END -DCRTSTUFFS_O
 
 # This is a version of crtbegin for -static links.
+crtbeginT1$(objext): $(srcdir)/crtstuff.c
+	$(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN1 -DCRTSTUFFT_O
+
 crtbeginT$(objext): $(srcdir)/crtstuff.c
 	$(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN -DCRTSTUFFT_O
 endif
diff --git a/libgcc/config.host b/libgcc/config.host
index 5e0f5ce..e6abdae 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -520,20 +520,24 @@  x86_64-*-openbsd*)
 	;;
 i[34567]86-*-linux*)
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
+	extra_parts="$extra_parts crtbegin1.o crtbeginS1.o crtbeginT1.o"
 	tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
 	md_unwind_header=i386/linux-unwind.h
 	;;
 i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
+	extra_parts="$extra_parts crtbegin1.o crtbeginS1.o crtbeginT1.o"
 	tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
 	;;
 x86_64-*-linux*)
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
+	extra_parts="$extra_parts crtbegin1.o crtbeginS1.o crtbeginT1.o"
 	tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
 	md_unwind_header=i386/linux-unwind.h
 	;;
 x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu)
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
+	extra_parts="$extra_parts crtbegin1.o crtbeginS1.o crtbeginT1.o"
 	tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
 	;;
 i[34567]86-pc-msdosdjgpp*)
diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c
index 0beda5e..1fad467 100644
--- a/libgcc/crtstuff.c
+++ b/libgcc/crtstuff.c
@@ -197,7 +197,34 @@  typedef void (*func_ptr) (void);
 
 #endif /* OBJECT_FORMAT_ELF */
 
-#ifdef CRT_BEGIN
+#ifdef CRT_BEGIN1
+
+#ifndef USE_CRT_BEGIN1
+# error "USE_CRT_BEGIN1 must be defined if CRT_BEGIN1 is in use."
+#endif /* ! USE_CRT_BEGIN1 */
+
+#ifdef USE_EH_FRAME_REGISTRY
+EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
+     __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4),
+		    __visibility__ ("hidden")))
+     = { };
+#endif /* USE_EH_FRAME_REGISTRY */
+
+#elif defined(CRT_BEGIN) /* ! CRT_BEGIN1 */
+
+#ifndef USE_CRT_BEGIN1
+# ifdef USE_EH_FRAME_REGISTRY
+/* Stick a label at the beginning of the frame unwind info so we can register
+   and deregister it with the exception handling library code.  */
+STATIC EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
+     __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4)))
+     = { };
+# endif /* USE_EH_FRAME_REGISTRY */
+#else /* USE_CRT_BEGIN1 */
+# ifdef USE_EH_FRAME_REGISTRY
+extern EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[];
+# endif /* USE_EH_FRAME_REGISTRY */
+#endif /* USE_CRT_BEGIN1 */
 
 /* NOTE:  In order to be able to support SVR4 shared libraries, we arrange
    to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
@@ -246,14 +273,6 @@  STATIC func_ptr __DTOR_LIST__[1]
 #endif /* __DTOR_LIST__ alternatives */
 #endif /* USE_INITFINI_ARRAY */
 
-#ifdef USE_EH_FRAME_REGISTRY
-/* Stick a label at the beginning of the frame unwind info so we can register
-   and deregister it with the exception handling library code.  */
-STATIC EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
-     __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4)))
-     = { };
-#endif /* USE_EH_FRAME_REGISTRY */
-
 #ifdef JCR_SECTION_NAME
 /* Stick a label at the beginning of the java class registration info
    so we can register them properly.  */
@@ -584,7 +603,7 @@  __do_global_ctors_1(void)
 #error "What are you doing with crtstuff.c, then?"
 #endif
 
-#elif defined(CRT_END) /* ! CRT_BEGIN */
+#elif defined(CRT_END) /* ! CRT_BEGIN1 && ! CRT_BEGIN */
 
 /* No need for .ctors/.dtors section if linker can place them in
    .init_array/.fini_array section.  */
@@ -752,6 +771,6 @@  __do_global_ctors (void)
 #error "What are you doing with crtstuff.c, then?"
 #endif
 
-#else /* ! CRT_BEGIN && ! CRT_END */
-#error "One of CRT_BEGIN or CRT_END must be defined."
+#else /* ! CRT_BEGIN1 && ! CRT_BEGIN && ! CRT_END */
+#error "One of CRT_BEGIN1, CRT_BEGIN or CRT_END must be defined."
 #endif