This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch rfc; rfa:doco] frame_sp_unwind


Hello,

This patch adds a per-architecture gdbarch_unwind_sp and the frame wrapper methods:
get_frame_sp()
and
frame_sp_unwind()
as replacements for TARGET_READ_SP. The key advantage of this new method is that it takes a ``struct frame_info'' parameter and hence avoids any global state.


It also modifies read_sp() so that it will use get_frame_sp and hence provide a certain level of forward compatibility. Similarly, frame_sp_unwind() has been written in a way that provides a certain level of backward compatibility.

For the d10v, sets UNWIND_SP instead of READ_SP and eliminates another global regcache/target reference.

Follow-on changes will include things like replace read_sp() with get_frame_sp(), eliminate generic_target_read_sp(), and deprecate TARGET_READ_SP.

Eli, note the doco change.

I'll look to commit this in a few days.

Andrew
2003-06-06  Andrew Cagney  <cagney@redhat.com>

	* gdbarch.sh (UNWIND_SP): Add.
	(TARGET_READ_SP): Change to function with predicate.
	* 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.

Index: doc/ChangeLog
2003-06-06  Andrew Cagney  <cagney@redhat.com>

	* gdbint.texinfo (Target Architecture Definition): Document
	"unwind_sp".  Cross reference "unwind_sp" and TARGET_READ_SP.

Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.118
diff -u -r1.118 d10v-tdep.c
--- d10v-tdep.c	3 Jun 2003 18:53:37 -0000	1.118
+++ d10v-tdep.c	6 Jun 2003 19:18:57 -0000
@@ -101,8 +101,6 @@
 
 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);
@@ -918,9 +916,11 @@
 }
 
 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
@@ -1604,7 +1604,7 @@
 
   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);
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.117
diff -u -r1.117 frame.c
--- frame.c	3 Jun 2003 18:53:37 -0000	1.117
+++ frame.c	6 Jun 2003 19:18:57 -0000
@@ -2250,6 +2250,37 @@
   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)
 {
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.96
diff -u -r1.96 frame.h
--- frame.h	3 Jun 2003 18:53:37 -0000	1.96
+++ frame.h	6 Jun 2003 19:19:00 -0000
@@ -166,6 +166,13 @@
    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.  */
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.240
diff -u -r1.240 gdbarch.sh
--- gdbarch.sh	2 Jun 2003 02:54:34 -0000	1.240
+++ gdbarch.sh	6 Jun 2003 19:19:07 -0000
@@ -431,7 +431,8 @@
 # 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
-f:2:TARGET_READ_SP:CORE_ADDR:read_sp:void:::0:generic_target_read_sp::0
+# 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
 # Function for getting target's idea of a frame pointer.  FIXME: GDB's
@@ -452,6 +453,7 @@
 # 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 @@
 # 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
Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.82
diff -u -r1.82 regcache.c
--- regcache.c	17 May 2003 05:59:58 -0000	1.82
+++ regcache.c	6 Jun 2003 19:19:09 -0000
@@ -1375,7 +1375,26 @@
 CORE_ADDR
 read_sp (void)
 {
-  return TARGET_READ_SP ();
+  /* Try TARGET_READ_SP first: that way code that provides
+     TARGET_READ_SP method preserves its current behavior.  */
+  if (TARGET_READ_SP_P ())
+    return TARGET_READ_SP ();
+  /* Try UNWIND_SP second: ensures that architectures which need to
+     unwind/unpack SP in weird and wonderful ways always override
+     SP_REGNUM.  The d10v, for instance needs to convert the SP
+     pointer register into a CORE_ADDR.  The MIPS needs to sign extend
+     its SP register.  */
+  if (gdbarch_unwind_sp_p (current_gdbarch))
+    return get_frame_sp (get_current_frame ());
+  /* Try SP_REGNUM last: this makes all sorts of [wrong] assumptions
+     about the architecture so put it at the end.  */
+  if (SP_REGNUM >= 0)
+    {
+      ULONGEST sp;
+      regcache_cooked_read_unsigned (current_regcache, SP_REGNUM, &sp);
+      return sp;
+    }
+  internal_error (__FILE__, __LINE__, "read_sp");
 }
 
 void
Index: doc/gdbint.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
retrieving revision 1.148
diff -u -r1.148 gdbint.texinfo
--- doc/gdbint.texinfo	1 Jun 2003 23:05:43 -0000	1.148
+++ doc/gdbint.texinfo	6 Jun 2003 19:19:14 -0000
@@ -3291,6 +3291,23 @@
 @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 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,14 +3907,16 @@
 @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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]