This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: PATCH: Share the dwarf2 unwind code between glibc and gcc 3.0
On Mon, Jul 09, 2001 at 04:06:18PM +0200, Mark Kettenis wrote:
>
> Changing the code such that it does find the GCC 2.x exception handler
> info is almost trivial. I implemented it, and it works fine with GCC
> 2.95.2. I already posted my code once. Attached is a slightly
> improved version. The difference between this code and the origional
> code from gcc-3_0-branch are an additional member of `struct
> _Unwind_Context' and a bit of code to fetch the GCC 2.x exception
> handler info in extract_cie_info(). The missing headers can be taken
> verbatim from the GCC 3.x sources. Of course integrating this into
> glibc would still involve a bit of work, but I'm not going to invest
> my time in it while HJ is still pushing his patch.
>
Here is a new patch based on Mark's __frame_state_for. I put the
patched unwind-dw2-fde.c, unwind-dw2-fde.h and unwind-dw2.c, plus the
unpatched unwind.h and unwind-pe.h in glibc. The resulting libc.soes
compiled with gcc 2.95, 2.96 and 3.0.1 work fine with my testcases.
H.J.
----
2001-07-09 H.J. Lu (hjl@gnu.org)
* unwind-dw2-fde.c: Include glibc heade files instead if _LIBC
is defined.
(init_object_mutex_once): Define differently if _LIBC is
defined.
(object_mutex_lock): New. Defined.
(object_mutex_unlock): New. Defined.
Replace all __gthread_mutex_lock (&object_mutex) with
object_mutex_lock ().
Replace all __gthread_mutex_unlock (&object_mutex) with
object_mutex_unlock ().
* unwind-dw2-fde.h (DW_EH_flexarr): New. Defined.
Replace all [] in struct with DW_EH_flexarr.
(object): Don't define if _LIBC is defined.
Replace all fde with struct dwarf_fde.
* unwind-dw2.c: Include glibc heade files instead if _LIBC is
defined.
(NEED___frame_state_for): New. Defined if _LIBC is defined.
(STACK_GROWS_DOWNWARD): Don't define if NEED___frame_state_for
is defined.
(_Unwind_Context): Likewise.
(extract_cie_info): Likewise.
(execute_stack_op): Likewise.
(uw_frame_state_for): Likewise.
(uw_update_context_1): Likewise.
(uw_update_context): Likewise.
(uw_init_context_1): Likewise.
(init_dwarf_reg_size_table): Likewise.
(uw_install_context_1): Likewise.
(uw_identify_context): Likewise.
Don't include "unwind.inc" if NEED___frame_state_for is
defined.
(__frame_state_for): New. Based on a patch from Mark Kettenis
<kettenis@science.uva.nl>. Define if NEED___frame_state_for is
defined.
2001-07-09 H.J. Lu (hjl@gnu.org)
* unwind-dw2-fde.c: Include glibc heade files instead if _LIBC
is defined.
(init_object_mutex_once): Define differently if _LIBC is
defined.
(object_mutex_lock): New. Defined.
(object_mutex_unlock): New. Defined.
Replace all __gthread_mutex_lock (&object_mutex) with
object_mutex_lock ().
Replace all __gthread_mutex_unlock (&object_mutex) with
object_mutex_unlock ().
* unwind-dw2-fde.h (DW_EH_flexarr): New. Defined.
Replace all [] in struct with DW_EH_flexarr.
(object): Don't define if _LIBC is defined.
Replace all fde with struct dwarf_fde.
* unwind-dw2.c: Include glibc heade files instead if _LIBC is
defined.
(NEED___frame_state_for): New. Defined if _LIBC is defined.
(STACK_GROWS_DOWNWARD): Don't define if NEED___frame_state_for
is defined.
(_Unwind_Context): Likewise.
(extract_cie_info): Likewise.
(execute_stack_op): Likewise.
(uw_frame_state_for): Likewise.
(uw_update_context_1): Likewise.
(uw_update_context): Likewise.
(uw_init_context_1): Likewise.
(init_dwarf_reg_size_table): Likewise.
(uw_install_context_1): Likewise.
(uw_identify_context): Likewise.
Don't include "unwind.inc" if NEED___frame_state_for is
defined.
(__frame_state_for): New. Based on a patch from Mark Kettenis
<kettenis@science.uva.nl>. Define if NEED___frame_state_for is
defined.
--- gcc/unwind-dw2-fde.c.mixed Tue Jun 12 14:39:06 2001
+++ gcc/unwind-dw2-fde.c Mon Jul 9 13:55:10 2001
@@ -28,6 +28,16 @@ along with GNU CC; see the file COPYING.
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#ifdef _LIBC
+#include <stdlib.h>
+#include <string.h>
+#include <bits/libc-lock.h>
+#include <dwarf2.h>
+#include <gccframe.h>
+#include <unwind.h>
+#include <unwind-pe.h>
+#include <unwind-dw2-fde.h>
+#else
#include "tconfig.h"
#include "tsystem.h"
#include "dwarf2.h"
@@ -35,6 +45,7 @@ Boston, MA 02111-1307, USA. */
#include "unwind-pe.h"
#include "unwind-dw2-fde.h"
#include "gthr.h"
+#endif
/* The unseen_objects list contains objects that have been registered
but not yet categorized in any way. The seen_objects list has had
@@ -43,6 +54,14 @@ Boston, MA 02111-1307, USA. */
static struct object *unseen_objects;
static struct object *seen_objects;
+#ifdef _LIBC
+__libc_lock_define_initialized_recursive (static, object_lock)
+#define init_object_mutex_once()
+#define object_mutex_lock() __libc_lock_lock (object_lock)
+#define object_mutex_unlock() __libc_lock_unlock (object_lock)
+#else
+#define object_mutex_lock() __gthread_mutex_lock (&object_mutex)
+#define object_mutex_unlock() __gthread_mutex_unlock (&object_mutex)
#ifdef __GTHREAD_MUTEX_INIT
static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
#else
@@ -65,6 +84,7 @@ init_object_mutex_once (void)
#else
#define init_object_mutex_once()
#endif
+#endif /* _LIBC */
/* Called from crtbegin.o to register the unwind info for an object. */
@@ -80,12 +100,12 @@ __register_frame_info_bases (void *begin
ob->s.b.encoding = DW_EH_PE_omit;
init_object_mutex_once ();
- __gthread_mutex_lock (&object_mutex);
+ object_mutex_lock();
ob->next = unseen_objects;
unseen_objects = ob;
- __gthread_mutex_unlock (&object_mutex);
+ object_mutex_unlock();
}
void
@@ -118,12 +138,12 @@ __register_frame_info_table_bases (void
ob->s.b.encoding = DW_EH_PE_omit;
init_object_mutex_once ();
- __gthread_mutex_lock (&object_mutex);
+ object_mutex_lock();
ob->next = unseen_objects;
unseen_objects = ob;
- __gthread_mutex_unlock (&object_mutex);
+ object_mutex_unlock();
}
void
@@ -158,7 +178,7 @@ __deregister_frame_info_bases (void *beg
struct object *ob = 0;
init_object_mutex_once ();
- __gthread_mutex_lock (&object_mutex);
+ object_mutex_lock();
for (p = &unseen_objects; *p ; p = &(*p)->next)
if ((*p)->u.single == begin)
@@ -189,11 +209,11 @@ __deregister_frame_info_bases (void *beg
}
}
- __gthread_mutex_unlock (&object_mutex);
+ object_mutex_unlock();
abort ();
out:
- __gthread_mutex_unlock (&object_mutex);
+ object_mutex_unlock();
return (void *) ob;
}
@@ -936,7 +956,7 @@ _Unwind_Find_FDE (void *pc, struct dwarf
fde *f = NULL;
init_object_mutex_once ();
- __gthread_mutex_lock (&object_mutex);
+ object_mutex_lock();
/* Linear search through the classified objects, to find the one
containing the pc. Note that pc_begin is sorted decending, and
@@ -970,7 +990,7 @@ _Unwind_Find_FDE (void *pc, struct dwarf
}
fini:
- __gthread_mutex_unlock (&object_mutex);
+ object_mutex_unlock();
if (f)
{
--- gcc/unwind-dw2-fde.h.mixed Tue May 22 16:53:14 2001
+++ gcc/unwind-dw2-fde.h Mon Jul 9 13:33:38 2001
@@ -28,14 +28,23 @@ along with GNU CC; see the file COPYING.
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Support different versions of gcc and glibc. */
+#if defined _LIBC && defined __flexarr
+#define DW_EH_flexarr __flexarr
+#endif
+
+#ifndef DW_EH_flexarr
+#define DW_EH_flexarr []
+#endif
struct fde_vector
{
void *orig_data;
size_t count;
- struct dwarf_fde *array[];
+ struct dwarf_fde *array DW_EH_flexarr;
};
+#ifndef _LIBC
struct object
{
void *pc_begin;
@@ -62,6 +71,7 @@ struct object
struct object *next;
};
+#endif
/* This is the original definition of struct object. While the struct
itself was opaque to users, they did know how large it was, and
@@ -131,7 +141,7 @@ struct dwarf_cie
uword length;
sword CIE_id;
ubyte version;
- unsigned char augmentation[];
+ unsigned char augmentation DW_EH_flexarr;
} __attribute__ ((packed, aligned (__alignof__ (void *))));
/* The first few fields of an FDE. */
@@ -139,7 +149,7 @@ struct dwarf_fde
{
uword length;
sword CIE_delta;
- unsigned char pc_begin[];
+ unsigned char pc_begin DW_EH_flexarr;
} __attribute__ ((packed, aligned (__alignof__ (void *))));
typedef struct dwarf_fde fde;
--- gcc/unwind-dw2.c.mixed Sat May 19 17:31:42 2001
+++ gcc/unwind-dw2.c Mon Jul 9 13:57:39 2001
@@ -18,6 +18,22 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#ifdef _LIBC
+#include <stdlib.h>
+#include <string.h>
+#include <error.h>
+#include <libintl.h>
+#include <gccframe.h>
+#include <dwarf2.h>
+#include <unwind.h>
+#include <unwind-pe.h>
+#include <unwind-dw2-fde.h>
+
+#define NEED___frame_state_for
+
+#undef USING_SJLJ_EXCEPTIONS
+#define USING_SJLJ_EXCEPTIONS 0
+#else
#include "tconfig.h"
#include "tsystem.h"
#include "dwarf2.h"
@@ -25,17 +41,11 @@
#include "unwind-pe.h"
#include "unwind-dw2-fde.h"
#include "gthr.h"
+#endif
#if !USING_SJLJ_EXCEPTIONS
-#ifndef STACK_GROWS_DOWNWARD
-#define STACK_GROWS_DOWNWARD 0
-#else
-#undef STACK_GROWS_DOWNWARD
-#define STACK_GROWS_DOWNWARD 1
-#endif
-
/* A target can override (perhaps for backward compatibility) how
many dwarf2 columns are unwound. */
#ifndef DWARF_FRAME_REGISTERS
@@ -51,10 +61,20 @@ struct _Unwind_Context
void *lsda;
struct dwarf_eh_bases bases;
_Unwind_Word args_size;
+ void *eh_ptr;
};
+#ifndef _LIBC
+#ifndef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 0
+#else
+#undef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
+#endif
+
/* Byte size of every register managed by these routines. */
static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS];
+#endif /* !_LIBC */
/* The result of interpreting the frame unwind info for a frame.
@@ -220,6 +240,16 @@ extract_cie_info (struct dwarf_cie *cie,
const unsigned char *ret = NULL;
_Unwind_Ptr tmp;
+ /* We must properly recognize "eh" to support g++ v2. */
+ if (aug[0] == 'e' && aug[1] == 'h')
+ {
+ context->eh_ptr = read_pointer (p);
+ p += sizeof (void *);
+ aug += 2;
+ }
+ else
+ context->eh_ptr = 0;
+
/* Immediately following the augmentation are the code and
data alignment and return address column. */
p = read_uleb128 (p, &tmp); fs->code_align = tmp;
@@ -242,15 +272,8 @@ extract_cie_info (struct dwarf_cie *cie,
/* Iterate over recognized augmentation subsequences. */
while (*aug != '\0')
{
- /* "eh" was used by g++ v2; recognize and skip. */
- if (aug[0] == 'e' && aug[1] == 'h')
- {
- p += sizeof (void *);
- aug += 2;
- }
-
/* "L" indicates a byte showing how the LSDA pointer is encoded. */
- else if (aug[0] == 'L')
+ if (aug[0] == 'L')
{
fs->lsda_encoding = *p++;
aug += 1;
@@ -280,7 +303,7 @@ extract_cie_info (struct dwarf_cie *cie,
return ret ? ret : p;
}
-
+#ifndef _LIBC
/* Decode a DW_OP stack program. Return the top of stack. Push INITIAL
onto the stack to start. */
@@ -676,7 +699,7 @@ execute_stack_op (const unsigned char *o
abort ();
return stack[stack_elt];
}
-
+#endif /* !_LIBC */
/* Decode DWARF 2 call frame information. Takes pointers the
instruction sequence to decode, current register information and
@@ -939,6 +962,88 @@ uw_frame_state_for (struct _Unwind_Conte
}
+#ifdef NEED___frame_state_for
+typedef struct frame_state
+{
+ void *cfa;
+ void *eh_ptr;
+ long cfa_offset;
+ long args_size;
+ long reg_or_offset[DWARF_FRAME_REGISTERS+1];
+ unsigned short cfa_reg;
+ unsigned short retaddr_column;
+ char saved[DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+
+/* Called from __throw to find the registers to restore for a given
+ PC_TARGET. The caller should allocate a local variable of `struct
+ frame_state' (declared in frame.h) and pass its address to STATE_IN. */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+ struct _Unwind_Context context;
+ _Unwind_FrameState fs;
+ int reg;
+
+ memset (&context, 0, sizeof (struct _Unwind_Context));
+ context.ra = pc_target + 1;
+
+ if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+ return 0;
+
+ /* We have no way to pass a location expression for the CFA to our
+ caller. It wouldn't understand it anyway. */
+ if (fs.cfa_how == CFA_EXP)
+#ifdef _LIBC
+ error (EXIT_FAILURE, 0,
+ _("REG_SAVED_EXP: Unsupported gcc v3 exception frame state."));
+#else
+ abort ();
+#endif
+
+ memset (state_in, 0, sizeof (*state_in));
+ state_in->cfa_reg = fs.cfa_reg;
+ state_in->cfa_offset = fs.cfa_offset;
+ state_in->args_size = context.args_size;
+
+ for (reg = 0; reg < DWARF_FRAME_REGISTERS + 1; reg++)
+ {
+ state_in->saved[reg] = fs.regs.reg[reg].how;
+ switch (state_in->saved[reg])
+ {
+ case REG_UNSAVED:
+ break;
+ case REG_SAVED_REG:
+ state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+ break;
+ case REG_SAVED_OFFSET:
+ state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+ break;
+ case REG_SAVED_EXP:
+ /* g++ v2 doesn't support REG_SAVED_EXP. */
+#ifdef _LIBC
+ error (EXIT_FAILURE, 0,
+ _("REG_SAVED_EXP: Unsupported gcc v3 exception frame state."));
+#else
+ abort ();
+#endif
+ break;
+ }
+ }
+
+ state_in->cfa_offset = fs.cfa_offset;
+ state_in->cfa_reg = fs.cfa_reg;
+ state_in->retaddr_column = fs.retaddr_column;
+ state_in->args_size = context.args_size;
+ state_in->eh_ptr = context.eh_ptr;
+
+ return state_in;
+}
+#endif /* NEED___frame_state_for */
+
+#ifndef _LIBC
static void
uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
@@ -1118,5 +1223,7 @@ uw_identify_context (struct _Unwind_Cont
#include "unwind.inc"
+
+#endif /* !_LIBC */
#endif /* !USING_SJLJ_EXCEPTIONS */