From 82417da5f06061d684c325816bdb1b1f0075fbc4 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Sun, 21 Mar 2004 22:28:52 +0000 Subject: [PATCH] 2004-03-21 Andrew Cagney * 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.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. * 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. --- gdb/ChangeLog | 17 +++++++++++++++++ gdb/frame-unwind.c | 31 ++++++++++++++++++++++++++----- gdb/frame-unwind.h | 24 +++++++++++++++++++++--- gdb/frame.c | 20 +++++++++++++------- 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 53824f1d941..6bbe41593dd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2004-03-21 Andrew Cagney + + * 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.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. + * 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. + 2004-03-20 Paul Hilfinger * bcache.c (print_percentage): Use floating point to avoid diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index 1d340912dac..cacb2ed4160 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -31,6 +31,7 @@ static struct gdbarch_data *frame_unwind_data; 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 @@ frame_unwind_append_sniffer (struct gdbarch *gdbarch, 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 @@ frame_unwind_find_by_frame (struct frame_info *next_frame) 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; } diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index 8d17280fc9a..49f28896ffe 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -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 @@ struct regcache; 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 @@ struct frame_unwind 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 @@ extern void frame_unwind_append_sniffer (struct gdbarch *gdbarch, 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 diff --git a/gdb/frame.c b/gdb/frame.c index 1af200fe60b..7df7c43e296 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -228,7 +228,8 @@ get_frame_id (struct frame_info *fi) /* 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 @@ frame_register_unwind (struct frame_info *frame, int regnum, /* 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 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) /* 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 @@ legacy_get_prev_frame (struct frame_info *this_frame) /* 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 @@ legacy_get_prev_frame (struct frame_info *this_frame) 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 @@ legacy_get_prev_frame (struct frame_info *this_frame) 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 @@ get_frame_type (struct frame_info *frame) { /* 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 -- 2.30.2