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]

PATCH: Share the dwarf2 unwind code between glibc and gcc 3.0


Here is my gcc patch to share the dwarf2 unwind code between glibc and
gcc. I will send patches for gcc 2.95/2.96 to do the same. Combine them
together in glibc, glibc can support mixed v2 and v3 unwind frames,
independent of the gcc version used to compile glibc.

Any comments?

Thanks.

H.J.
----
2001-07-07  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.
	(get_cie): Don't define if _LIBC is defined.
	(next_fde): Likewise.

	* unwind-pe.h: Include <gccframe.h> if _LIBC is defined.
	(frame_state): New for the v2 dwarf2 frame unwind code if
	NEED__Unwind_GetFrameForV2 is defined.
	(cie_info): Likewise.
	(_Unwind_GetFrameForV2): Likewise.
	(size_of_encoded_value): Don't define if DWARF2_FRAME_UNWIND_V2
	is defined.
	(base_of_encoded_value): Likewise.
	(read_encoded_value_with_base): Likewise.
	(read_encoded_value): Likewise.
	(read_uleb128): Likewise.
	(read_sleb128): Likewise.

	* unwind-dw2-fde.h (dwarf_eh_bases): Moved to ...
	* unwind-pe.h: Here.

	* unwind-dw2-fde.h (fde): Moved to ...
	* unwind-pe.h: Here.

	* unwind-dw2-fde.h (_Unwind_Find_FDE): Moved to ...
	* unwind-pe.h: Here.

	* unwind-dw2.c: Include glibc heade files instead if _LIBC is
	defined.
	(NEED__Unwind_GetFrameForV2): New. Defined if _LIBC is defined.
	(STACK_GROWS_DOWNWARD): Don't define if NEED__Unwind_GetFrameForV2
	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__Unwind_GetFrameForV2 is
	defined.
	(_Unwind_GetFrameForV2): New. Define if NEED__Unwind_GetFrameForV2
	is defined.

--- gcc/unwind-dw2-fde.c.mixed	Tue Jun 12 14:39:06 2001
+++ gcc/unwind-dw2-fde.c	Sun Jul  8 19:08:12 2001
@@ -28,6 +28,15 @@ 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 <unwind.h>
+#include <unwind-pe.h>
+#include <unwind-dw2-fde.h>
+#else
 #include "tconfig.h"
 #include "tsystem.h"
 #include "dwarf2.h"
@@ -35,6 +44,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 +53,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 +83,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 +99,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 +137,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 +177,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 +208,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 +955,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 +989,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	Sun Jul  8 19:10:40 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
@@ -77,14 +87,6 @@ struct old_object
   struct old_object *next;
 };
 
-struct dwarf_eh_bases
-{
-  void *tbase;
-  void *dbase;
-  void *func;
-};
-
-
 extern void __register_frame_info_bases (void *, struct object *,
 					 void *, void *);
 extern void __register_frame_info (void *, struct object *);
@@ -131,7 +133,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,11 +141,10 @@ 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;
-
+#ifndef DWARF2_FRAME_UNWIND_V2
 /* Locate the CIE for a given FDE.  */
 
 static inline struct dwarf_cie *
@@ -152,10 +153,9 @@ get_cie (struct dwarf_fde *f)
   return (void *)&f->CIE_delta - f->CIE_delta;
 }
 
-static inline fde *
-next_fde (fde *f)
+static inline struct dwarf_fde *
+next_fde (struct dwarf_fde *f)
 {
-  return (fde *)((char *)f + f->length + sizeof (f->length));
+  return (struct dwarf_fde *)((char *)f + f->length + sizeof (f->length));
 }
-
-extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
+#endif /* !DWARF2_FRAME_UNWIND_V2 */
--- gcc/unwind-dw2.c.mixed	Sat May 19 17:31:42 2001
+++ gcc/unwind-dw2.c	Sun Jul  8 18:58:58 2001
@@ -18,6 +18,20 @@
    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 <dwarf2.h>
+#include <unwind.h>
+#define NEED__Unwind_GetFrameForV2
+#include <unwind-pe.h>
+#include <unwind-dw2-fde.h>
+
+#undef USING_SJLJ_EXCEPTIONS
+#define USING_SJLJ_EXCEPTIONS 0
+#else
 #include "tconfig.h"
 #include "tsystem.h"
 #include "dwarf2.h"
@@ -25,17 +39,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
@@ -53,8 +61,17 @@ struct _Unwind_Context
   _Unwind_Word args_size;
 };
 
+#ifndef NEED__Unwind_GetFrameForV2
+#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 /* NEED__Unwind_GetFrameForV2 */
 
 
 /* The result of interpreting the frame unwind info for a frame.
@@ -207,6 +224,7 @@ _Unwind_GetTextRelBase (struct _Unwind_C
 }
 #endif
 
+#ifndef NEED__Unwind_GetFrameForV2
 /* Extract any interesting information from the CIE for the translation
    unit F belongs to.  Return a pointer to the byte after the augmentation,
    or NULL if we encountered an undecipherable augmentation.  */
@@ -676,7 +694,7 @@ execute_stack_op (const unsigned char *o
     abort ();
   return stack[stack_elt];
 }
-
+#endif /* !NEED__Unwind_GetFrameForV2 */
 
 /* Decode DWARF 2 call frame information. Takes pointers the
    instruction sequence to decode, current register information and
@@ -876,6 +894,89 @@ execute_cfa_program (const unsigned char
     }
 }
 
+#ifdef NEED__Unwind_GetFrameForV2
+void
+_Unwind_GetFrameForV2 (void *pc_target, const unsigned char *insn,
+		       fde *fde, struct dwarf_eh_bases * bases,
+		       struct frame_state *state,
+		       struct cie_info *info)
+{
+  struct _Unwind_Context context;
+  _Unwind_FrameState fs;
+  struct dwarf_cie *cie;
+  const unsigned char *aug, *end;
+  size_t s;
+
+  memset (&context, 0, sizeof (context));
+  context.args_size = 0;
+  context.lsda = 0;
+  context.ra = pc_target;
+  memcpy (&context.bases, bases, sizeof(*bases));
+
+  memset (&fs, 0, sizeof (fs));
+  fs.pc = context.bases.func;
+  fs.retaddr_column = info->ra_regno;
+  fs.code_align = info->code_align;
+  fs.data_align = info->data_align;
+  fs.lsda_encoding = info->lsda_encoding;
+  fs.fde_encoding = info->fde_encoding;
+  fs.saw_z = info->saw_z;
+
+  cie = get_cie (fde);
+
+  /* First decode all the insns in the CIE.  */
+  end = (unsigned char *) next_fde ((struct dwarf_fde *) cie);
+  execute_cfa_program (insn, end, &context, &fs);
+
+  /* Locate augmentation for the fde.  */
+  aug = (unsigned char *)fde + sizeof (*fde);
+  aug += 2 * size_of_encoded_value (fs.fde_encoding);
+  insn = NULL;
+  if (fs.saw_z)
+    {
+      _Unwind_Ptr i;
+      aug = read_uleb128 (aug, &i);
+      insn = aug + i;
+    }
+  if (fs.lsda_encoding != DW_EH_PE_omit)
+    aug = read_encoded_value (&context, fs.lsda_encoding, aug,
+			      (_Unwind_Ptr *) &context.lsda);
+
+  /* Then the insns in the FDE up to our target PC.  */
+  if (insn == NULL)
+    insn = aug;
+  end = (unsigned char *) next_fde (fde);
+  execute_cfa_program (insn, end, &context, &fs);
+
+  /* Now we convert to the old g++ v2 frame format.  */
+  state->cfa_reg = fs.cfa_reg;
+  state->cfa_offset = fs.cfa_offset;
+  state->args_size = context.args_size;
+
+  for (s = 0; s <= DWARF_FRAME_REGISTERS; s++)
+    {
+      switch (fs.regs.reg[s].how)
+	{
+	case REG_UNSAVED:
+	  state->saved[s] = REG_UNSAVED;
+	  break;
+	case REG_SAVED_OFFSET:
+	  state->saved[s] = REG_SAVED_OFFSET;
+	  state->reg_or_offset[s] = fs.regs.reg[s].loc.offset;
+	  break;
+	case REG_SAVED_REG:
+	  state->saved[s] = REG_SAVED_REG;
+	  state->reg_or_offset[s] = fs.regs.reg[s].loc.reg;
+	  break;
+	case REG_SAVED_EXP:
+	  /* g++ v2 doesn't support REG_SAVED_EXP.  */
+	  error (EXIT_FAILURE, 0,
+		 _("REG_SAVED_EXP: Unsupported gcc v3 exception frame state."));
+	  break;
+	}
+    }
+}
+#else /* NEED__Unwind_GetFrameForV2 */
 static _Unwind_Reason_Code
 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
 {
@@ -1118,5 +1219,7 @@ uw_identify_context (struct _Unwind_Cont
 
 
 #include "unwind.inc"
+
+#endif /* NEED__Unwind_GetFrameForV2 */
 
 #endif /* !USING_SJLJ_EXCEPTIONS */
--- gcc/unwind-pe.h.mixed	Tue Jun 12 14:39:06 2001
+++ gcc/unwind-pe.h	Sun Jul  8 18:54:29 2001
@@ -22,6 +22,10 @@
    compatibility problems with the base ABI.  This is slightly better
    than duplicating code, however.  */
 
+#ifdef _LIBC
+#include <gccframe.h>
+#endif
+
 /* If using C++, references to abort have to be qualified with std::. */
 #if __cplusplus
 #define __gxx_abort std::abort
@@ -51,7 +55,70 @@
 
 #define DW_EH_PE_indirect	0x80
 
+struct dwarf_eh_bases
+{
+  void *tbase;
+  void *dbase;
+  void *func;
+};
+
+/* It is shared by both v2 and v3 dwarf2 frame unwind code.  */
+struct dwarf_fde;
+typedef struct dwarf_fde fde;
+
+extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
+
+#ifdef NEED__Unwind_GetFrameForV2
+#ifndef DWARF_FRAME_REGISTERS
+# ifdef FIRST_PSEUDO_REGISTER
+#  define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+# else
+#  error DWARF_FRAME_REGISTERS is not defined.
+# endif
+#endif
+
+/* This is the register and unwind state for a particular frame. It
+   is used by the v2 dwarf2 frame unwind code.  */
+
+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];
+  long base_offset;
+  char indirect;
+} frame_state;
+
+/* The information we care about from a CIE. It is used by the v2
+   dwarf2 frame unwind code.  */
+
+struct cie_info {
+  char *augmentation;
+  void *eh_ptr;
+  void *pc;
+  int code_align;
+  int data_align;
+  unsigned ra_regno;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+};
+
+/* Convert the v3 frame into the v2 frame. It is used to unwind the v3
+   frame in the v2 unwinder.  */
+extern void _Unwind_GetFrameForV2 (void *pc_target,
+				   const unsigned char *insn, fde *f,
+				   struct dwarf_eh_bases *bases,
+				   struct frame_state *state,
+				   struct cie_info *info);
+#endif /* NEED__Unwind_GetFrameForV2 */
 
+#ifndef DWARF2_FRAME_UNWIND_V2
 /* Given an encoding, return the number of bytes the format occupies.
    This is only defined for fixed-size encodings, and so does not
    include leb128.  */
@@ -248,3 +315,4 @@ read_sleb128 (const unsigned char *p, _U
 {
   return read_encoded_value_with_base (DW_EH_PE_sleb128, 0, p, val);
 }
+#endif /* !DWARF2_FRAME_UNWIND_V2 */


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