From e8a89fe2788ee8bbcc84d7fb13d28f8b924318c4 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Tue, 15 Jul 2003 17:35:00 +0000 Subject: [PATCH] 2003-07-15 Andrew Cagney * frame.c (get_frame_id): Use frame_unwind_find_by_frame. (frame_register_unwind, create_new_frame): Ditto. (legacy_get_prev_frame, get_frame_type): Ditto. (get_frame_base_address): Use frame_base_find_by_frame. (get_frame_locals_address): Use frame_base_find_by_frame. (get_frame_args_address): Use frame_base_find_by_frame. * frame-base.h (frame_base_sniffer_ftype): Declare. (frame_base_append_sniffer): Declare. (frame_base_find_by_frame): Replace frame_base_find_by_pc. * frame-base.c (append_predicate): Add a "sniffer" parameter. (frame_base_append_sniffer): New function. (frame_base_append_predicate): Add a NULL sniffer. (frame_base_find_by_frame): Replace "frame_base_find_by_pc". (struct frame_base_table): Add "sniffer". (frame_base_free): Free the "sniffer" table. * frame-unwind.h (frame_unwind_sniffer_ftype): Define. (frame_unwind_append_sniffer): Declare. (frame_unwind_find_by_frame): Replace frame_unwind_find_by_pc. * frame-unwind.c (frame_unwind_free): Free the "sniffer" table. (struct frame_unwind_table): Add "sniffer", delete "middle". (append_predicate): Add "sniffer" parameter, append the sniffer. (frame_unwind_init): Update append_predicate call. (frame_unwind_append_sniffer): New function. (frame_unwind_append_predicate): Update append_predicate call. (frame_unwind_find_by_frame): Replace frame_unwind_find_by_pc. --- gdb/ChangeLog | 28 ++++++++++++++++++++++++++++ gdb/frame-base.c | 30 +++++++++++++++++++++++++----- gdb/frame-base.h | 43 ++++++++++++++++++++++++------------------- gdb/frame-unwind.c | 43 +++++++++++++++++++++++++++++++++++-------- gdb/frame-unwind.h | 35 ++++++++++++++++++++--------------- gdb/frame.c | 26 ++++++++++---------------- 6 files changed, 142 insertions(+), 63 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8973053..074cf45 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,33 @@ 2003-07-15 Andrew Cagney + * frame.c (get_frame_id): Use frame_unwind_find_by_frame. + (frame_register_unwind, create_new_frame): Ditto. + (legacy_get_prev_frame, get_frame_type): Ditto. + (get_frame_base_address): Use frame_base_find_by_frame. + (get_frame_locals_address): Use frame_base_find_by_frame. + (get_frame_args_address): Use frame_base_find_by_frame. + * frame-base.h (frame_base_sniffer_ftype): Declare. + (frame_base_append_sniffer): Declare. + (frame_base_find_by_frame): Replace frame_base_find_by_pc. + * frame-base.c (append_predicate): Add a "sniffer" parameter. + (frame_base_append_sniffer): New function. + (frame_base_append_predicate): Add a NULL sniffer. + (frame_base_find_by_frame): Replace "frame_base_find_by_pc". + (struct frame_base_table): Add "sniffer". + (frame_base_free): Free the "sniffer" table. + * frame-unwind.h (frame_unwind_sniffer_ftype): Define. + (frame_unwind_append_sniffer): Declare. + (frame_unwind_find_by_frame): Replace frame_unwind_find_by_pc. + * frame-unwind.c (frame_unwind_free): Free the "sniffer" table. + (struct frame_unwind_table): Add "sniffer", delete "middle". + (append_predicate): Add "sniffer" parameter, append the sniffer. + (frame_unwind_init): Update append_predicate call. + (frame_unwind_append_sniffer): New function. + (frame_unwind_append_predicate): Update append_predicate call. + (frame_unwind_find_by_frame): Replace frame_unwind_find_by_pc. + +2003-07-15 Andrew Cagney + * frame.c (get_prev_frame): Move disabled inside_entry_func to before code inhibiting repeated unwind attempts. Add to commentary on that test's problems. diff --git a/gdb/frame-base.c b/gdb/frame-base.c index 0865a0c..86d955b 100644 --- a/gdb/frame-base.c +++ b/gdb/frame-base.c @@ -71,6 +71,7 @@ static struct gdbarch_data *frame_base_data; struct frame_base_table { frame_base_p_ftype **p; + frame_base_sniffer_ftype **sniffer; const struct frame_base *default_base; int nr; }; @@ -89,6 +90,7 @@ frame_base_free (struct gdbarch *gdbarch, void *data) struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data); xfree (table->p); + xfree (table->sniffer); xfree (table); } @@ -108,11 +110,16 @@ frame_base_table (struct gdbarch *gdbarch) /* Append a predicate to the end of the table. */ static void -append_predicate (struct frame_base_table *table, frame_base_p_ftype *p) +append_predicate (struct frame_base_table *table, frame_base_p_ftype *p, + frame_base_sniffer_ftype *sniffer) { table->p = xrealloc (table->p, ((table->nr + 1) * sizeof (frame_base_p_ftype *))); + table->sniffer = xrealloc (table->sniffer, + ((table->nr + 1) + * sizeof (frame_base_sniffer_ftype *))); table->p[table->nr] = p; + table->sniffer[table->nr] = sniffer; table->nr++; } @@ -121,7 +128,15 @@ frame_base_append_predicate (struct gdbarch *gdbarch, frame_base_p_ftype *p) { struct frame_base_table *table = frame_base_table (gdbarch); - append_predicate (table, p); + append_predicate (table, p, NULL); +} + +void +frame_base_append_sniffer (struct gdbarch *gdbarch, + frame_base_sniffer_ftype *sniffer) +{ + struct frame_base_table *table = frame_base_table (gdbarch); + append_predicate (table, NULL, sniffer); } void @@ -133,13 +148,18 @@ frame_base_set_default (struct gdbarch *gdbarch, } const struct frame_base * -frame_base_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc) +frame_base_find_by_frame (struct frame_info *next_frame) { - int i; + struct gdbarch *gdbarch = get_frame_arch (next_frame); struct frame_base_table *table = frame_base_table (gdbarch); + int i; for (i = 0; i < table->nr; i++) { - const struct frame_base *desc = table->p[i] (pc); + const struct frame_base *desc = NULL; + if (table->p[i] != NULL) + desc = table->p[i] (frame_pc_unwind (next_frame)); + else if (table->sniffer[i] != NULL) + desc = table->sniffer[i] (next_frame); if (desc != NULL) return desc; } diff --git a/gdb/frame-base.h b/gdb/frame-base.h index 5e0d5db..7433c54 100644 --- a/gdb/frame-base.h +++ b/gdb/frame-base.h @@ -29,30 +29,12 @@ struct frame_base; struct gdbarch; struct regcache; -/* Return the frame base methods for the function that contains PC, or - NULL if it can't handle this frame. */ +/* For compatibility. */ typedef const struct frame_base *(frame_base_p_ftype) (CORE_ADDR pc); - -/* Add a frame base handler to the list. The predicates are polled in - the order that they are appended. */ - extern void frame_base_append_predicate (struct gdbarch *gdbarch, frame_base_p_ftype *p); -/* Set the default frame base. If all else fails, this one is - returned. If this isn't set, the default is to use legacy code - that uses things like the frame ID's base (ulgh!). */ - -extern void frame_base_set_default (struct gdbarch *gdbarch, - const struct frame_base *def); - -/* Iterate through the list of frame base handlers until one returns - an implementation. */ - -extern const struct frame_base *frame_base_find_by_pc (struct gdbarch *gdbarch, - CORE_ADDR pc); - /* Assuming the frame chain: (outer) prev <-> this <-> next (inner); and that this is a `normal frame'; use the NEXT frame, and its register unwind method, to determine the address of THIS frame's @@ -91,4 +73,27 @@ struct frame_base frame_this_args_ftype *this_args; }; +/* Given the NEXT frame, return the frame base methods for THIS frame, + or NULL if it can't handle THIS frame. */ + +typedef const struct frame_base *(frame_base_sniffer_ftype) (struct frame_info *next_frame); + +/* Append a frame base sniffer to the list. The sniffers are polled + in the order that they are appended. */ + +extern void frame_base_append_sniffer (struct gdbarch *gdbarch, + frame_base_sniffer_ftype *sniffer); + +/* Set the default frame base. If all else fails, this one is + returned. If this isn't set, the default is to use legacy code + that uses things like the frame ID's base (ulgh!). */ + +extern void frame_base_set_default (struct gdbarch *gdbarch, + const struct frame_base *def); + +/* Iterate through the list of frame base handlers until one returns + an implementation. */ + +extern const struct frame_base *frame_base_find_by_frame (struct frame_info *next_frame); + #endif diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index 921d30b..ed43cb3 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -30,17 +30,21 @@ static struct gdbarch_data *frame_unwind_data; struct frame_unwind_table { frame_unwind_p_ftype **p; - int middle; + frame_unwind_sniffer_ftype **sniffer; int nr; }; /* Append a predicate to the end of the table. */ static void -append_predicate (struct frame_unwind_table *table, frame_unwind_p_ftype *p) +append_predicate (struct frame_unwind_table *table, frame_unwind_p_ftype *p, + frame_unwind_sniffer_ftype *sniffer) { table->p = xrealloc (table->p, ((table->nr + 1) * sizeof (frame_unwind_p_ftype *))); + table->sniffer = xrealloc (table->sniffer, ((table->nr + 1) + * sizeof (frame_unwind_sniffer_ftype *))); table->p[table->nr] = p; + table->sniffer[table->nr] = sniffer; table->nr++; } @@ -48,7 +52,7 @@ static void * frame_unwind_init (struct gdbarch *gdbarch) { struct frame_unwind_table *table = XCALLOC (1, struct frame_unwind_table); - append_predicate (table, dummy_frame_p); + append_predicate (table, dummy_frame_p, NULL); return table; } @@ -58,6 +62,7 @@ frame_unwind_free (struct gdbarch *gdbarch, void *data) struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); xfree (table->p); + xfree (table->sniffer); xfree (table); } @@ -74,15 +79,31 @@ frame_unwind_append_predicate (struct gdbarch *gdbarch, table = frame_unwind_init (gdbarch); set_gdbarch_data (gdbarch, frame_unwind_data, table); } - append_predicate (table, p); + append_predicate (table, p, NULL); } -const struct frame_unwind * -frame_unwind_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc) +void +frame_unwind_append_sniffer (struct gdbarch *gdbarch, + frame_unwind_sniffer_ftype *sniffer) { - int i; struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); + if (table == NULL) + { + /* ULGH, called during architecture initialization. Patch + things up. */ + table = frame_unwind_init (gdbarch); + set_gdbarch_data (gdbarch, frame_unwind_data, table); + } + append_predicate (table, NULL, sniffer); +} + +const struct frame_unwind * +frame_unwind_find_by_frame (struct frame_info *next_frame) +{ + int i; + struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES) /* Seriously old code. Don't even try to use this new mechanism. (Note: The variable USE_GENERIC_DUMMY_FRAMES is deprecated, not @@ -91,7 +112,13 @@ frame_unwind_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc) return legacy_saved_regs_unwind; for (i = 0; i < table->nr; i++) { - const struct frame_unwind *desc = table->p[i] (pc); + const struct frame_unwind *desc; + if (table->p[i] != NULL) + desc = table->p[i] (frame_pc_unwind (next_frame)); + else if (table->sniffer[i] != NULL) + desc = table->sniffer[i] (next_frame); + else + internal_error (__FILE__, __LINE__, "Missing sniffer?"); if (desc != NULL) return desc; } diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index ad1efdf..80ce4b6 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -30,25 +30,12 @@ struct regcache; #include "frame.h" /* For enum frame_type. */ -/* Return the frame unwind methods for the function that contains PC, - or NULL if this this unwinder can't handle this frame. */ - +/* For compatibility with the old frame code. See end of header for + new methods. */ typedef const struct frame_unwind *(frame_unwind_p_ftype) (CORE_ADDR pc); - -/* Add a frame unwinder to the list. The predicates are polled in the - order that they are appended. The initial list contains the dummy - frame's predicate. */ - extern void frame_unwind_append_predicate (struct gdbarch *gdbarch, frame_unwind_p_ftype *p); -/* Iterate through the list of frame unwinders until one returns an - implementation. */ - -extern const struct frame_unwind *frame_unwind_find_by_pc (struct gdbarch - *gdbarch, - CORE_ADDR pc); - /* The following unwind functions assume a chain of frames forming the sequence: (outer) prev <-> this <-> next (inner). All the functions are called with called with the next frame's `struct @@ -139,4 +126,22 @@ struct frame_unwind frame_prev_register_ftype *prev_register; }; +/* 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. */ + +typedef const struct frame_unwind *(frame_unwind_sniffer_ftype) (struct frame_info *next_frame); + +/* Add a frame sniffer to the list. The predicates are polled in the + order that they are appended. The initial list contains the dummy + frame sniffer. */ + +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. */ + +extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *next_frame); + #endif diff --git a/gdb/frame.c b/gdb/frame.c index 73895e2..9b95e9c 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -229,8 +229,7 @@ get_frame_id (struct frame_info *fi) /* Find the unwinder. */ if (fi->unwind == NULL) { - fi->unwind = frame_unwind_find_by_pc (current_gdbarch, - get_frame_pc (fi)); + fi->unwind = frame_unwind_find_by_frame (fi->next); /* FIXME: cagney/2003-04-02: Rather than storing the frame's type in the frame, the unwinder's type should be returned directly. Unfortunatly, legacy code, called by @@ -517,8 +516,7 @@ frame_register_unwind (struct frame_info *frame, int regnum, /* Find the unwinder. */ if (frame->unwind == NULL) { - frame->unwind = frame_unwind_find_by_pc (current_gdbarch, - get_frame_pc (frame)); + frame->unwind = frame_unwind_find_by_frame (frame->next); /* FIXME: cagney/2003-04-02: Rather than storing the frame's type in the frame, the unwinder's type should be returned directly. Unfortunatly, legacy code, called by @@ -1206,7 +1204,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_pc (current_gdbarch, pc); + fi->unwind = frame_unwind_find_by_frame (fi->next); if (fi->unwind->type != UNKNOWN_FRAME) fi->type = fi->unwind->type; else @@ -1365,8 +1363,7 @@ 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_pc (current_gdbarch, - get_frame_pc (prev)); + prev->unwind = frame_unwind_find_by_frame (prev->next); if (prev->unwind->type == UNKNOWN_FRAME) prev->type = frame_type_from_pc (get_frame_pc (prev)); else @@ -1514,8 +1511,7 @@ 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_pc (current_gdbarch, - frame_pc_unwind (this_frame)); + prev->unwind = frame_unwind_find_by_frame (this_frame->next); /* FIXME: cagney/2003-04-02: Rather than storing the frame's type in the frame, the unwinder's type should be returned directly. Unfortunatly, legacy code, called by @@ -1676,8 +1672,7 @@ 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_pc (current_gdbarch, - get_frame_pc (prev)); + prev->unwind = frame_unwind_find_by_frame (prev->next); /* If the unwinder provides a frame type, use it. Otherwize continue on to that heuristic mess. */ @@ -2090,7 +2085,7 @@ get_frame_base_address (struct frame_info *fi) if (get_frame_type (fi) != NORMAL_FRAME) return 0; if (fi->base == NULL) - fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi)); + fi->base = frame_base_find_by_frame (fi->next); /* Sneaky: If the low-level unwind and high-level base code share a common unwinder, let them share the prologue cache. */ if (fi->base->unwind == fi->unwind) @@ -2106,7 +2101,7 @@ get_frame_locals_address (struct frame_info *fi) return 0; /* If there isn't a frame address method, find it. */ if (fi->base == NULL) - fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi)); + fi->base = frame_base_find_by_frame (fi->next); /* Sneaky: If the low-level unwind and high-level base code share a common unwinder, let them share the prologue cache. */ if (fi->base->unwind == fi->unwind) @@ -2124,7 +2119,7 @@ get_frame_args_address (struct frame_info *fi) return 0; /* If there isn't a frame address method, find it. */ if (fi->base == NULL) - fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi)); + fi->base = frame_base_find_by_frame (fi->next); /* Sneaky: If the low-level unwind and high-level base code share a common unwinder, let them share the prologue cache. */ if (fi->base->unwind == fi->unwind) @@ -2163,8 +2158,7 @@ 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_pc (current_gdbarch, - get_frame_pc (frame)); + frame->unwind = frame_unwind_find_by_frame (frame->next); /* FIXME: cagney/2003-04-02: Rather than storing the frame's type in the frame, the unwinder's type should be returned directly. Unfortunatly, legacy code, called by -- 2.7.4