Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.518 diff -u -r1.518 Makefile.in --- Makefile.in 28 Feb 2004 18:04:36 -0000 1.518 +++ Makefile.in 9 Mar 2004 22:44:58 -0000 @@ -541,6 +541,7 @@ stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \ target.c thread.c top.c tracepoint.c \ trad-frame.c \ + tramp-frame.c \ typeprint.c \ ui-out.c utils.c ui-file.h ui-file.c \ user-regs.c \ @@ -904,7 +905,8 @@ gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \ cp-namespace.o \ reggroups.o \ - trad-frame.o + trad-frame.o \ + tramp-frame.o TSOBS = inflow.o Index: dummy-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dummy-frame.c,v retrieving revision 1.27 diff -u -r1.27 dummy-frame.c --- dummy-frame.c 10 Oct 2003 00:28:43 -0000 1.27 +++ dummy-frame.c 9 Mar 2004 22:44:58 -0000 @@ -32,7 +32,8 @@ #include "command.h" #include "gdbcmd.h" -static void dummy_frame_this_id (struct frame_info *next_frame, +static void dummy_frame_this_id (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, struct frame_id *this_id); @@ -301,7 +302,8 @@ register value is taken from the local copy of the register buffer. */ static void -dummy_frame_prev_register (struct frame_info *next_frame, +dummy_frame_prev_register (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, int regnum, int *optimized, enum lval_type *lvalp, CORE_ADDR *addrp, @@ -312,7 +314,7 @@ /* Call the ID method which, if at all possible, will set the prologue cache. */ - dummy_frame_this_id (next_frame, this_prologue_cache, &id); + dummy_frame_this_id (self, next_frame, this_prologue_cache, &id); dummy = (*this_prologue_cache); gdb_assert (dummy != NULL); @@ -341,7 +343,8 @@ dummy cache is located and and saved in THIS_PROLOGUE_CACHE. */ static void -dummy_frame_this_id (struct frame_info *next_frame, +dummy_frame_this_id (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, struct frame_id *this_id) { @@ -400,7 +403,7 @@ (*this_id).stack_addr); } -static struct frame_unwind dummy_frame_unwind = +static const struct frame_unwind dummy_frame_unwind = { DUMMY_FRAME, dummy_frame_this_id, @@ -408,7 +411,8 @@ }; const struct frame_unwind * -dummy_frame_sniffer (struct frame_info *next_frame) +dummy_frame_sniffer (const struct frame_unwind_sniffer *self, + struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); if (DEPRECATED_PC_IN_CALL_DUMMY_P () Index: dummy-frame.h =================================================================== RCS file: /cvs/src/src/gdb/dummy-frame.h,v retrieving revision 1.12 diff -u -r1.12 dummy-frame.h --- dummy-frame.h 16 Jul 2003 22:29:13 -0000 1.12 +++ dummy-frame.h 9 Mar 2004 22:44:58 -0000 @@ -26,6 +26,7 @@ struct regcache; struct frame_unwind; struct frame_id; +struct frame_unwind_sniffer; /* GENERIC DUMMY FRAMES @@ -48,7 +49,8 @@ /* If the PC falls in a dummy frame, return a dummy frame unwinder. */ -extern const struct frame_unwind *dummy_frame_sniffer (struct frame_info *next_frame); +const struct frame_unwind *dummy_frame_sniffer (const struct frame_unwind_sniffer *self, + struct frame_info *next_frame); /* Does the PC fall in a dummy frame? Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.31 diff -u -r1.31 dwarf2-frame.c --- dwarf2-frame.c 16 Feb 2004 20:32:01 -0000 1.31 +++ dwarf2-frame.c 9 Mar 2004 22:44:59 -0000 @@ -730,7 +730,8 @@ } static void -dwarf2_frame_this_id (struct frame_info *next_frame, void **this_cache, +dwarf2_frame_this_id (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct dwarf2_frame_cache *cache = @@ -740,7 +741,8 @@ } static void -dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, +dwarf2_frame_prev_register (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) @@ -861,7 +863,8 @@ response to the "info frame" command. */ static CORE_ADDR -dwarf2_frame_base_address (struct frame_info *next_frame, void **this_cache) +dwarf2_frame_base_address (const struct frame_base *self, + struct frame_info *next_frame, void **this_cache) { struct dwarf2_frame_cache *cache = dwarf2_frame_cache (next_frame, this_cache); @@ -1608,6 +1611,6 @@ void _initialize_dwarf2_frame (void) { - dwarf2_frame_data = register_gdbarch_data (dwarf2_frame_init); + dwarf2_frame_data = register_gdbarch_data (NULL, dwarf2_frame_init); dwarf2_frame_objfile_data = register_objfile_data (); } Index: frame-base.c =================================================================== RCS file: /cvs/src/src/gdb/frame-base.c,v retrieving revision 1.8 diff -u -r1.8 frame-base.c --- frame-base.c 4 Aug 2003 22:24:44 -0000 1.8 +++ frame-base.c 9 Mar 2004 22:44:59 -0000 @@ -22,6 +22,7 @@ #include "defs.h" #include "frame-base.h" #include "frame.h" +#include "gdb_obstack.h" /* A default frame base implementations. If it wasn't for the old DEPRECATED_FRAME_LOCALS_ADDRESS and DEPRECATED_FRAME_ARGS_ADDRESS, @@ -29,14 +30,16 @@ really need to override this. */ static CORE_ADDR -default_frame_base_address (struct frame_info *next_frame, void **this_cache) +default_frame_base_address (const struct frame_base *self, + struct frame_info *next_frame, void **this_cache) { struct frame_info *this_frame = get_prev_frame (next_frame); return get_frame_base (this_frame); /* sigh! */ } static CORE_ADDR -default_frame_locals_address (struct frame_info *next_frame, void **this_cache) +default_frame_locals_address (const struct frame_base *self, + struct frame_info *next_frame, void **this_cache) { if (DEPRECATED_FRAME_LOCALS_ADDRESS_P ()) { @@ -45,21 +48,22 @@ struct frame_info *this_frame = get_prev_frame (next_frame); return DEPRECATED_FRAME_LOCALS_ADDRESS (this_frame); } - return default_frame_base_address (next_frame, this_cache); + return default_frame_base_address (self, next_frame, this_cache); } static CORE_ADDR -default_frame_args_address (struct frame_info *next_frame, void **this_cache) +default_frame_args_address (const struct frame_base *self, + struct frame_info *next_frame, void **this_cache) { if (DEPRECATED_FRAME_ARGS_ADDRESS_P ()) { struct frame_info *this_frame = get_prev_frame (next_frame); return DEPRECATED_FRAME_ARGS_ADDRESS (this_frame); } - return default_frame_base_address (next_frame, this_cache); + return default_frame_base_address (self, next_frame, this_cache); } -const struct frame_base default_frame_base = { +static const struct frame_base default_frame_base = { NULL, /* No parent. */ default_frame_base_address, default_frame_locals_address, @@ -68,60 +72,60 @@ static struct gdbarch_data *frame_base_data; +struct frame_base_table_entry +{ + const struct frame_base_sniffer *sniffer; + struct frame_base_table_entry *next; +}; + struct frame_base_table { - frame_base_sniffer_ftype **sniffer; + struct frame_base_table_entry *first; const struct frame_base *default_base; - int nr; }; static void * -frame_base_init (struct gdbarch *gdbarch) -{ - struct frame_base_table *table = XCALLOC (1, struct frame_base_table); - table->default_base = &default_frame_base; - return table; -} - -static struct frame_base_table * -frame_base_table (struct gdbarch *gdbarch) +frame_base_init (struct obstack *obstack) { - struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data); - if (table == NULL) - { - /* ULGH, called during architecture initialization. Patch - things up. */ - table = frame_base_init (gdbarch); - set_gdbarch_data (gdbarch, frame_base_data, table); - } - return table; + return OBSTACK_ZALLOC (obstack, struct frame_base_table); } /* Append a predicate to the end of the table. */ static void -append_predicate (struct frame_base_table *table, - frame_base_sniffer_ftype *sniffer) +append_predicate (struct gdbarch *gdbarch, + const struct frame_base_sniffer *sniffer) { - table->sniffer = xrealloc (table->sniffer, - ((table->nr + 1) - * sizeof (frame_base_sniffer_ftype *))); - table->sniffer[table->nr] = sniffer; - table->nr++; + struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data); + struct frame_base_table_entry **entry; + + for (entry = &table->first; (*entry) != NULL; entry = &(*entry)->next); + (*entry) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base_table_entry); + (*entry)->sniffer = sniffer; } 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, sniffer); + struct frame_base_sniffer *base_sniffer; + + base_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base_sniffer); + base_sniffer->sniffer = sniffer; + append_predicate (gdbarch, base_sniffer); +} + +void +frame_base_sniffer_append (struct gdbarch *gdbarch, + const struct frame_base_sniffer *sniffer) +{ + append_predicate (gdbarch, sniffer); } void frame_base_set_default (struct gdbarch *gdbarch, const struct frame_base *default_base) { - struct frame_base_table *table = frame_base_table (gdbarch); + struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data); table->default_base = default_base; } @@ -129,12 +133,14 @@ frame_base_find_by_frame (struct frame_info *next_frame) { 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++) + struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data); + struct frame_base_table_entry *entry; + + for (entry = table->first; entry != NULL; entry = entry->next) { - const struct frame_base *desc = NULL; - desc = table->sniffer[i] (next_frame); + const struct frame_base *desc; + + desc = entry->sniffer->sniffer (entry->sniffer, next_frame); if (desc != NULL) return desc; } @@ -146,5 +152,5 @@ void _initialize_frame_base (void) { - frame_base_data = register_gdbarch_data (frame_base_init); + frame_base_data = register_gdbarch_data (frame_base_init, NULL); } Index: frame-base.h =================================================================== RCS file: /cvs/src/src/gdb/frame-base.h,v retrieving revision 1.3 diff -u -r1.3 frame-base.h --- frame-base.h 16 Jul 2003 22:29:13 -0000 1.3 +++ frame-base.h 9 Mar 2004 22:44:59 -0000 @@ -22,6 +22,8 @@ #if !defined (FRAME_BASE_H) #define FRAME_BASE_H 1 +struct frame_base; +struct frame_base_sniffer; struct frame_info; struct frame_id; struct frame_unwind; @@ -44,17 +46,20 @@ /* A generic base address. */ -typedef CORE_ADDR (frame_this_base_ftype) (struct frame_info *next_frame, +typedef CORE_ADDR (frame_this_base_ftype) (const struct frame_base *self, + struct frame_info *next_frame, void **this_base_cache); /* The base address of the frame's local variables. */ -typedef CORE_ADDR (frame_this_locals_ftype) (struct frame_info *next_frame, +typedef CORE_ADDR (frame_this_locals_ftype) (const struct frame_base *self, + struct frame_info *next_frame, void **this_base_cache); /* The base address of the frame's arguments / parameters. */ -typedef CORE_ADDR (frame_this_args_ftype) (struct frame_info *next_frame, +typedef CORE_ADDR (frame_this_args_ftype) (const struct frame_base *self, + struct frame_info *next_frame, void **this_base_cache); struct frame_base @@ -65,18 +70,28 @@ frame_this_base_ftype *this_base; frame_this_locals_ftype *this_locals; frame_this_args_ftype *this_args; + struct frame_data *base_data; }; /* 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); +typedef const struct frame_base *(frame_base_sniffer_ftype) + (const struct frame_base_sniffer *self, + struct frame_info *next_frame); +struct frame_base_sniffer +{ + frame_base_sniffer_ftype *sniffer; + const struct frame_data *sniffer_data; +}; /* 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); +extern void frame_base_sniffer_append (struct gdbarch *gdbarch, + const struct frame_base_sniffer *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 Index: frame-unwind.c =================================================================== RCS file: /cvs/src/src/gdb/frame-unwind.c,v retrieving revision 1.8 diff -u -r1.8 frame-unwind.c --- frame-unwind.c 22 Feb 2004 17:08:42 -0000 1.8 +++ frame-unwind.c 9 Mar 2004 22:44:59 -0000 @@ -24,48 +24,59 @@ #include "frame-unwind.h" #include "gdb_assert.h" #include "dummy-frame.h" +#include "gdb_obstack.h" static struct gdbarch_data *frame_unwind_data; -struct frame_unwind_table +struct frame_unwind_table_entry { - frame_unwind_sniffer_ftype **sniffer; - int nr; + const struct frame_unwind_sniffer *sniffer; + struct frame_unwind_table_entry *next; }; -/* Append a predicate to the end of the table. */ -static void -append_predicate (struct frame_unwind_table *table, - frame_unwind_sniffer_ftype *sniffer) -{ - table->sniffer = xrealloc (table->sniffer, ((table->nr + 1) - * sizeof (frame_unwind_sniffer_ftype *))); - table->sniffer[table->nr] = sniffer; - table->nr++; -} +struct frame_unwind_table +{ + struct frame_unwind_table_entry *first; +}; static void * -frame_unwind_init (struct gdbarch *gdbarch) +frame_unwind_init (struct obstack *obstack) { - struct frame_unwind_table *table = XCALLOC (1, struct frame_unwind_table); - append_predicate (table, dummy_frame_sniffer); + struct frame_unwind_table *table; + struct frame_unwind_sniffer *dummy_sniffer; + + dummy_sniffer = OBSTACK_ZALLOC (obstack, struct frame_unwind_sniffer); + dummy_sniffer->sniffer = dummy_frame_sniffer; + + table = OBSTACK_ZALLOC (obstack, struct frame_unwind_table); + table->first = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry); + table->first->sniffer = dummy_sniffer; + return table; } +/* Append a predicate to the end of the table. */ + +void +frame_unwind_sniffer_append (struct gdbarch *gdbarch, + const struct frame_unwind_sniffer *sniffer) +{ + struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); + struct frame_unwind_table_entry **entry; + for (entry = &table->first; (*entry) != NULL; entry = &(*entry)->next); + (*entry) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry); + (*entry)->sniffer = sniffer; +} + void frame_unwind_append_sniffer (struct gdbarch *gdbarch, frame_unwind_sniffer_ftype *sniffer) { - 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, sniffer); + struct frame_unwind_sniffer *unwind_sniffer; + + unwind_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_sniffer); + unwind_sniffer->sniffer = sniffer; + frame_unwind_sniffer_append (gdbarch, unwind_sniffer); } const struct frame_unwind * @@ -74,16 +85,18 @@ int i; struct gdbarch *gdbarch = get_frame_arch (next_frame); struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); + struct frame_unwind_table_entry *entry; if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES && legacy_frame_p (gdbarch)) /* Seriously old code. Don't even try to use this new mechanism. (Note: The variable USE_GENERIC_DUMMY_FRAMES is deprecated, not the dummy frame mechanism. All architectures should be using generic dummy frames). */ return legacy_saved_regs_unwind; - for (i = 0; i < table->nr; i++) + for (entry = table->first; entry != NULL; entry = entry->next) { const struct frame_unwind *desc; - desc = table->sniffer[i] (next_frame); + gdb_assert (entry->sniffer->sniffer != NULL); + desc = entry->sniffer->sniffer (entry->sniffer, next_frame); if (desc != NULL) return desc; } @@ -95,5 +108,5 @@ void _initialize_frame_unwind (void) { - frame_unwind_data = register_gdbarch_data (frame_unwind_init); + frame_unwind_data = register_gdbarch_data (frame_unwind_init, NULL); } 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 9 Mar 2004 22:44:59 -0000 @@ -65,7 +65,8 @@ with the other unwind methods. Memory for that cache should be allocated using frame_obstack_zalloc(). */ -typedef void (frame_this_id_ftype) (struct frame_info *next_frame, +typedef void (frame_this_id_ftype) (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, struct frame_id *this_id); @@ -101,13 +102,15 @@ with the other unwind methods. Memory for that cache should be allocated using frame_obstack_zalloc(). */ -typedef void (frame_prev_register_ftype) (struct frame_info *next_frame, - void **this_prologue_cache, - int prev_regnum, - int *optimized, - enum lval_type * lvalp, - CORE_ADDR *addrp, - int *realnump, void *valuep); +typedef void (frame_prev_register_ftype) + (const struct frame_unwind *self, + struct frame_info *next_frame, + void **this_prologue_cache, + int prev_regnum, + int *optimized, + enum lval_type * lvalp, + CORE_ADDR *addrp, + int *realnump, void *valuep); struct frame_unwind { @@ -118,20 +121,33 @@ here? */ frame_this_id_ftype *this_id; frame_prev_register_ftype *prev_register; + const struct frame_data *unwind_data; }; /* 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); +struct frame_unwind_sniffer; + +typedef const struct frame_unwind *(frame_unwind_sniffer_ftype) + (const struct frame_unwind_sniffer *self, + struct frame_info *next_frame); + +struct frame_unwind_sniffer +{ + frame_unwind_sniffer_ftype *sniffer; + const struct frame_data *sniffer_data; +}; /* 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); +void frame_unwind_append_sniffer (struct gdbarch *gdbarch, + frame_unwind_sniffer_ftype *sniffer); +void frame_unwind_sniffer_append (struct gdbarch *gdbarch, + const struct frame_unwind_sniffer *sniffer); /* Iterate through the next frame's sniffers until one returns with an unwinder implementation. */ Index: frame.c =================================================================== RCS file: /cvs/src/src/gdb/frame.c,v retrieving revision 1.162 diff -u -r1.162 frame.c --- frame.c 16 Feb 2004 21:49:21 -0000 1.162 +++ frame.c 9 Mar 2004 22:44:59 -0000 @@ -237,7 +237,8 @@ fi->type = fi->unwind->type; } /* Find THIS frame's ID. */ - fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->this_id.value); + fi->unwind->this_id (fi->unwind, fi->next, &fi->prologue_cache, + &fi->this_id.value); fi->this_id.p = 1; if (frame_debug) { @@ -429,7 +430,7 @@ } CORE_ADDR -frame_func_unwind (struct frame_info *fi) +frame_unwind_func_by_symtab (struct frame_info *fi) { if (!fi->prev_func.p) { @@ -447,6 +448,12 @@ } CORE_ADDR +frame_func_unwind (struct frame_info *fi) +{ + return frame_unwind_func_by_symtab (fi); +} + +CORE_ADDR get_frame_func (struct frame_info *fi) { return frame_func_unwind (fi->next); @@ -544,7 +551,8 @@ /* Ask this frame to unwind its register. See comment in "frame-unwind.h" for why NEXT frame and this unwind cace are passed in. */ - frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum, + frame->unwind->prev_register (frame->unwind, frame->next, + &frame->prologue_cache, regnum, optimizedp, lvalp, addrp, realnump, bufferp); if (frame_debug) @@ -938,7 +946,8 @@ most frame. */ static void -legacy_saved_regs_prev_register (struct frame_info *next_frame, +legacy_saved_regs_prev_register (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, @@ -1024,7 +1033,8 @@ } static void -legacy_saved_regs_this_id (struct frame_info *next_frame, +legacy_saved_regs_this_id (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, struct frame_id *id) { @@ -1444,7 +1454,8 @@ /* Still don't want to worry about this except on the innermost frame. This macro will set FROMLEAF if THIS_FRAME is a frameless function invocation. */ - if (this_frame->level == 0) + if (this_frame->level == 0 + && this_frame->unwind->type == UNKNOWN_FRAME) /* FIXME: 2002-11-09: Frameless functions can occure anywhere in the frame chain, not just the inner most frame! The generic, per-architecture, frame code should handle this and the below @@ -1485,7 +1496,8 @@ this to after the ffi test; I'd rather have backtraces from start go curfluy than have an abort called from main not show main. */ - if (DEPRECATED_FRAME_CHAIN_P ()) + if (DEPRECATED_FRAME_CHAIN_P () + && this_frame->unwind->type == UNKNOWN_FRAME) address = DEPRECATED_FRAME_CHAIN (this_frame); else { @@ -1501,7 +1513,7 @@ using the method deprecated_set_frame_type(). */ prev->type = prev->unwind->type; /* Find PREV frame's ID. */ - prev->unwind->this_id (this_frame, + prev->unwind->this_id (prev->unwind, this_frame, &prev->prologue_cache, &prev->this_id.value); prev->this_id.p = 1; @@ -1656,10 +1668,25 @@ if (prev->unwind == NULL) 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. */ - if (prev->unwind->type != UNKNOWN_FRAME) + /* If the unwinder provides a frame type (i.e., is a new style + unwinder), use it. Otherwize continue on to that heuristic + mess. */ + switch (prev->unwind->type) { + case SIGTRAMP_FRAME: + prev->type = prev->unwind->type; + prev->unwind->this_id (prev->unwind, prev->next, + &prev->prologue_cache, + &prev->this_id.value); + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, prev); + fprintf_unfiltered (gdb_stdlog, " } // legacy with sigtramp type\n"); + } + return prev; + case DUMMY_FRAME: + case NORMAL_FRAME: prev->type = prev->unwind->type; if (prev->type == NORMAL_FRAME) /* FIXME: cagney/2003-06-16: would get_frame_pc() be better? */ @@ -1672,6 +1699,10 @@ fprintf_unfiltered (gdb_stdlog, " } // legacy with unwound type\n"); } return prev; + case UNKNOWN_FRAME: + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); } /* NOTE: cagney/2002-11-18: The code segments, found in @@ -2055,8 +2086,8 @@ /* 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) - return fi->base->this_base (fi->next, &fi->prologue_cache); - return fi->base->this_base (fi->next, &fi->base_cache); + return fi->base->this_base (fi->base, fi->next, &fi->prologue_cache); + return fi->base->this_base (fi->base, fi->next, &fi->base_cache); } CORE_ADDR @@ -2074,7 +2105,7 @@ cache = &fi->prologue_cache; else cache = &fi->base_cache; - return fi->base->this_locals (fi->next, cache); + return fi->base->this_locals (fi->base, fi->next, cache); } CORE_ADDR @@ -2092,7 +2123,7 @@ cache = &fi->prologue_cache; else cache = &fi->base_cache; - return fi->base->this_args (fi->next, cache); + return fi->base->this_args (fi->base, fi->next, cache); } /* Level of the selected frame: 0 for innermost, 1 for its caller, ... Index: frame.h =================================================================== RCS file: /cvs/src/src/gdb/frame.h,v retrieving revision 1.119 diff -u -r1.119 frame.h --- frame.h 16 Feb 2004 21:49:21 -0000 1.119 +++ frame.h 9 Mar 2004 22:44:59 -0000 @@ -260,6 +260,7 @@ /* Following on from the `resume' address. Return the entry point address of the function containing that resume address, or zero if that function isn't known. */ +extern CORE_ADDR frame_unwind_func_by_symtab (struct frame_info *fi); extern CORE_ADDR frame_func_unwind (struct frame_info *fi); extern CORE_ADDR get_frame_func (struct frame_info *fi); Index: gdb_obstack.h =================================================================== RCS file: /cvs/src/src/gdb/gdb_obstack.h,v retrieving revision 1.2 diff -u -r1.2 gdb_obstack.h --- gdb_obstack.h 9 Feb 2004 23:50:55 -0000 1.2 +++ gdb_obstack.h 9 Mar 2004 22:44:59 -0000 @@ -24,6 +24,10 @@ #include "obstack.h" +#define OBSTACK_ZALLOC(OBSTACK,TYPE) (memset (obstack_alloc ((OBSTACK), sizeof (TYPE)), 0, sizeof (TYPE))) + +#define OBSTACK_CALLOC(OBSTACK,NUMBER,TYPE) (memset (obstack_alloc ((OBSTACK), (NUMBER) * sizeof (TYPE)), 0, (NUMBER) * sizeof (TYPE))) + /* Unless explicitly specified, GDB obstacks always use xmalloc() and xfree(). */ /* Note: ezannoni 2004-02-09: One could also specify the allocation Index: gdbarch.c =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.c,v retrieving revision 1.275 diff -u -r1.275 gdbarch.c --- gdbarch.c 16 Feb 2004 21:49:21 -0000 1.275 +++ gdbarch.c 9 Mar 2004 22:44:59 -0000 @@ -5382,7 +5382,8 @@ { unsigned index; int init_p; - gdbarch_data_init_ftype *init; + gdbarch_data_pre_init_ftype *pre_init; + gdbarch_data_post_init_ftype *post_init; }; struct gdbarch_data_registration @@ -5403,10 +5404,12 @@ }; struct gdbarch_data * -register_gdbarch_data (gdbarch_data_init_ftype *init) +register_gdbarch_data (gdbarch_data_pre_init_ftype *pre_init, + gdbarch_data_post_init_ftype *post_init) { struct gdbarch_data_registration **curr; /* Append the new registraration. */ + gdb_assert ((pre_init != NULL) != (post_init != NULL)); for (curr = &gdbarch_data_registry.registrations; (*curr) != NULL; curr = &(*curr)->next); @@ -5414,7 +5417,8 @@ (*curr)->next = NULL; (*curr)->data = XMALLOC (struct gdbarch_data); (*curr)->data->index = gdbarch_data_registry.nr++; - (*curr)->data->init = init; + (*curr)->data->pre_init = pre_init; + (*curr)->data->post_init = post_init; (*curr)->data->init_p = 1; return (*curr)->data; } @@ -5450,23 +5454,23 @@ gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data) { gdb_assert (data->index < gdbarch->nr_data); - /* The data-pointer isn't initialized, call init() to get a value but - only if the architecture initializaiton has completed. Otherwise - punt - hope that the caller knows what they are doing. */ - if (gdbarch->data[data->index] == NULL - && gdbarch->initialized_p) + if (gdbarch->data[data->index] == NULL) { /* Be careful to detect an initialization cycle. */ gdb_assert (data->init_p); data->init_p = 0; - gdb_assert (data->init != NULL); - gdbarch->data[data->index] = data->init (gdbarch); + if (data->pre_init != NULL) + gdbarch->data[data->index] = data->pre_init (gdbarch->obstack); + else if (gdbarch->initialized_p + && data->post_init != NULL) + gdbarch->data[data->index] = data->post_init (gdbarch); + else + internal_error (__FILE__, __LINE__, "Bad initialization method"); data->init_p = 1; gdb_assert (gdbarch->data[data->index] != NULL); } return gdbarch->data[data->index]; } - /* Keep a registry of swapped data required by GDB modules. */ Index: gdbarch.h =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.h,v retrieving revision 1.238 diff -u -r1.238 gdbarch.h --- gdbarch.h 16 Feb 2004 21:49:21 -0000 1.238 +++ gdbarch.h 9 Mar 2004 22:44:59 -0000 @@ -48,6 +48,7 @@ struct regset; struct disassemble_info; struct target_ops; +struct obstack; extern struct gdbarch *current_gdbarch; @@ -2534,11 +2535,13 @@ struct gdbarch_data; -typedef void *(gdbarch_data_init_ftype) (struct gdbarch *gdbarch); -extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_init_ftype *init); +typedef void *(gdbarch_data_pre_init_ftype) (struct obstack *obstack); +typedef void *(gdbarch_data_post_init_ftype) (struct gdbarch *gdbarch); +extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_pre_init_ftype *pre, + gdbarch_data_post_init_ftype *post); extern void set_gdbarch_data (struct gdbarch *gdbarch, - struct gdbarch_data *data, - void *pointer); + struct gdbarch_data *data, + void *pointer); extern void *gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *); Index: gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.301 diff -u -r1.301 gdbarch.sh --- gdbarch.sh 16 Feb 2004 21:49:21 -0000 1.301 +++ gdbarch.sh 9 Mar 2004 22:44:59 -0000 @@ -890,6 +890,7 @@ struct regset; struct disassemble_info; struct target_ops; +struct obstack; extern struct gdbarch *current_gdbarch; @@ -1218,11 +1219,13 @@ struct gdbarch_data; -typedef void *(gdbarch_data_init_ftype) (struct gdbarch *gdbarch); -extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_init_ftype *init); +typedef void *(gdbarch_data_pre_init_ftype) (struct obstack *obstack); +typedef void *(gdbarch_data_post_init_ftype) (struct gdbarch *gdbarch); +extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_pre_init_ftype *pre, + gdbarch_data_post_init_ftype *post); extern void set_gdbarch_data (struct gdbarch *gdbarch, - struct gdbarch_data *data, - void *pointer); + struct gdbarch_data *data, + void *pointer); extern void *gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *); Index: gnu-v3-abi.c =================================================================== RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v retrieving revision 1.20 diff -u -r1.20 gnu-v3-abi.c --- gnu-v3-abi.c 5 Dec 2003 04:25:09 -0000 1.20 +++ gnu-v3-abi.c 9 Mar 2004 22:44:59 -0000 @@ -422,7 +422,7 @@ static void init_gnuv3_ops (void) { - vtable_type_gdbarch_data = register_gdbarch_data (build_gdb_vtable_type); + vtable_type_gdbarch_data = register_gdbarch_data (NULL, build_gdb_vtable_type); gnu_v3_abi_ops.shortname = "gnu-v3"; gnu_v3_abi_ops.longname = "GNU G++ Version 3 ABI"; Index: ppcnbsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v retrieving revision 1.11 diff -u -r1.11 ppcnbsd-tdep.c --- ppcnbsd-tdep.c 10 Nov 2003 22:47:28 -0000 1.11 +++ ppcnbsd-tdep.c 9 Mar 2004 22:44:59 -0000 @@ -30,6 +30,8 @@ #include "ppc-tdep.h" #include "ppcnbsd-tdep.h" #include "nbsd-tdep.h" +#include "tramp-frame.h" +#include "trad-frame.h" #include "solib-svr4.h" @@ -228,6 +230,57 @@ } static void +ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + CORE_ADDR offset; + int i; + struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + this_cache->this_base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); + offset = this_cache->this_base + 0x18 + 2 * tdep->wordsize; + for (i = 0; i < 32; i++) + { + int regnum = i + tdep->ppc_gp0_regnum; + this_cache->prev_regs[regnum].addr = offset; + offset += tdep->wordsize; + } + this_cache->prev_regs[tdep->ppc_lr_regnum].addr = offset; + offset += tdep->wordsize; + this_cache->prev_regs[tdep->ppc_cr_regnum].addr = offset; + offset += tdep->wordsize; + this_cache->prev_regs[tdep->ppc_xer_regnum].addr = offset; + offset += tdep->wordsize; + this_cache->prev_regs[tdep->ppc_ctr_regnum].addr = offset; + offset += tdep->wordsize; + this_cache->prev_regs[PC_REGNUM].addr = offset; /* SRR0? */ + offset += tdep->wordsize; + + /* Construct the frame ID using the function start. */ + this_cache->this_id = frame_id_build (this_cache->this_base, func); +} + +/* Given the NEXTE frame, examine the instructions at and around this + frame's resume address (aka PC) to see of they look like a signal + trampoline. Return the address of the trampolines first + instruction, or zero if it isn't a signal trampoline. */ + +static const struct tramp_frame ppcnbsd_sigtramp = { + 4, /* insn size */ + { /* insn */ + 0x38610018, /* addi r3,r1,24 */ + 0x38000127, /* li r0,295 */ + 0x44000002, /* sc */ + 0x38000001, /* li r0,1 */ + 0x44000002, /* sc */ + }, + ppcnbsd_sigtramp_cache_init +}; + +static void ppcnbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -237,6 +290,7 @@ set_gdbarch_return_value (gdbarch, ppcnbsd_return_value); set_solib_svr4_fetch_link_map_offsets (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets); + tramp_frame_append (gdbarch, &ppcnbsd_sigtramp); } void Index: regcache.c =================================================================== RCS file: /cvs/src/src/gdb/regcache.c,v retrieving revision 1.109 diff -u -r1.109 regcache.c --- regcache.c 29 Feb 2004 17:01:38 -0000 1.109 +++ regcache.c 9 Mar 2004 22:44:59 -0000 @@ -1705,7 +1705,7 @@ void _initialize_regcache (void) { - regcache_descr_handle = register_gdbarch_data (init_regcache_descr); + regcache_descr_handle = register_gdbarch_data (NULL, init_regcache_descr); DEPRECATED_REGISTER_GDBARCH_SWAP (current_regcache); DEPRECATED_REGISTER_GDBARCH_SWAP (deprecated_registers); DEPRECATED_REGISTER_GDBARCH_SWAP (deprecated_register_valid); Index: reggroups.c =================================================================== RCS file: /cvs/src/src/gdb/reggroups.c,v retrieving revision 1.8 diff -u -r1.8 reggroups.c --- reggroups.c 22 Aug 2003 09:49:01 -0000 1.8 +++ reggroups.c 9 Mar 2004 22:44:59 -0000 @@ -268,7 +268,7 @@ void _initialize_reggroup (void) { - reggroups_data = register_gdbarch_data (reggroups_init); + reggroups_data = register_gdbarch_data (NULL, reggroups_init); /* The pre-defined list of groups. */ add_group (&default_groups, general_reggroup, XMALLOC (struct reggroup_el)); Index: remote.c =================================================================== RCS file: /cvs/src/src/gdb/remote.c,v retrieving revision 1.130 diff -u -r1.130 remote.c --- remote.c 25 Feb 2004 20:41:00 -0000 1.130 +++ remote.c 9 Mar 2004 22:45:00 -0000 @@ -5456,7 +5456,7 @@ struct cmd_list_element *tmpcmd; /* architecture specific data */ - remote_gdbarch_data_handle = register_gdbarch_data (init_remote_state); + remote_gdbarch_data_handle = register_gdbarch_data (NULL, init_remote_state); /* Old tacky stuff. NOTE: This comes after the remote protocol so that the remote protocol has been initialized. */ Index: rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.183 diff -u -r1.183 rs6000-tdep.c --- rs6000-tdep.c 2 Mar 2004 02:20:25 -0000 1.183 +++ rs6000-tdep.c 9 Mar 2004 22:45:00 -0000 @@ -50,6 +50,10 @@ #include "gdb_assert.h" #include "dis-asm.h" +#include "trad-frame.h" +#include "frame-unwind.h" +#include "frame-base.h" + /* If the kernel has to deliver a signal, it pushes a sigcontext structure on the stack and then calls the signal handler, passing the address of the sigcontext in an argument register. Usually @@ -65,6 +69,7 @@ struct rs6000_framedata { + CORE_ADDR func_start; /* true function start */ int offset; /* total size of frame --- the distance by which we decrement sp to allocate the frame */ @@ -502,6 +507,7 @@ int minimal_toc_loaded = 0; int prev_insn_was_prologue_insn = 1; int num_skip_non_prologue_insns = 0; + int num_skip_syscall_insn = 0; const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch); struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); @@ -521,6 +527,7 @@ lim_pc = refine_prologue_limit (pc, lim_pc); memset (fdata, 0, sizeof (struct rs6000_framedata)); + fdata->func_start = pc; fdata->saved_gpr = -1; fdata->saved_fpr = -1; fdata->saved_vr = -1; @@ -549,9 +556,65 @@ break; op = extract_signed_integer (buf, 4); + /* A PPC64 GNU/Linux system call function starts with a + non-threaded fast-path, only when that fails is a stack frame + created, treat it as several functions: + + *INDENT-OFF* + NAME: + SINGLE_THREAD_P + bne- .Lpseudo_cancel + __NAME_nocancel: + li r0,162 + sc + bnslr+ + b 0x7fe014ef64 <.__syscall_error> + Lpseudo_cancel: + stdu r1,-128(r1) + ... + *INDENT-ON* */ + if (((op & 0xffff0000) == 0x38000000 /* li r0,N */ + && pc == fdata->func + 0) + || (op == 0x44000002 /* sc */ + && pc == fdata->func + 4 + && num_skip_syscall_insn == 1) + || (op == 0x4ca30020 /* bnslr+ */ + && pc == fdata->func + 8 + && num_skip_syscall_insn == 2)) + { + num_skip_syscall_insn++; + continue; + } + else if ((op & 0xfc000003) == 0x48000000 /* b __syscall_error */ + && pc == fdata->func + 12 + && num_skip_syscall_insn == 3) + { + num_skip_syscall_insn++; + fdata->func_start = pc; + continue; + } + if ((op & 0xfc1fffff) == 0x7c0802a6) { /* mflr Rx */ - lr_reg = (op & 0x03e00000); + /* Since shared library / PIC code, which needs to get its + address at runtime, can appear to save more than one link + register vis: + + *INDENT-OFF* + stwu r1,-304(r1) + mflr r3 + bl 0xff570d0 (blrl) + stw r30,296(r1) + mflr r30 + stw r31,300(r1) + stw r3,308(r1); + ... + *INDENT-ON* + + remember just the first one, but skip over additional + ones. */ + if (lr_reg < 0) + lr_reg = (op & 0x03e00000); continue; } @@ -1862,12 +1925,12 @@ case 0: return builtin_type_int0; case 4: - return builtin_type_int32; + return builtin_type_uint32; case 8: if (tdep->ppc_ev0_regnum <= n && n <= tdep->ppc_ev31_regnum) return builtin_type_vec64; else - return builtin_type_int64; + return builtin_type_uint64; break; case 16: return builtin_type_vec128; @@ -2622,6 +2685,164 @@ return print_insn_little_powerpc (memaddr, info); } +static CORE_ADDR +rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + return frame_unwind_register_unsigned (next_frame, PC_REGNUM); +} + +static struct frame_id +rs6000_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + return frame_id_build (frame_unwind_register_unsigned (next_frame, + SP_REGNUM), + frame_pc_unwind (next_frame)); +} + +static void +rs6000_trad_frame_init (const struct trad_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct rs6000_framedata fdata; + CORE_ADDR base; + int wordsize = tdep->wordsize; + + skip_prologue (frame_unwind_func_by_symtab (next_frame), + frame_pc_unwind (next_frame), &fdata); + + /* If there were any saved registers, figure out parent's stack + pointer. */ + /* The following is true only if the frame doesn't have a call to + alloca(), FIXME. */ + + if (fdata.saved_fpr == 0 + && fdata.saved_gpr == 0 + && fdata.saved_vr == 0 + && fdata.saved_ev == 0 + && fdata.lr_offset == 0 + && fdata.cr_offset == 0 + && fdata.vr_offset == 0 + && fdata.ev_offset == 0) + base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); + else + { + /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most + address of the current frame. Things might be easier if the + ->frame pointed to the outer-most address of the frame. In + the mean time, the address of the prev frame is used as the + base address of this frame. */ + base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); + if (!fdata.frameless) + /* Frameless really means stackless. */ + base = read_memory_addr (base, wordsize); + } + trad_frame_set_value (this_cache, SP_REGNUM, base); + + /* if != -1, fdata.saved_fpr is the smallest number of saved_fpr. + All fpr's from saved_fpr to fp31 are saved. */ + + if (fdata.saved_fpr >= 0) + { + int i; + CORE_ADDR fpr_addr = base + fdata.fpr_offset; + for (i = fdata.saved_fpr; i < 32; i++) + { + this_cache->prev_regs[FP0_REGNUM + i].addr = fpr_addr; + fpr_addr += 8; + } + } + + /* if != -1, fdata.saved_gpr is the smallest number of saved_gpr. + All gpr's from saved_gpr to gpr31 are saved. */ + + if (fdata.saved_gpr >= 0) + { + int i; + CORE_ADDR gpr_addr = base + fdata.gpr_offset; + for (i = fdata.saved_gpr; i < 32; i++) + { + this_cache->prev_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr; + gpr_addr += wordsize; + } + } + + /* if != -1, fdata.saved_vr is the smallest number of saved_vr. + All vr's from saved_vr to vr31 are saved. */ + if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) + { + if (fdata.saved_vr >= 0) + { + int i; + CORE_ADDR vr_addr = base + fdata.vr_offset; + for (i = fdata.saved_vr; i < 32; i++) + { + this_cache->prev_regs[tdep->ppc_vr0_regnum + i].addr = vr_addr; + vr_addr += register_size (gdbarch, tdep->ppc_vr0_regnum); + } + } + } + + /* if != -1, fdata.saved_ev is the smallest number of saved_ev. + All vr's from saved_ev to ev31 are saved. ????? */ + if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1) + { + if (fdata.saved_ev >= 0) + { + int i; + CORE_ADDR ev_addr = base + fdata.ev_offset; + for (i = fdata.saved_ev; i < 32; i++) + { + this_cache->prev_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr; + this_cache->prev_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + 4; + ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum); + } + } + } + + /* If != 0, fdata.cr_offset is the offset from the frame that + holds the CR. */ + if (fdata.cr_offset != 0) + this_cache->prev_regs[tdep->ppc_cr_regnum].addr = base + fdata.cr_offset; + + /* If != 0, fdata.lr_offset is the offset from the frame that + holds the LR. */ + if (fdata.lr_offset != 0) + this_cache->prev_regs[tdep->ppc_lr_regnum].addr = base + fdata.lr_offset; + /* The PC is found in the link register. */ + this_cache->prev_regs[PC_REGNUM] = this_cache->prev_regs[tdep->ppc_lr_regnum]; + + /* If != 0, fdata.vrsave_offset is the offset from the frame that + holds the VRSAVE. */ + if (fdata.vrsave_offset != 0) + this_cache->prev_regs[tdep->ppc_vrsave_regnum].addr = base + fdata.vrsave_offset; + + if (fdata.alloca_reg < 0) + /* If no alloca register used, then fi->frame is the value of the + %sp for this frame, and it is good enough. */ + this_cache->this_base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); + else + this_cache->this_base = frame_unwind_register_unsigned (next_frame, + fdata.alloca_reg); + this_cache->this_id = frame_id_build (base, fdata.func); +} + +static int +rs6000_trad_frame_sniffer (const struct trad_frame *self, + struct frame_info *next_frame) +{ + return 1; +} + +struct trad_frame rs6000_trad_frame = { + NORMAL_FRAME, + rs6000_trad_frame_sniffer, + rs6000_trad_frame_init, +}; + + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of architectures already created during this debugging session. @@ -2874,8 +3095,6 @@ Problem is, 220 isn't frame (16 byte) aligned. Round it up to 224. */ set_gdbarch_frame_red_zone_size (gdbarch, 224); - set_gdbarch_deprecated_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos); - set_gdbarch_believe_pcc_promotion (gdbarch, 1); set_gdbarch_deprecated_register_convertible (gdbarch, rs6000_register_convertible); set_gdbarch_deprecated_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual); @@ -2896,7 +3115,6 @@ set_gdbarch_push_dummy_call (gdbarch, rs6000_push_dummy_call); set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address); - set_gdbarch_deprecated_pop_frame (gdbarch, rs6000_pop_frame); set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -2918,14 +3136,6 @@ set_gdbarch_use_struct_convention (gdbarch, rs6000_use_struct_convention); - set_gdbarch_deprecated_frameless_function_invocation (gdbarch, rs6000_frameless_function_invocation); - set_gdbarch_deprecated_frame_chain (gdbarch, rs6000_frame_chain); - set_gdbarch_deprecated_frame_saved_pc (gdbarch, rs6000_frame_saved_pc); - - set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs); - set_gdbarch_deprecated_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info); - set_gdbarch_deprecated_init_frame_pc_first (gdbarch, rs6000_init_frame_pc_first); - if (!sysv_abi) { /* Handle RS/6000 function pointers (which are really function @@ -2933,15 +3143,37 @@ set_gdbarch_convert_from_func_ptr_addr (gdbarch, rs6000_convert_from_func_ptr_addr); } - set_gdbarch_deprecated_frame_args_address (gdbarch, rs6000_frame_args_address); - set_gdbarch_deprecated_frame_locals_address (gdbarch, rs6000_frame_args_address); - set_gdbarch_deprecated_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call); /* Helpers for function argument information. */ set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument); /* Hook in ABI-specific overrides, if they have been registered. */ gdbarch_init_osabi (info, gdbarch); + + switch (info.osabi) + { + case GDB_OSABI_NETBSD_AOUT: + case GDB_OSABI_NETBSD_ELF: + case GDB_OSABI_UNKNOWN: + case GDB_OSABI_LINUX: + set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc); + trad_frame_append (gdbarch, &rs6000_trad_frame); + set_gdbarch_unwind_dummy_id (gdbarch, rs6000_unwind_dummy_id); + break; + default: + set_gdbarch_deprecated_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos); + set_gdbarch_believe_pcc_promotion (gdbarch, 1); + set_gdbarch_deprecated_pop_frame (gdbarch, rs6000_pop_frame); + set_gdbarch_deprecated_frame_args_address (gdbarch, rs6000_frame_args_address); + set_gdbarch_deprecated_frame_locals_address (gdbarch, rs6000_frame_args_address); + set_gdbarch_deprecated_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call); + set_gdbarch_deprecated_frameless_function_invocation (gdbarch, rs6000_frameless_function_invocation); + set_gdbarch_deprecated_frame_chain (gdbarch, rs6000_frame_chain); + set_gdbarch_deprecated_frame_saved_pc (gdbarch, rs6000_frame_saved_pc); + set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs); + set_gdbarch_deprecated_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info); + set_gdbarch_deprecated_init_frame_pc_first (gdbarch, rs6000_init_frame_pc_first); + } if (from_xcoff_exec) { Index: sentinel-frame.c =================================================================== RCS file: /cvs/src/src/gdb/sentinel-frame.c,v retrieving revision 1.8 diff -u -r1.8 sentinel-frame.c --- sentinel-frame.c 8 Jun 2003 18:27:14 -0000 1.8 +++ sentinel-frame.c 9 Mar 2004 22:45:00 -0000 @@ -45,7 +45,8 @@ /* Here the register value is taken direct from the register cache. */ static void -sentinel_frame_prev_register (struct frame_info *next_frame, +sentinel_frame_prev_register (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, int regnum, int *optimized, enum lval_type *lvalp, CORE_ADDR *addrp, @@ -71,7 +72,8 @@ } static void -sentinel_frame_this_id (struct frame_info *next_frame, +sentinel_frame_this_id (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_prologue_cache, struct frame_id *this_id) { Index: solib-svr4.c =================================================================== RCS file: /cvs/src/src/gdb/solib-svr4.c,v retrieving revision 1.41 diff -u -r1.41 solib-svr4.c --- solib-svr4.c 21 Feb 2004 18:34:45 -0000 1.41 +++ solib-svr4.c 9 Mar 2004 22:45:00 -0000 @@ -1588,7 +1588,7 @@ _initialize_svr4_solib (void) { fetch_link_map_offsets_gdbarch_data = - register_gdbarch_data (init_fetch_link_map_offsets); + register_gdbarch_data (NULL, init_fetch_link_map_offsets); svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses; svr4_so_ops.free_so = svr4_free_so; Index: trad-frame.c =================================================================== RCS file: /cvs/src/src/gdb/trad-frame.c,v retrieving revision 1.4 diff -u -r1.4 trad-frame.c --- trad-frame.c 20 Aug 2003 22:30:17 -0000 1.4 +++ trad-frame.c 9 Mar 2004 22:45:00 -0000 @@ -1,6 +1,6 @@ /* Traditional frame unwind support, for GDB the GNU Debugger. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -21,101 +21,131 @@ #include "defs.h" #include "frame.h" +#include "frame-unwind.h" #include "trad-frame.h" #include "regcache.h" +#include "frame-base.h" +#include "gdb_assert.h" /* A traditional frame is unwound by analysing the function prologue and using the information gathered to track registers. For non-optimized frames, the technique is reliable (just need to check for all potential instruction sequences). */ -struct trad_frame_saved_reg * -trad_frame_alloc_saved_regs (struct frame_info *next_frame) +struct trad_frame_cache * +trad_frame_cache_zalloc (struct frame_info *next_frame) { - int regnum; struct gdbarch *gdbarch = get_frame_arch (next_frame); - int numregs = NUM_REGS + NUM_PSEUDO_REGS; - struct trad_frame_saved_reg *this_saved_regs - = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg); + const int numregs = NUM_REGS + NUM_PSEUDO_REGS; + struct trad_frame_cache *trad_cache; + int regnum; + + trad_cache = FRAME_OBSTACK_ZALLOC (struct trad_frame_cache); + trad_cache->prev_regs = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg); for (regnum = 0; regnum < numregs; regnum++) { - this_saved_regs[regnum].realreg = regnum; - this_saved_regs[regnum].addr = -1; + trad_cache->prev_regs[regnum].realreg = regnum; + trad_cache->prev_regs[regnum].addr = -1; } - return this_saved_regs; + return trad_cache; } enum { REG_VALUE = -1, REG_UNKNOWN = -2 }; int -trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum) +trad_frame_value_p (struct trad_frame_cache *this_cache, int regnum) { - return (this_saved_regs[regnum].realreg == REG_VALUE); + return (this_cache->prev_regs[regnum].realreg == REG_VALUE); } int -trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum) +trad_frame_addr_p (struct trad_frame_cache *this_cache, int regnum) { - return (this_saved_regs[regnum].realreg >= 0 - && this_saved_regs[regnum].addr != -1); + return (this_cache->prev_regs[regnum].realreg >= 0 + && this_cache->prev_regs[regnum].addr != -1); } int -trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[], +trad_frame_realreg_p (struct trad_frame_cache *this_cache, int regnum) { - return (this_saved_regs[regnum].realreg >= 0 - && this_saved_regs[regnum].addr == -1); + return (this_cache->prev_regs[regnum].realreg >= 0 + && this_cache->prev_regs[regnum].addr == -1); } void -trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[], +trad_frame_set_value (struct trad_frame_cache *this_cache, int regnum, LONGEST val) { /* Make the REALREG invalid, indicating that the ADDR contains the register's value. */ - this_saved_regs[regnum].realreg = REG_VALUE; - this_saved_regs[regnum].addr = val; + this_cache->prev_regs[regnum].realreg = REG_VALUE; + this_cache->prev_regs[regnum].addr = val; } void -trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[], +trad_frame_set_unknown (struct trad_frame_cache *this_cache, int regnum) { /* Make the REALREG invalid, indicating that the value is not known. */ - this_saved_regs[regnum].realreg = REG_UNKNOWN; - this_saved_regs[regnum].addr = -1; + this_cache->prev_regs[regnum].realreg = REG_UNKNOWN; + this_cache->prev_regs[regnum].addr = -1; } -void -trad_frame_prev_register (struct frame_info *next_frame, - struct trad_frame_saved_reg this_saved_regs[], +struct frame_data +{ + const struct frame_unwind *frame_unwind; + const struct frame_base *frame_base; + const struct trad_frame *trad_frame; +}; + +static struct trad_frame_cache * +trad_frame_cache (const struct frame_data *self, + struct frame_info *next_frame, + void **this_cache) +{ + if ((*this_cache) == NULL) + { + (*this_cache) = trad_frame_cache_zalloc (next_frame); + gdb_assert (self->trad_frame->init != NULL); + self->trad_frame->init (self->trad_frame, next_frame, (*this_cache)); + } + return (*this_cache); +} + +static void +trad_frame_prev_register (const struct frame_unwind *self, + struct frame_info *next_frame, + void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realregp, void *bufferp) { + struct trad_frame_cache *trad_cache + = trad_frame_cache (self->unwind_data, next_frame, this_cache); struct gdbarch *gdbarch = get_frame_arch (next_frame); - if (trad_frame_addr_p (this_saved_regs, regnum)) + + if (trad_frame_addr_p (trad_cache, regnum)) { /* The register was saved in memory. */ *optimizedp = 0; *lvalp = lval_memory; - *addrp = this_saved_regs[regnum].addr; + *addrp = trad_cache->prev_regs[regnum].addr; *realregp = -1; if (bufferp != NULL) { /* Read the value in from memory. */ - get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp, + get_frame_memory (next_frame, trad_cache->prev_regs[regnum].addr, bufferp, register_size (gdbarch, regnum)); } } - else if (trad_frame_realreg_p (this_saved_regs, regnum)) + else if (trad_frame_realreg_p (trad_cache, regnum)) { /* Ask the next frame to return the value of the register. */ - frame_register_unwind (next_frame, this_saved_regs[regnum].realreg, + frame_register_unwind (next_frame, trad_cache->prev_regs[regnum].realreg, optimizedp, lvalp, addrp, realregp, bufferp); } - else if (trad_frame_value_p (this_saved_regs, regnum)) + else if (trad_frame_value_p (trad_cache, regnum)) { /* The register's value is available. */ *optimizedp = 0; @@ -124,11 +154,96 @@ *realregp = -1; if (bufferp != NULL) store_unsigned_integer (bufferp, register_size (gdbarch, regnum), - this_saved_regs[regnum].addr); + trad_cache->prev_regs[regnum].addr); } else { error ("Register %s not available", gdbarch_register_name (gdbarch, regnum)); } +} + +static void +trad_frame_this_id (const struct frame_unwind *self, + struct frame_info *next_frame, void **this_cache, + struct frame_id *this_id) +{ + struct trad_frame_cache *trad_cache + = trad_frame_cache (self->unwind_data, next_frame, this_cache); + (*this_id) = trad_cache->this_id; +} + +static const struct frame_unwind * +trad_frame_unwind_sniffer (const struct frame_unwind_sniffer *self, + struct frame_info *next_frame) +{ + const struct trad_frame *trad_frame = self->sniffer_data->trad_frame; + gdb_assert (trad_frame->sniffer != NULL); + if (trad_frame->sniffer (trad_frame, next_frame)) + return self->sniffer_data->frame_unwind; + else + return NULL; +} + +static CORE_ADDR +trad_frame_base (const struct frame_base *self, + struct frame_info *next_frame, + void **this_cache) +{ + struct trad_frame_cache *trad_cache + = trad_frame_cache (self->base_data, next_frame, this_cache); + return trad_cache->this_base; +} + +static const struct frame_base * +trad_frame_base_sniffer (const struct frame_base_sniffer *self, + struct frame_info *next_frame) +{ + const struct trad_frame *trad_frame = self->sniffer_data->trad_frame; + gdb_assert (trad_frame->sniffer != NULL); + if (trad_frame->sniffer (trad_frame, next_frame)) + return self->sniffer_data->frame_base; + else + return NULL; +} + +void +trad_frame_append (struct gdbarch *gdbarch, + const struct trad_frame *trad_frame) +{ + struct frame_data *data; + struct frame_unwind *unwind; + struct frame_unwind_sniffer *unwind_sniffer; + struct frame_base *base; + struct frame_base_sniffer *base_sniffer; + + data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data); + unwind = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind); + unwind_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_sniffer); + base = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base); + base_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base_sniffer); + + data->frame_unwind = unwind; + data->frame_base = base; + data->trad_frame = trad_frame; + + unwind->type = trad_frame->type; + unwind->this_id = trad_frame_this_id; + unwind->prev_register = trad_frame_prev_register; + unwind->unwind_data = data; + unwind_sniffer->sniffer = trad_frame_unwind_sniffer; + unwind_sniffer->sniffer_data = data; + + frame_unwind_sniffer_append (gdbarch, unwind_sniffer); + + base->base_data = data; + base->unwind = unwind; + base->this_base = trad_frame_base; + base->this_locals = trad_frame_base; + base->this_args = trad_frame_base; + + base_sniffer->sniffer = trad_frame_base_sniffer; + base_sniffer->sniffer_data = data; + + frame_base_sniffer_append (gdbarch, base_sniffer); } Index: trad-frame.h =================================================================== RCS file: /cvs/src/src/gdb/trad-frame.h,v retrieving revision 1.4 diff -u -r1.4 trad-frame.h --- trad-frame.h 1 Jul 2003 13:25:19 -0000 1.4 +++ trad-frame.h 9 Mar 2004 22:45:00 -0000 @@ -1,6 +1,6 @@ /* Traditional frame unwind support, for GDB the GNU Debugger. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -23,6 +23,9 @@ #define TRAD_FRAME_H struct frame_info; +struct trad_frame; + +#include "frame.h" /* For frame_id. */ /* A traditional saved regs table, indexed by REGNUM, encoding where the value of REGNUM for the previous frame can be found in this @@ -56,33 +59,55 @@ int realreg; }; -/* Encode REGNUM value in the trad-frame. */ -void trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[], - int regnum, LONGEST val); +struct trad_frame_cache +{ + struct frame_id this_id; + CORE_ADDR this_base; + struct trad_frame_saved_reg *prev_regs; +}; -/* Mark REGNUM as unknown. */ -void trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[], +/* Encode REGNUM's value in the trad-frame. */ +void trad_frame_set_value (struct trad_frame_cache *this_cache, + int regnum, LONGEST val); +void trad_frame_set_addr (struct trad_frame_cache *this_cache, + int regnum, CORE_ADDR addr); +void trad_frame_set_realreg (struct trad_frame_cache *this_cache, + int regnum, int realreg); +void trad_frame_set_unknown (struct trad_frame_cache *this_cache, int regnum); +/* Set the offset of a register, and then update all offsets. Useful + when the offset of a register is known before its absolute + address. */ +void trad_frame_set_offset (struct trad_frame_cache *this_cache, + int regnum, LONGEST addr); +void trad_frame_add_addr (struct trad_frame_cache *this_cache, + int regnum, CORE_ADDR addr); + /* Convenience functions, return non-zero if the register has been encoded as specified. */ -int trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], +int trad_frame_value_p (struct trad_frame_cache *this_cache, int regnum); -int trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], +int trad_frame_addr_p (struct trad_frame_cache *this_cache, int regnum); -int trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[], +int trad_frame_realreg_p (struct trad_frame_cache *this_cache, int regnum); +typedef void (trad_frame_init_ftype) (const struct trad_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache); +typedef int (trad_frame_sniffer_ftype) (const struct trad_frame *self, + struct frame_info *next_frame); -/* Return a freshly allocated (and initialized) trad_frame array. */ -struct trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct frame_info *next_frame); +struct trad_frame +{ + enum frame_type type; + trad_frame_sniffer_ftype *sniffer; + trad_frame_init_ftype *init; + const struct trad_frame_data *trad_data; +}; -/* Given the trad_frame info, return the location of the specified - register. */ -void trad_frame_prev_register (struct frame_info *next_frame, - struct trad_frame_saved_reg this_saved_regs[], - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realregp, void *bufferp); +void trad_frame_append (struct gdbarch *gdbarch, + const struct trad_frame *trad_frame); #endif Index: user-regs.c =================================================================== RCS file: /cvs/src/src/gdb/user-regs.c,v retrieving revision 1.4 diff -u -r1.4 user-regs.c --- user-regs.c 9 Mar 2004 20:03:37 -0000 1.4 +++ user-regs.c 9 Mar 2004 22:45:00 -0000 @@ -207,5 +207,5 @@ void _initialize_user_regs (void) { - user_regs_data = register_gdbarch_data (user_regs_init); + user_regs_data = register_gdbarch_data (NULL, user_regs_init); }