This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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 */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]