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] Add frame_register(); GET_SAVED_REGISTER() is a predicate


Hello,

The attached patch adds a new function:

+/* Return the value of the register in this FRAME. Convenience
+ function that is equivalent to frame_register_unwind
+ (get_next_frame (FRAME), ...). If VALUEP is NULL, don't
+ fetch/compute the value. */
+
+extern void frame_register (struct frame_info *frame, int regnum,
+ int *optimizedp, enum lval_type *lvalp,
+ CORE_ADDR *addrp, int *realnump,
+ void *valuep);
+

This function is very like the existing frame_register_unwind() only it returns the value of REGNUM that belongs to FRAME and not the value that belongs to FRAME's caller. Further, consistent with frame_register_unwind (and unlike get_saved_register()), it returns the registers actual location (register number) in REALNUM while GET_SAVED_REGISTER() was returning the register's offset (in the registers[] array).

The patch then modifies frame.c and valops.c to use the new function.

The reason for changing the existing GET_SAVED_REGISTER() to a predicate method is a bit nasty. When a target architecture provides a GET_SAVED_REGISTER() method, the frame_register() function has no direct way of obtaining the register's REALNUM and hence is forced to compute that value using a simple lookup. If an architecture does not provide GET_SAVED_REGISTER(), frame_register() can bypass all that mess and call the unwind code directly.

The valops.c change is even more, er, ammusing. If you look at the patch as it stands, it should cause GDB to abort. It turns out though, that GDB's testsuite contains no test to exercise those code paths and, consequently, that part of the change is very un tested. I'm going to separate out the valops.c part of the change for the moment.

I'll look to commit the gdbarch and frame.[ch] parts in a few days.

Andrew
2002-11-01  Andrew Cagney  <cagney@redhat.com>

	* gdbarch.sh (GET_SAVED_REGISTER): Change to a predicate function.
	* gdbarch.h, gdbarch.c: Regnerate.
	* valops.c (value_assign): Use frame_register_read instead of
	get_saved_register.
	(value_assign): Use frame_register instead of get_saved_register.
	* frame.h (frame_register): Declare.
	* frame.c (frame_register): New function.
	(get_saved_register): Test GET_SAVED_REGISTER_P before calling
	GET_SAVED_REGISTER.
	(frame_register_read): Use frame_register instead of
	get_saved_register.

Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.19
diff -u -r1.19 frame.c
--- frame.c	31 Oct 2002 20:14:33 -0000	1.19
+++ frame.c	1 Nov 2002 22:57:35 -0000
@@ -125,6 +125,66 @@
 }
 
 void
+frame_register (struct frame_info *frame, int regnum,
+		int *optimizedp, enum lval_type *lvalp,
+		CORE_ADDR *addrp, int *realnump, void *bufferp)
+{
+  /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
+     that the value proper does not need to be fetched.  */
+  gdb_assert (optimizedp != NULL);
+  gdb_assert (lvalp != NULL);
+  gdb_assert (addrp != NULL);
+  gdb_assert (realnump != NULL);
+  /* gdb_assert (bufferp != NULL); */
+
+  /* Ulgh!  Old code that, for lval_register, sets ADDRP to the offset
+     of the register in the register cache.  It should instead return
+     the REGNUM corresponding to that register.  Translate the .  */
+  if (GET_SAVED_REGISTER_P ())
+    {
+      GET_SAVED_REGISTER (bufferp, optimizedp, addrp, frame, regnum, lvalp);
+      /* Compute the REALNUM if the caller wants it.  */
+      if (*lvalp == lval_register)
+	{
+	  int regnum;
+	  for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
+	    {
+	      if (*addrp == register_offset_hack (current_gdbarch, regnum))
+		{
+		  *realnump = regnum;
+		  return;
+		}
+	    }
+	  internal_error (__FILE__, __LINE__,
+			  "Failed to compute the register number corresponding"
+			  " to 0x%s", paddr_d (*addrp));
+	}
+      *realnump = -1;
+      return;
+    }
+
+  /* Reached the the bottom (youngest, inner most) of the frame chain
+     (youngest, inner most) frame, go direct to the hardware register
+     cache (do not pass go, do not try to cache the value, ...).  The
+     unwound value would have been cached in frame->next but that
+     doesn't exist.  This doesn't matter as the hardware register
+     cache is stopping any unnecessary accesses to the target.  */
+
+  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
+     special case, there was always an inner frame dedicated to the
+     hardware registers.  Unfortunatly, there is too much unwind code
+     around that looks up/down the frame chain while making the
+     assumption that each frame level is using the same unwind code.  */
+
+  if (frame == NULL)
+    frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, realnump,
+			   bufferp);
+  else
+    frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
+			   realnump, bufferp);
+}
+
+void
 frame_unwind_signed_register (struct frame_info *frame, int regnum,
 			      LONGEST *val)
 {
@@ -240,7 +300,13 @@
 		    int regnum,
 		    enum lval_type *lval)
 {
-  GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval);
+  if (GET_SAVED_REGISTER_P ())
+    {
+      GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval);
+      return;
+    }
+  generic_unwind_get_saved_register (raw_buffer, optimized, addrp, frame,
+				     regnum, lval);
 }
 
 /* frame_register_read ()
@@ -253,9 +319,11 @@
 int
 frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
 {
-  int optim;
-  get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame,
-		      regnum, (enum lval_type *) NULL);
+  int optimized;
+  enum lval_type lval;
+  CORE_ADDR addr;
+  int realnum;
+  frame_register (frame, regnum, &optimized, &lval, &addr, &realnum, myaddr);
 
   /* FIXME: cagney/2002-05-15: This test, is just bogus.
 
@@ -267,7 +335,7 @@
   if (register_cached (regnum) < 0)
     return 0;			/* register value not available */
 
-  return !optim;
+  return !optimized;
 }
 
 
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.28
diff -u -r1.28 frame.h
--- frame.h	1 Nov 2002 21:21:49 -0000	1.28
+++ frame.h	1 Nov 2002 22:57:35 -0000
@@ -350,6 +350,16 @@
 				   CORE_ADDR *addrp, int *realnump,
 				   void *valuep);
 
+/* Return the value of the register in this FRAME.  Convenience
+   function that is equivalent to frame_register_unwind
+   (get_next_frame (FRAME), ...).  If VALUEP is NULL, don't
+   fetch/compute the value.  */
+
+extern void frame_register (struct frame_info *frame, int regnum,
+			    int *optimizedp, enum lval_type *lvalp,
+			    CORE_ADDR *addrp, int *realnump,
+			    void *valuep);
+
 /* Unwind FRAME so that the value of register REGNUM, in the previous
    frame is returned.  Simplified versions of frame_register_unwind.  */
 /* NOTE: cagney/2002-09-13: Return void as one day these functions may
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.167
diff -u -r1.167 gdbarch.sh
--- gdbarch.sh	26 Oct 2002 17:19:27 -0000	1.167
+++ gdbarch.sh	1 Nov 2002 22:57:40 -0000
@@ -508,7 +508,7 @@
 v:2:BELIEVE_PCC_PROMOTION:int:believe_pcc_promotion:::::::
 v:2:BELIEVE_PCC_PROMOTION_TYPE:int:believe_pcc_promotion_type:::::::
 f:2:COERCE_FLOAT_TO_DOUBLE:int:coerce_float_to_double:struct type *formal, struct type *actual:formal, actual:::default_coerce_float_to_double::0
-f:2:GET_SAVED_REGISTER:void:get_saved_register:char *raw_buffer, int *optimized, CORE_ADDR *addrp, struct frame_info *frame, int regnum, enum lval_type *lval:raw_buffer, optimized, addrp, frame, regnum, lval:::generic_unwind_get_saved_register::0
+F:2:GET_SAVED_REGISTER:void:get_saved_register:char *raw_buffer, int *optimized, CORE_ADDR *addrp, struct frame_info *frame, int regnum, enum lval_type *lval:raw_buffer, optimized, addrp, frame, regnum, lval
 #
 f:2:REGISTER_CONVERTIBLE:int:register_convertible:int nr:nr:::generic_register_convertible_not::0
 f:2:REGISTER_CONVERT_TO_VIRTUAL:void:register_convert_to_virtual:int regnum, struct type *type, char *from, char *to:regnum, type, from, to:::0::0
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.78
diff -u -r1.78 valops.c
--- valops.c	23 Oct 2002 21:33:07 -0000	1.78
+++ valops.c	1 Nov 2002 22:57:42 -0000
@@ -720,9 +720,8 @@
 	     amount_copied < amount_to_copy;
 	     amount_copied += reg_size, regno++)
 	  {
-	    get_saved_register (buffer + amount_copied,
-				(int *) NULL, (CORE_ADDR *) NULL,
-				frame, regno, (enum lval_type *) NULL);
+	    frame_register_read (frame, regno, buffer + amount_copied);
+	    internal_error (__FILE__, __LINE__, "x");
 	  }
 
 	/* Modify what needs to be modified.  */
@@ -745,10 +744,12 @@
 	    enum lval_type lval;
 	    CORE_ADDR addr;
 	    int optim;
+	    int realnum;
 
 	    /* Just find out where to put it.  */
-	    get_saved_register ((char *) NULL,
-				&optim, &addr, frame, regno, &lval);
+	    frame_register (frame, regno, &optim, &lval, &addr, &realnum,
+			    NULL);
+	    internal_error (__FILE__, __LINE__, "x");
 
 	    if (optim)
 	      error ("Attempt to assign to a value that was optimized out.");

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