diff options
-rw-r--r-- | gdb/ChangeLog | 31 | ||||
-rw-r--r-- | gdb/Makefile.in | 10 | ||||
-rw-r--r-- | gdb/dummy-frame.c | 33 | ||||
-rw-r--r-- | gdb/dummy-frame.h | 27 | ||||
-rw-r--r-- | gdb/frame-unwind.c | 103 | ||||
-rw-r--r-- | gdb/frame-unwind.h | 96 | ||||
-rw-r--r-- | gdb/frame.c | 59 | ||||
-rw-r--r-- | gdb/frame.h | 53 |
8 files changed, 293 insertions, 119 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c73c06d..e0f1231 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,36 @@ 2003-01-18 Andrew Cagney <ac131313@redhat.com> + * dummy-frame.h (dummy_frame_id_unwind): Delete declaration. + (dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto. + (struct frame_unwind): Declare opaque. + (dummy_frame_p): Declare function. + * dummy-frame.c (dummy_frame_id_unwind): Make static. + (dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto. + * dummy-frame.c: Include "frame-unwind.h". + (dummy_frame_p): New function. + (dummy_frame_unwind): New variable. + * frame.c: Include "frame-unwind.h". + (frame_pc_unwind, frame_id_unwind, frame_register_unwind): Update + to use the new unwind field. + (set_unwind_by_pc): Delete function. + (create_new_frame, get_prev_frame): Set unwind field using + frame_unwind_find_by_pc. + (trad_frame_unwind, trad_frame_unwinder): New variables. + * frame.h (trad_frame_unwind): Declare variable. + (frame_id_unwind_ftype): Delete declaration. + (frame_pc_unwind_ftype, frame_register_unwind_ftype): Ditto. + (struct frame_unwind): Declare opaque. + (struct frame_info): Replace the fields id_unwind, pc_unwind and + register_unwind with a single unwind pointer. + * frame-unwind.h, frame-unwind.c: New files. + * Makefile.in (SFILES): Add frame-unwind.c. + (frame_unwind_h): Define. + (COMMON_OBS): Add frame-unwind.o. + (frame-unwind.o): Specify dependencies. + (frame.o, dummy-frame.o): Update dependencies. + +2003-01-18 Andrew Cagney <ac131313@redhat.com> + * ada-valprint.c: Eliminate PTR. * breakpoint.c, corelow.c, cris-tdep.c, dbxread.c: Ditto. * defs.h, dve3900-rom.c, dwarf2read.c, dwarfread.c: Ditto. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index c0847dd..d23d48c 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -511,6 +511,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ dummy-frame.c dwarfread.c dwarf2read.c \ elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \ f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \ + frame-unwind.c \ gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \ hpacc-abi.c \ inf-loop.c infcmd.c inflow.c infrun.c \ @@ -623,6 +624,7 @@ event_top_h = event-top.h expression_h = expression.h $(symtab_h) $(doublest_h) f_lang_h = f-lang.h frame_h = frame.h +frame_unwind_h = frame-unwind.h gdb_events_h = gdb-events.h gdb_stabs_h = gdb-stabs.h gdb_h = gdb.h @@ -833,7 +835,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \ c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \ nlmread.o serial.o mdebugread.o top.o utils.o \ ui-file.o \ - frame.o doublest.o \ + frame.o frame-unwind.o doublest.o \ gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \ reggroups.o @@ -1636,7 +1638,7 @@ doublest.o: doublest.c $(defs_h) $(doublest_h) $(floatformat_h) \ dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) $(gdb_string_h) dsrec.o: dsrec.c $(defs_h) $(serial_h) $(srec_h) dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \ - $(frame_h) $(inferior_h) $(gdb_assert_h) + $(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h) dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ $(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h) dwarf2cfi.o: dwarf2cfi.c $(defs_h) $(gdbcore_h) $(symtab_h) $(symfile_h) \ @@ -1688,7 +1690,9 @@ fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \ frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \ $(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \ $(gdb_obstack_h) $(dummy_frame_h) $(gdbcore_h) $(annotate_h) \ - $(language_h) + $(language_h) $(frame_unwind_h) +frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \ + $(gdb_assert_h) $(dummy_frame_h) $(legacy_frame_h) frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \ $(arch_utils_h) $(regcache_h) gcore.o: gcore.c $(defs_h) $(cli_decode_h) $(inferior_h) $(gdbcore_h) \ diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index 99d388d..0a3e35e 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -28,6 +28,7 @@ #include "frame.h" #include "inferior.h" #include "gdb_assert.h" +#include "frame-unwind.h" /* Dummy frame. This saves the processor state just prior to setting up the inferior function call. Older targets save the registers @@ -304,7 +305,7 @@ generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, /* Given a call-dummy dummy-frame, return the registers. Here the register value is taken from the local copy of the register buffer. */ -void +static void dummy_frame_register_unwind (struct frame_info *frame, void **cache, int regnum, int *optimized, enum lval_type *lvalp, CORE_ADDR *addrp, @@ -331,7 +332,10 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache, } } -CORE_ADDR +/* Assuming that FRAME is a dummy, return the resume address for the + previous frame. */ + +static CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame, void **cache) { @@ -345,8 +349,12 @@ dummy_frame_pc_unwind (struct frame_info *frame, } -void -dummy_frame_id_unwind (struct frame_info *frame, void **cache, +/* Assuming that FRAME is a dummy, return the ID of the calling frame + (the frame that the dummy has the saved state of). */ + +static void +dummy_frame_id_unwind (struct frame_info *frame, + void **cache, struct frame_id *id) { struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); @@ -359,3 +367,20 @@ dummy_frame_id_unwind (struct frame_info *frame, void **cache, (*id) = dummy->id; } +static struct frame_unwind dummy_frame_unwind = +{ + dummy_frame_pc_unwind, + dummy_frame_id_unwind, + dummy_frame_register_unwind +}; + +const struct frame_unwind * +dummy_frame_p (CORE_ADDR pc) +{ + if (DEPRECATED_PC_IN_CALL_DUMMY_P () + ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0) + : pc_in_dummy_frame (pc)) + return &dummy_frame_unwind; + else + return NULL; +} diff --git a/gdb/dummy-frame.h b/gdb/dummy-frame.h index 746e663..2d03421 100644 --- a/gdb/dummy-frame.h +++ b/gdb/dummy-frame.h @@ -24,6 +24,7 @@ struct frame_info; struct regcache; +struct frame_unwind; struct frame_id; /* GENERIC DUMMY FRAMES @@ -43,30 +44,10 @@ struct frame_id; generic_{file,func}_frame_chain_valid and FIX_CALL_DUMMY as generic_fix_call_dummy. */ -/* Assuming that FRAME is a dummy, return a register value for the - previous frame. */ +/* If the PC falls in a dummy frame, return a dummy frame + unwinder. */ -extern void dummy_frame_register_unwind (struct frame_info *frame, - void **unwind_cache, - int regnum, - int *optimized, - enum lval_type *lvalp, - CORE_ADDR *addrp, - int *realnump, - void *valuep); - -/* Assuming that FRAME is a dummy, return the resume address for the - previous frame. */ - -extern CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame, - void **unwind_cache); - -/* Assuming that FRAME is a dummy, return the ID of the calling frame - (the frame that the dummy has the saved state of). */ - -extern void dummy_frame_id_unwind (struct frame_info *frame, - void **unwind_cache, - struct frame_id *id); +extern const struct frame_unwind *dummy_frame_p (CORE_ADDR pc); /* Does the PC fall in a dummy frame? diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c new file mode 100644 index 0000000..a889f95 --- /dev/null +++ b/gdb/frame-unwind.c @@ -0,0 +1,103 @@ +/* Definitions for frame unwinder, for GDB, the GNU debugger. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "frame.h" +#include "frame-unwind.h" +#include "gdb_assert.h" +#include "dummy-frame.h" + +static struct gdbarch_data *frame_unwind_data; + +struct frame_unwind_table +{ + frame_unwind_p_ftype **p; + int middle; + 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) +{ + table->p = xrealloc (table->p, ((table->nr + 1) + * sizeof (frame_unwind_p_ftype *))); + table->p[table->nr] = p; + table->nr++; +} + +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); + return table; +} + +static void +frame_unwind_free (struct gdbarch *gdbarch, void *data) +{ + struct frame_unwind_table *table = + gdbarch_data (gdbarch, frame_unwind_data); + xfree (table->p); + xfree (table); +} + +void +frame_unwind_append_predicate (struct gdbarch *gdbarch, + frame_unwind_p_ftype *p) +{ + 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, p); +} + +const struct frame_unwind * +frame_unwind_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + int i; + struct frame_unwind_table *table = + gdbarch_data (gdbarch, frame_unwind_data); + /* Seriously old code. Don't even try to use this new mechanism. */ + if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES) + return trad_frame_unwind; + for (i = 0; i < table->nr; i++) + { + const struct frame_unwind *desc = table->p[i] (pc); + if (desc != NULL) + return desc; + } + return trad_frame_unwind; +} + +void +_initialize_frame_unwind (void) +{ + frame_unwind_data = register_gdbarch_data (frame_unwind_init, + frame_unwind_free); +} diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h new file mode 100644 index 0000000..863f259 --- /dev/null +++ b/gdb/frame-unwind.h @@ -0,0 +1,96 @@ +/* Definitions for a frame unwinder, for GDB, the GNU debugger. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined (FRAME_UNWIND_H) +#define FRAME_UNWIND_H 1 + +struct frame_info; +struct frame_id; +struct frame_unwind; +struct gdbarch; +struct regcache; + +/* Return the frame unwind methods for the function that contains PC, + or NULL if this this unwinder can't handle this frame. */ + +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); + +/* Return the location (and possibly value) of REGNUM for the previous + (older, up) frame. All parameters except VALUEP can be assumed to + be non NULL. When VALUEP is NULL, just the location of the + register should be returned. + + UNWIND_CACHE is provided as mechanism for implementing a per-frame + local cache. It's initial value being NULL. Memory for that cache + should be allocated using frame_obstack_zalloc(). + + Register window architectures (eg SPARC) should note that REGNUM + identifies the register for the previous frame. For instance, a + request for the value of "o1" for the previous frame would be found + in the register "i1" in this FRAME. */ + +typedef void (frame_unwind_reg_ftype) (struct frame_info * frame, + void **unwind_cache, + int regnum, + int *optimized, + enum lval_type * lvalp, + CORE_ADDR *addrp, + int *realnump, void *valuep); + +/* Same as for registers above, but return the address at which the + calling frame would resume. */ + +typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info * frame, + void **unwind_cache); + +/* Same as for registers above, but return the ID of the frame that + called this one. */ + +typedef void (frame_unwind_id_ftype) (struct frame_info * frame, + void **unwind_cache, + struct frame_id * id); + + +struct frame_unwind +{ + /* Should the frame's type go here? */ + /* Should an attribute indicating the frame's address-in-block go + here? */ + frame_unwind_pc_ftype *pc; + frame_unwind_id_ftype *id; + frame_unwind_reg_ftype *reg; +}; + +#endif diff --git a/gdb/frame.c b/gdb/frame.c index 78811e4..f85b54a 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -34,6 +34,7 @@ #include "gdbcore.h" #include "annotate.h" #include "language.h" +#include "frame-unwind.h" /* Return a frame uniq ID that can be used to, later, re-find the frame. */ @@ -127,7 +128,7 @@ frame_pc_unwind (struct frame_info *frame) { if (!frame->pc_unwind_cache_p) { - frame->pc_unwind_cache = frame->pc_unwind (frame, &frame->unwind_cache); + frame->pc_unwind_cache = frame->unwind->pc (frame, &frame->unwind_cache); frame->pc_unwind_cache_p = 1; } return frame->pc_unwind_cache; @@ -138,7 +139,7 @@ frame_id_unwind (struct frame_info *frame) { if (!frame->id_unwind_cache_p) { - frame->id_unwind (frame, &frame->unwind_cache, &frame->id_unwind_cache); + frame->unwind->id (frame, &frame->unwind_cache, &frame->id_unwind_cache); frame->id_unwind_cache_p = 1; } return frame->id_unwind_cache; @@ -185,8 +186,8 @@ frame_register_unwind (struct frame_info *frame, int regnum, } /* Ask this frame to unwind its register. */ - frame->register_unwind (frame, &frame->unwind_cache, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + frame->unwind->reg (frame, &frame->unwind_cache, regnum, + optimizedp, lvalp, addrp, realnump, bufferp); } void @@ -714,6 +715,14 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache, id->base = base; } +const struct frame_unwind trad_frame_unwinder = { + frame_saved_regs_pc_unwind, + frame_saved_regs_id_unwind, + frame_saved_regs_register_unwind +}; +const struct frame_unwind *trad_frame_unwind = &trad_frame_unwinder; + + /* Function: get_saved_register Find register number REGNUM relative to FRAME and put its (raw, target format) contents in *RAW_BUFFER. @@ -813,42 +822,6 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized, deprecated_read_register_gen (regnum, raw_buffer); } -/* Using the PC, select a mechanism for unwinding a frame returning - the previous frame. The register unwind function should, on - demand, initialize the ->context object. */ - -static void -set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp, - frame_register_unwind_ftype **unwind_register, - frame_pc_unwind_ftype **unwind_pc, - frame_id_unwind_ftype **unwind_id) -{ - if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES) - { - /* Still need to set this to something. The ``info frame'' code - calls this function to find out where the saved registers are. - Hopefully this is robust enough to stop any core dumps and - return vaguely correct values.. */ - *unwind_register = frame_saved_regs_register_unwind; - *unwind_pc = frame_saved_regs_pc_unwind; - *unwind_id = frame_saved_regs_id_unwind; - } - else if (DEPRECATED_PC_IN_CALL_DUMMY_P () - ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0) - : pc_in_dummy_frame (pc)) - { - *unwind_register = dummy_frame_register_unwind; - *unwind_pc = dummy_frame_pc_unwind; - *unwind_id = dummy_frame_id_unwind; - } - else - { - *unwind_register = frame_saved_regs_register_unwind; - *unwind_pc = frame_saved_regs_pc_unwind; - *unwind_id = frame_saved_regs_id_unwind; - } -} - /* Create an arbitrary (i.e. address specified by user) or innermost frame. Always returns a non-NULL value. */ @@ -891,8 +864,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) INIT_EXTRA_FRAME_INFO (0, fi); /* Select/initialize an unwind function. */ - set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind, - &fi->pc_unwind, &fi->id_unwind); + fi->unwind = frame_unwind_find_by_pc (current_gdbarch, fi->pc); return fi; } @@ -1135,8 +1107,7 @@ get_prev_frame (struct frame_info *next_frame) (and probably other architectural information). The PC lets you check things like the debug info at that point (dwarf2cfi?) and use that to decide how the frame should be unwound. */ - set_unwind_by_pc (prev->pc, prev->frame, &prev->register_unwind, - &prev->pc_unwind, &prev->id_unwind); + prev->unwind = frame_unwind_find_by_pc (current_gdbarch, prev->pc); /* NOTE: cagney/2002-11-18: The code segments, found in create_new_frame and get_prev_frame(), that initializes the diff --git a/gdb/frame.h b/gdb/frame.h index 09df2b8..9cbdaa4 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -24,6 +24,10 @@ #define FRAME_H 1 struct symtab_and_line; +struct frame_unwind; + +/* The traditional frame unwinder. */ +extern const struct frame_unwind *trad_frame_unwind; /* The frame object. */ @@ -302,43 +306,6 @@ extern CORE_ADDR frame_pc_unwind (struct frame_info *frame); caller's frame. */ extern struct frame_id frame_id_unwind (struct frame_info *frame); - -/* Return the location (and possibly value) of REGNUM for the previous - (older, up) frame. All parameters except VALUEP can be assumed to - be non NULL. When VALUEP is NULL, just the location of the - register should be returned. - - UNWIND_CACHE is provided as mechanism for implementing a per-frame - local cache. It's initial value being NULL. Memory for that cache - should be allocated using frame_obstack_zalloc(). - - Register window architectures (eg SPARC) should note that REGNUM - identifies the register for the previous frame. For instance, a - request for the value of "o1" for the previous frame would be found - in the register "i1" in this FRAME. */ - -typedef void (frame_register_unwind_ftype) (struct frame_info *frame, - void **unwind_cache, - int regnum, - int *optimized, - enum lval_type *lvalp, - CORE_ADDR *addrp, - int *realnump, - void *valuep); - -/* Same as for registers above, but return the address at which the - calling frame would resume. */ - -typedef CORE_ADDR (frame_pc_unwind_ftype) (struct frame_info *frame, - void **unwind_cache); - -/* Same as for registers above, but return the ID of the frame that - called this one. */ - -typedef void (frame_id_unwind_ftype) (struct frame_info *frame, - void **unwind_cache, - struct frame_id *id); - /* Describe the saved registers of a frame. */ #if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS) @@ -426,18 +393,14 @@ struct frame_info better all agree as to the contents. */ void *unwind_cache; - /* See description above. The previous frame's registers. */ - frame_register_unwind_ftype *register_unwind; + /* The frame's unwinder. */ + const struct frame_unwind *unwind; - /* See description above. The previous frame's resume address. - Save the previous PC in a local cache. */ - frame_pc_unwind_ftype *pc_unwind; + /* Cached copy of the previous frame's resume address. */ int pc_unwind_cache_p; CORE_ADDR pc_unwind_cache; - /* See description above. The previous frame's resume address. - Save the previous PC in a local cache. */ - frame_id_unwind_ftype *id_unwind; + /* Cached copy of the previous frame's ID. */ int id_unwind_cache_p; struct frame_id id_unwind_cache; |