This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[patch/rfc] More generic unwinders
- From: Andrew Cagney <cagney at gnu dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Thu, 18 Mar 2004 17:46:17 -0500
- Subject: [patch/rfc] More generic unwinders
Hello,
This patch (based on my tramp branch) extends frame-unwind so that it is
easier to parameterize an unwinder with both static (unwind_data) and
dynamic (this_prologue_cache) information. It does this by adding a
"static" method (i.e., callable before an instance of the unwinder has
been created) to the frame_unwind object.
I've now managed to trim things back to the point where no existing code
is affected. With this in place it becomes possible to implement the
tramp frame.
I previously posted a draft version of this patch here:
http://sources.redhat.com/ml/gdb-patches/2004-03/msg00353.html
Baring comments, I'll look to commit in a few days,
Andrew
2004-03-17 Andrew Cagney <cagney@redhat.com>
* frame-unwind.h: Update copyright.
(struct frame_data): Add opaque declaration.
(frame_sniffer_ftype): Declare.
(struct frame_unwind): Add "unwind_data" and "sniffer".
(frame_unwind_register_unwinder): Declare.
(frame_unwind_find_by_frame): Add parameter "this_cache".
* frame-unwind.c (struct frame_unwind_table_entry): Add field
"unwinder".
(frame_unwind_register_unwinder): New function.
(frame_unwind_find_by_frame): Handle an unwind sniffer.
* frame.c (get_frame_id, create_new_frame, legacy_get_prev_frame)
(legacy_get_prev_frame, legacy_get_prev_frame)
(get_frame_type): Pass the prologue_cache to
frame_unwind_find_by_frame.
Index: frame-unwind.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.c,v
retrieving revision 1.10
diff -u -r1.10 frame-unwind.c
--- frame-unwind.c 15 Mar 2004 23:08:28 -0000 1.10
+++ frame-unwind.c 18 Mar 2004 22:29:48 -0000
@@ -31,6 +31,7 @@
struct frame_unwind_table_entry
{
frame_unwind_sniffer_ftype *sniffer;
+ const struct frame_unwind *unwinder;
struct frame_unwind_table_entry *next;
};
@@ -61,8 +62,19 @@
table->tail = &((*table->tail)->next);
}
+void
+frame_unwind_register_unwinder (struct gdbarch *gdbarch,
+ const struct frame_unwind *unwinder)
+{
+ struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
+ (*table->tail) = GDBARCH_OBSTACK_ZALLOC (gdbarch,
+ struct frame_unwind_table_entry);
+ (*table->tail)->unwinder = unwinder;
+ table->tail = &((*table->tail)->next);
+}
+
const struct frame_unwind *
-frame_unwind_find_by_frame (struct frame_info *next_frame)
+frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache)
{
int i;
struct gdbarch *gdbarch = get_frame_arch (next_frame);
@@ -76,10 +88,19 @@
return legacy_saved_regs_unwind;
for (entry = table->head; entry != NULL; entry = entry->next)
{
- const struct frame_unwind *desc;
- desc = entry->sniffer (next_frame);
- if (desc != NULL)
- return desc;
+ if (entry->sniffer != NULL)
+ {
+ const struct frame_unwind *desc = NULL;
+ desc = entry->sniffer (next_frame);
+ if (desc != NULL)
+ return desc;
+ }
+ if (entry->unwinder != NULL)
+ {
+ if (entry->unwinder->sniffer (entry->unwinder, next_frame,
+ this_cache))
+ return entry->unwinder;
+ }
}
return legacy_saved_regs_unwind;
}
Index: frame-unwind.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.h,v
retrieving revision 1.9
diff -u -r1.9 frame-unwind.h
--- frame-unwind.h 16 Jul 2003 22:29:13 -0000 1.9
+++ frame-unwind.h 18 Mar 2004 22:29:48 -0000
@@ -1,6 +1,6 @@
/* Definitions for a frame unwinder, for GDB, the GNU debugger.
- Copyright 2003 Free Software Foundation, Inc.
+ Copyright 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
@@ -22,6 +22,7 @@
#if !defined (FRAME_UNWIND_H)
#define FRAME_UNWIND_H 1
+struct frame_data;
struct frame_info;
struct frame_id;
struct frame_unwind;
@@ -42,6 +43,14 @@
as where this frame's prologue stores the previous frame's
registers. */
+/* Given the NEXT frame, take a wiff of THIS frame's registers (namely
+ the PC and attributes) and if SELF is the applicable unwinder,
+ return non-zero. Possibly also initialize THIS_PROLOGUE_CACHE. */
+
+typedef int (frame_sniffer_ftype) (const struct frame_unwind *self,
+ struct frame_info *next_frame,
+ void **this_prologue_cache);
+
/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
use the NEXT frame, and its register unwind method, to determine
the frame ID of THIS frame.
@@ -118,8 +127,16 @@
here? */
frame_this_id_ftype *this_id;
frame_prev_register_ftype *prev_register;
+ const struct frame_data *unwind_data;
+ frame_sniffer_ftype *sniffer;
};
+/* Register a frame unwinder, _appending_ it to the end of the search
+ list. */
+extern void frame_unwind_register_unwinder (struct gdbarch *gdbarch,
+ const struct frame_unwind *unwinder);
+
+
/* Given the NEXT frame, take a wiff of THIS frame's registers (namely
the PC and attributes) and if it is the applicable unwinder return
the unwind methods, or NULL if it is not. */
@@ -134,8 +151,9 @@
frame_unwind_sniffer_ftype *sniffer);
/* Iterate through the next frame's sniffers until one returns with an
- unwinder implementation. */
+ unwinder implementation. Possibly initialize THIS_CACHE. */
-extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *next_frame);
+extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *next_frame,
+ void **this_cache);
#endif
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.163
diff -u -r1.163 frame.c
--- frame.c 17 Mar 2004 23:43:36 -0000 1.163
+++ frame.c 18 Mar 2004 22:29:48 -0000
@@ -228,7 +228,8 @@
/* Find the unwinder. */
if (fi->unwind == NULL)
{
- fi->unwind = frame_unwind_find_by_frame (fi->next);
+ fi->unwind = frame_unwind_find_by_frame (fi->next,
+ &fi->prologue_cache);
/* FIXME: cagney/2003-04-02: Rather than storing the frame's
type in the frame, the unwinder's type should be returned
directly. Unfortunately, legacy code, called by
@@ -532,7 +533,8 @@
/* Find the unwinder. */
if (frame->unwind == NULL)
{
- frame->unwind = frame_unwind_find_by_frame (frame->next);
+ frame->unwind = frame_unwind_find_by_frame (frame->next,
+ &frame->prologue_cache);
/* FIXME: cagney/2003-04-02: Rather than storing the frame's
type in the frame, the unwinder's type should be returned
directly. Unfortunately, legacy code, called by
@@ -1191,7 +1193,7 @@
/* Select/initialize both the unwind function and the frame's type
based on the PC. */
- fi->unwind = frame_unwind_find_by_frame (fi->next);
+ fi->unwind = frame_unwind_find_by_frame (fi->next, &fi->prologue_cache);
if (fi->unwind->type != UNKNOWN_FRAME)
fi->type = fi->unwind->type;
else
@@ -1344,7 +1346,8 @@
/* Set the unwind functions based on that identified PC. Ditto
for the "type" but strongly prefer the unwinder's frame type. */
- prev->unwind = frame_unwind_find_by_frame (prev->next);
+ prev->unwind = frame_unwind_find_by_frame (prev->next,
+ &prev->prologue_cache);
if (prev->unwind->type == UNKNOWN_FRAME)
prev->type = frame_type_from_pc (get_frame_pc (prev));
else
@@ -1493,7 +1496,8 @@
to the new frame code. Implement FRAME_CHAIN the way the
new frame will. */
/* Find PREV frame's unwinder. */
- prev->unwind = frame_unwind_find_by_frame (this_frame);
+ prev->unwind = frame_unwind_find_by_frame (this_frame,
+ &prev->prologue_cache);
/* FIXME: cagney/2003-04-02: Rather than storing the frame's
type in the frame, the unwinder's type should be returned
directly. Unfortunately, legacy code, called by
@@ -1654,7 +1658,8 @@
If there isn't a FRAME_CHAIN, the code above will have already
done this. */
if (prev->unwind == NULL)
- prev->unwind = frame_unwind_find_by_frame (prev->next);
+ prev->unwind = frame_unwind_find_by_frame (prev->next,
+ &prev->prologue_cache);
/* If the unwinder provides a frame type, use it. Otherwize
continue on to that heuristic mess. */
@@ -2124,7 +2129,8 @@
{
/* Initialize the frame's unwinder because it is that which
provides the frame's type. */
- frame->unwind = frame_unwind_find_by_frame (frame->next);
+ frame->unwind = frame_unwind_find_by_frame (frame->next,
+ &frame->prologue_cache);
/* FIXME: cagney/2003-04-02: Rather than storing the frame's
type in the frame, the unwinder's type should be returned
directly. Unfortunately, legacy code, called by