This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
[Patch] Unterminated .eh_frame when using --eh-frame-hdr
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: libc-alpha at sources dot redhat dot com
- Date: Mon, 08 Nov 2004 14:32:24 +0000
- Subject: [Patch] Unterminated .eh_frame when using --eh-frame-hdr
HAVE_DWARF2_UNWIND_INFO currently guards two things:
(a) the calls to __register_frame_info(), etc.
(b) the __EH_FRAME_BEGIN__ and __FRAME_END__ definitions, including
(in the latter case) .eh_frame's null terminator.
Both are omitted when --eh-frame-hdr is in use.
The current set-up works fine when .eh_frame_hdr has a binary-sorted
table of FDEs. The problem is that this sorted table is optional, and
isn't created if an FDE uses an absolute encoding for the initial PC.
Quoting from bfd/elf-eh-frame.c:
/* If a shared library uses absolute pointers
which we cannot turn into PC relative,
don't create the binary search table,
since it is affected by runtime relocations. */
On targets like x86, gcc will generate PC-relative FDEs when generating
PIC, so we do indeed get the sorted table. Unfortunately, the MIPS ABIs
don't define a suitable relocation for PC-relative encodings, so gcc uses
an absolute encoding instead.
At the moment, the linker doesn't convert these absolute MIPS FDEs into
PC-relative form (although it probably should) and so .eh_frame_hdr has
no sorted table. The unwinder must therefore create the table itself,
just as it would if there were no .eh_frame_hdr, and to do that it needs
to know where the end of .eh_frame is. Omitting (b) for --eh-frame-hdr
prevents this and can lead to a segfault when unwinding through libc.
The patch below introduces a new macro, HAVE_DWARF2_UNWIND_INFO_REGISTRY,
to control (a), and enables (b) when --eh-frame-hdr is being used.
Tested on MIPS (all three ABIs). It fixes various g++ failures like
eh/terminate1.C. Please install if OK.
Richard
PS. I've included the autogenerated change to configure since it's likely
to apply cleanly. Let me know if that's not the done thing ;)
2004-11-08 Richard Sandiford <rsandifo@redhat.com>
* configure.in (HAVE_DWARF2_UNWIND_INFO): Define even when no
registry calls are needed.
(HAVE_DWARF2_UNWIND_INFO_REGISTRY): New macro.
* configure: Regenerate.
* config.h.in (HAVE_DWARF2_UNWIND_INFO_REGISTRY): Add placeholder.
* elf/soinit.c: Use HAVE_DWARF2_UNWIND_INFO_REGISTRY rather than
HAVE_DWARF2_UNWIND_INFO to guard the registry code.
Index: configure.in
===================================================================
RCS file: /cvs/glibc/libc/configure.in,v
retrieving revision 1.430
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.430 configure.in
--- configure.in 26 Oct 2004 01:35:54 -0000 1.430
+++ configure.in 8 Nov 2004 14:20:38 -0000
@@ -1778,12 +1778,17 @@ if test $libc_cv_gcc_dwarf2_unwind_info
fi
rm -f conftest*])
case $libc_cv_gcc_dwarf2_unwind_info in
+no_registry_needed)
+ AC_DEFINE(HAVE_DWARF2_UNWIND_INFO)
+ ;;
yes)
AC_DEFINE(HAVE_DWARF2_UNWIND_INFO)
+ AC_DEFINE(HAVE_DWARF2_UNWIND_INFO_REGISTRY)
;;
static)
AC_DEFINE(HAVE_DWARF2_UNWIND_INFO)
AC_DEFINE(HAVE_DWARF2_UNWIND_INFO_STATIC)
+ AC_DEFINE(HAVE_DWARF2_UNWIND_INFO_REGISTRY)
;;
esac
Index: configure
===================================================================
RCS file: /cvs/glibc/libc/configure,v
retrieving revision 1.423
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.423 configure
--- configure 26 Oct 2004 01:35:53 -0000 1.423
+++ configure 8 Nov 2004 14:20:48 -0000
@@ -6378,11 +6378,21 @@ fi
echo "$as_me:$LINENO: result: $libc_cv_gcc_dwarf2_unwind_info" >&5
echo "${ECHO_T}$libc_cv_gcc_dwarf2_unwind_info" >&6
case $libc_cv_gcc_dwarf2_unwind_info in
+no_registry_needed)
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_DWARF2_UNWIND_INFO 1
+_ACEOF
+
+ ;;
yes)
cat >>confdefs.h <<\_ACEOF
#define HAVE_DWARF2_UNWIND_INFO 1
_ACEOF
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_DWARF2_UNWIND_INFO_REGISTRY 1
+_ACEOF
+
;;
static)
cat >>confdefs.h <<\_ACEOF
@@ -6393,6 +6403,10 @@ _ACEOF
#define HAVE_DWARF2_UNWIND_INFO_STATIC 1
_ACEOF
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_DWARF2_UNWIND_INFO_REGISTRY 1
+_ACEOF
+
;;
esac
Index: config.h.in
===================================================================
RCS file: /cvs/glibc/libc/config.h.in,v
retrieving revision 1.70
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.70 config.h.in
--- config.h.in 16 Sep 2004 23:55:55 -0000 1.70
+++ config.h.in 8 Nov 2004 14:20:51 -0000
@@ -98,6 +98,10 @@
#undef HAVE_DWARF2_UNWIND_INFO
/* Define if gcc uses DWARF2 unwind information for exception support
+ and requires explicit calls to register the unwind tables. */
+#undef HAVE_DWARF2_UNWIND_INFO_REGISTRY
+
+/* Define if gcc uses DWARF2 unwind information for exception support
with static variable. */
#undef HAVE_DWARF2_UNWIND_INFO_STATIC
Index: elf/soinit.c
===================================================================
RCS file: /cvs/glibc/libc/elf/soinit.c,v
retrieving revision 1.11
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.11 soinit.c
--- elf/soinit.c 26 Nov 2003 07:14:31 -0000 1.11
+++ elf/soinit.c 8 Nov 2004 14:20:51 -0000
@@ -28,6 +28,8 @@ run_hooks (void (*const list[]) (void))
static char __EH_FRAME_BEGIN__[]
__attribute__ ((section (".eh_frame")))
= { };
+#endif
+#ifdef HAVE_DWARF2_UNWIND_INFO_REGISTRY
# ifdef HAVE_DWARF2_UNWIND_INFO_STATIC
extern void __register_frame_info (const void *, struct object *);
extern void __register_frame_info_bases (const void *, struct object *,
@@ -47,7 +49,7 @@ __libc_global_ctors (void)
/* Call constructor functions. */
run_hooks (__CTOR_LIST__);
-#ifdef HAVE_DWARF2_UNWIND_INFO
+#ifdef HAVE_DWARF2_UNWIND_INFO_REGISTRY
# ifdef HAVE_DWARF2_UNWIND_INFO_STATIC
{
static struct object ob;
@@ -89,7 +91,7 @@ __libc_fini (void)
{
/* Call destructor functions. */
run_hooks (__DTOR_LIST__);
-#ifdef HAVE_DWARF2_UNWIND_INFO
+#ifdef HAVE_DWARF2_UNWIND_INFO_REGISTRY
# ifdef HAVE_DWARF2_UNWIND_INFO_STATIC
# if defined CRT_GET_RFIB_TEXT || defined CRT_GET_RFIB_DATA
__deregister_frame_info_bases (__EH_FRAME_BEGIN__);