This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[patch/rfc] Add frame_register(); GET_SAVED_REGISTER() is a predicate
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Fri, 01 Nov 2002 18:48:30 -0500
- Subject: [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.");