diff options
-rw-r--r-- | gdb/ChangeLog | 13 | ||||
-rw-r--r-- | gdb/d10v-tdep.c | 10 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/doc/gdbint.texinfo | 27 | ||||
-rw-r--r-- | gdb/frame.c | 31 | ||||
-rw-r--r-- | gdb/frame.h | 7 | ||||
-rw-r--r-- | gdb/gdbarch.c | 37 | ||||
-rw-r--r-- | gdb/gdbarch.h | 11 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 3 | ||||
-rw-r--r-- | gdb/regcache.c | 5 |
10 files changed, 138 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a49e596..78ff45e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,18 @@ 2003-06-08 Andrew Cagney <cagney@redhat.com> + * gdbarch.sh (UNWIND_SP): Add. + * gdbarch.h, gdbarch.c: Re-generate. + * frame.c (frame_sp_unwind): New function. + (get_frame_sp): New function. + * frame.h (get_frame_sp, frame_sp_unwind): Declare. + * regcache.c (read_sp): Rewrite, try each of TARGET_READ_SP, + gdbarch_unwind_sp and SP_REGNUM when looking for the SP register + value. + * d10v-tdep.c (d10v_unwind_sp): Replace d10v_read_sp. + (d10v_gdbarch_init): Set unwind_sp instead of read_sp. + +2003-06-08 Andrew Cagney <cagney@redhat.com> + Deprecate BIG_REMOTE_BREAKPOINT, LITTLE_REMOTE_BREAKPOINT and REMOTE_BREAKPOINT. * remote.c: Update. diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index a83d6ba..84d0a85 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -102,8 +102,6 @@ a0_regnum (struct gdbarch *gdbarch) extern void _initialize_d10v_tdep (void); -static CORE_ADDR d10v_read_sp (void); - static void d10v_eva_prepare_to_trace (void); static void d10v_eva_get_trace_data (void); @@ -902,9 +900,11 @@ d10v_write_pc (CORE_ADDR val, ptid_t ptid) } static CORE_ADDR -d10v_read_sp (void) +d10v_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) { - return (d10v_make_daddr (read_register (D10V_SP_REGNUM))); + ULONGEST sp; + frame_unwind_unsigned_register (next_frame, D10V_SP_REGNUM, &sp); + return d10v_make_daddr (sp); } /* When arguments must be pushed onto the stack, they go on in reverse @@ -1528,7 +1528,7 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_read_pc (gdbarch, d10v_read_pc); set_gdbarch_write_pc (gdbarch, d10v_write_pc); - set_gdbarch_read_sp (gdbarch, d10v_read_sp); + set_gdbarch_unwind_sp (gdbarch, d10v_unwind_sp); set_gdbarch_num_regs (gdbarch, d10v_num_regs); set_gdbarch_sp_regnum (gdbarch, D10V_SP_REGNUM); diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index b9c28f0..653c565 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2003-06-08 Andrew Cagney <cagney@redhat.com> + + * gdbint.texinfo (Target Architecture Definition): Document + "unwind_sp". Cross reference "unwind_sp" and TARGET_READ_SP. + 2003-06-07 Adam Fedor <fedor@gnu.org> * gdb.texinfo: Add Objective-C documentation. diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index dc5c6b8..75444ee 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -3291,6 +3291,23 @@ return d10v_make_iaddr (pc); @noindent @xref{DEPRECATED_FRAME_SAVED_PC}, which this method replaces. +@item CORE_ADDR unwind_sp (struct frame_info *@var{this_frame}) +@findex unwind_sp +@anchor{unwind_sp} Return the frame's inner most stack address. This is +commonly refered to as the frame's @dfn{stack pointer}. + +The implementation, which must be frame agnostic (work with any frame), +is typically no more than: + +@smallexample +ULONGEST sp; +frame_unwind_unsigned_register (this_frame, D10V_SP_REGNUM, &sp); +return d10v_make_daddr (sp); +@end smallexample + +@noindent +@xref{TARGET_READ_SP}, which this method replaces. + @item FUNCTION_EPILOGUE_SIZE @findex FUNCTION_EPILOGUE_SIZE For some COFF targets, the @code{x_sym.x_misc.x_fsize} field of the @@ -3890,15 +3907,17 @@ Number of bits in a short integer; defaults to @code{2 * TARGET_CHAR_BIT}. @findex write_pc @findex read_sp @findex read_fp -These change the behavior of @code{read_pc}, @code{write_pc}, -@code{read_sp} and @code{deprecated_read_fp}. For most targets, these -may be left undefined. @value{GDBN} will call the read and write -register functions with the relevant @code{_REGNUM} argument. +@anchor{TARGET_READ_SP} These change the behavior of @code{read_pc}, +@code{write_pc}, @code{read_sp} and @code{deprecated_read_fp}. For most +targets, these may be left undefined. @value{GDBN} will call the read +and write register functions with the relevant @code{_REGNUM} argument. These macros are useful when a target keeps one of these registers in a hard to get at place; for example, part in a segment register and part in an ordinary register. +@xref{unwind_sp}, which replaces @code{TARGET_READ_SP}. + @item TARGET_VIRTUAL_FRAME_POINTER(@var{pc}, @var{regp}, @var{offsetp}) @findex TARGET_VIRTUAL_FRAME_POINTER Returns a @code{(register, offset)} pair representing the virtual frame diff --git a/gdb/frame.c b/gdb/frame.c index 4b103cd..b7a8785 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -2250,6 +2250,37 @@ get_frame_arch (struct frame_info *this_frame) return current_gdbarch; } +/* Stack pointer methods. */ + +CORE_ADDR +get_frame_sp (struct frame_info *this_frame) +{ + return frame_sp_unwind (this_frame->next); +} + +CORE_ADDR +frame_sp_unwind (struct frame_info *next_frame) +{ + /* Normality, an architecture that provides a way of obtaining any + frame inner-most address. */ + if (gdbarch_unwind_sp_p (current_gdbarch)) + return gdbarch_unwind_sp (current_gdbarch, next_frame); + /* Things are looking grim. If it's the inner-most frame and there + is a TARGET_READ_SP then that can be used. */ + if (next_frame->level < 0 && TARGET_READ_SP_P ()) + return TARGET_READ_SP (); + /* Now things are really are grim. Hope that the value returned by + the SP_REGNUM register is meaningful. */ + if (SP_REGNUM >= 0) + { + ULONGEST sp; + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp); + return sp; + } + internal_error (__FILE__, __LINE__, "Missing unwind SP method"); +} + + int legacy_frame_p (struct gdbarch *current_gdbarch) { diff --git a/gdb/frame.h b/gdb/frame.h index bfd9469..04fa67d 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -166,6 +166,13 @@ extern struct frame_info *frame_find_by_id (struct frame_id id); This replaced: frame->pc; */ extern CORE_ADDR get_frame_pc (struct frame_info *); +/* The frame's inner-most bound. AKA the stack-pointer. Confusingly + known as top-of-stack. */ + +extern CORE_ADDR get_frame_sp (struct frame_info *); +extern CORE_ADDR frame_sp_unwind (struct frame_info *); + + /* 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. */ diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index eeea625..648b8f5 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -243,6 +243,7 @@ struct gdbarch gdbarch_deprecated_frame_chain_valid_ftype *deprecated_frame_chain_valid; gdbarch_deprecated_frame_saved_pc_ftype *deprecated_frame_saved_pc; gdbarch_unwind_pc_ftype *unwind_pc; + gdbarch_unwind_sp_ftype *unwind_sp; gdbarch_frame_args_address_ftype *frame_args_address; gdbarch_frame_locals_address_ftype *frame_locals_address; gdbarch_deprecated_saved_pc_after_call_ftype *deprecated_saved_pc_after_call; @@ -410,6 +411,7 @@ struct gdbarch startup_gdbarch = 0, /* deprecated_frame_chain_valid */ 0, /* deprecated_frame_saved_pc */ 0, /* unwind_pc */ + 0, /* unwind_sp */ 0, /* frame_args_address */ 0, /* frame_locals_address */ 0, /* deprecated_saved_pc_after_call */ @@ -721,6 +723,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of deprecated_frame_chain_valid, has predicate */ /* Skip verify of deprecated_frame_saved_pc, has predicate */ /* Skip verify of unwind_pc, has predicate */ + /* Skip verify of unwind_sp, has predicate */ /* Skip verify of frame_args_address, invalid_p == 0 */ /* Skip verify of frame_locals_address, invalid_p == 0 */ /* Skip verify of deprecated_saved_pc_after_call, has predicate */ @@ -2636,6 +2639,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: unwind_pc = 0x%08lx\n", (long) current_gdbarch->unwind_pc); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_unwind_sp_p() = %d\n", + gdbarch_unwind_sp_p (current_gdbarch)); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: unwind_sp = 0x%08lx\n", + (long) current_gdbarch->unwind_sp); #ifdef USE_STRUCT_CONVENTION fprintf_unfiltered (file, "gdbarch_dump: %s # %s\n", @@ -4970,6 +4981,32 @@ set_gdbarch_unwind_pc (struct gdbarch *gdbarch, gdbarch->unwind_pc = unwind_pc; } +int +gdbarch_unwind_sp_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->unwind_sp != 0; +} + +CORE_ADDR +gdbarch_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + gdb_assert (gdbarch != NULL); + if (gdbarch->unwind_sp == 0) + internal_error (__FILE__, __LINE__, + "gdbarch: gdbarch_unwind_sp invalid"); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_sp called\n"); + return gdbarch->unwind_sp (gdbarch, next_frame); +} + +void +set_gdbarch_unwind_sp (struct gdbarch *gdbarch, + gdbarch_unwind_sp_ftype unwind_sp) +{ + gdbarch->unwind_sp = unwind_sp; +} + CORE_ADDR gdbarch_frame_args_address (struct gdbarch *gdbarch, struct frame_info *fi) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 092f487..e9895cf 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -371,6 +371,8 @@ extern void set_gdbarch_deprecated_target_read_fp (struct gdbarch *gdbarch, gdba #define DEPRECATED_TARGET_READ_FP() (gdbarch_deprecated_target_read_fp (current_gdbarch)) #endif +/* UNWIND_SP is a direct replacement for TARGET_READ_SP. */ + #if defined (TARGET_READ_SP) /* Legacy for systems yet to multi-arch TARGET_READ_SP */ #if !defined (TARGET_READ_SP_P) @@ -504,7 +506,8 @@ extern void set_gdbarch_num_pseudo_regs (struct gdbarch *gdbarch, int num_pseudo /* GDB's standard (or well known) register numbers. These can map onto a real register or a pseudo (computed) register or not be defined at - all (-1). */ + all (-1). + SP_REGNUM will hopefully be replaced by UNWIND_SP. */ /* Default (value) for non- multi-arch platforms. */ #if (!GDB_MULTI_ARCH) && !defined (SP_REGNUM) @@ -2257,6 +2260,12 @@ typedef CORE_ADDR (gdbarch_unwind_pc_ftype) (struct gdbarch *gdbarch, struct fra extern CORE_ADDR gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame); extern void set_gdbarch_unwind_pc (struct gdbarch *gdbarch, gdbarch_unwind_pc_ftype *unwind_pc); +extern int gdbarch_unwind_sp_p (struct gdbarch *gdbarch); + +typedef CORE_ADDR (gdbarch_unwind_sp_ftype) (struct gdbarch *gdbarch, struct frame_info *next_frame); +extern CORE_ADDR gdbarch_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame); +extern void set_gdbarch_unwind_sp (struct gdbarch *gdbarch, gdbarch_unwind_sp_ftype *unwind_sp); + /* Default (function) for non- multi-arch platforms. */ #if (!GDB_MULTI_ARCH) && !defined (FRAME_ARGS_ADDRESS) #define FRAME_ARGS_ADDRESS(fi) (get_frame_base (fi)) diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 3f2bbee..c1f83a9 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -431,6 +431,7 @@ f:2:TARGET_WRITE_PC:void:write_pc:CORE_ADDR val, ptid_t ptid:val, ptid::0:generi # This is simply not needed. See value_of_builtin_frame_fp_reg and # call_function_by_hand. F::DEPRECATED_TARGET_READ_FP:CORE_ADDR:deprecated_target_read_fp:void +# UNWIND_SP is a direct replacement for TARGET_READ_SP. F:2:TARGET_READ_SP:CORE_ADDR:read_sp:void # The dummy call frame SP should be set by push_dummy_call. F:2:DEPRECATED_DUMMY_WRITE_SP:void:deprecated_dummy_write_sp:CORE_ADDR val:val @@ -452,6 +453,7 @@ v:2:NUM_PSEUDO_REGS:int:num_pseudo_regs::::0:0::0::: # GDB's standard (or well known) register numbers. These can map onto # a real register or a pseudo (computed) register or not be defined at # all (-1). +# SP_REGNUM will hopefully be replaced by UNWIND_SP. v:2:SP_REGNUM:int:sp_regnum::::-1:-1::0 # This is simply not needed. See value_of_builtin_frame_fp_reg and # call_function_by_hand. @@ -609,6 +611,7 @@ F:2:DEPRECATED_FRAME_CHAIN_VALID:int:deprecated_frame_chain_valid:CORE_ADDR chai # interfaces they have very different underlying implementations. F:2:DEPRECATED_FRAME_SAVED_PC:CORE_ADDR:deprecated_frame_saved_pc:struct frame_info *fi:fi::0:0 M::UNWIND_PC:CORE_ADDR:unwind_pc:struct frame_info *next_frame:next_frame: +M::UNWIND_SP:CORE_ADDR:unwind_sp:struct frame_info *next_frame:next_frame: f:2:FRAME_ARGS_ADDRESS:CORE_ADDR:frame_args_address:struct frame_info *fi:fi::0:get_frame_base::0 f:2:FRAME_LOCALS_ADDRESS:CORE_ADDR:frame_locals_address:struct frame_info *fi:fi::0:get_frame_base::0 F::DEPRECATED_SAVED_PC_AFTER_CALL:CORE_ADDR:deprecated_saved_pc_after_call:struct frame_info *frame:frame diff --git a/gdb/regcache.c b/gdb/regcache.c index 9584336..facaab3 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -1351,8 +1351,11 @@ read_sp (void) { if (TARGET_READ_SP_P ()) return TARGET_READ_SP (); - /* Else return SP from get_current_frame. */ + else if (gdbarch_unwind_sp_p (current_gdbarch)) + return get_frame_sp (get_current_frame ()); else if (SP_REGNUM >= 0) + /* Try SP_REGNUM last: this makes all sorts of [wrong] assumptions + about the architecture so put it at the end. */ return read_register (SP_REGNUM); internal_error (__FILE__, __LINE__, "read_sp: Unable to find SP"); } |