PATCH: Share the dwarf2 unwind code between glibc and gcc 3.0
H . J . Lu
hjl@lucon.org
Sun Jul 8 19:45:00 GMT 2001
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 */
More information about the Libc-alpha
mailing list