This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[patch/rfc] frame_pc_unwind()
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Fri, 08 Nov 2002 19:46:06 -0500
- Subject: [patch/rfc] frame_pc_unwind()
Hello,
The attached patch adds a per-frame frame_pc_unwind() method. This goes
with the per-frame frame_register_unwind() method (notice how the
names/meanings match - unlike frame_saved_pc() vs get_saved_register() :-).
For a dummy frame it uses the dummy-frame version. For other frames it
falls back to the existing FRAME_SAVED_PC() version.
This patch means that both GET_SAVED_REGISTER() and FRAME_SAVED_PC()
have now officially been `put on notice'. Need to demonstrate the
replacement before they can be made obsolete though :-)
Baring comments, I'll commit this in a few days,
Andrew
2002-11-08 Andrew Cagney <ac131313@redhat.com>
* frame.c (frame_pc_unwind): New function.
(frame_saved_regs_pc_unwind): New function.
(frame_register_unwind): Pass unwind_cache instead of
register_unwind_cache.
(set_unwind_by_pc): Add unwind_pc parameter, set.
(create_new_frame): Pass frame->pc_unwind to set_unwind_by_pc.
(get_prev_frame): Ditto.
* frame.h (frame_pc_unwind_ftype): Declare.
(struct frame_info): Add pc_unwind, pc_unwind_cache_p and
pc_unwind_cache. Rename register_unwind_cache to unwind_cache.
(frame_pc_unwind): Declare.
* dummy-frame.c (dummy_frame_pc_unwind): New function.
(struct dummy_frame): Add comment mentioning that values are for
previous frame.
* dummy-frame.h (dummy_frame_pc_unwind): Declare.
* blockframe.c (file_frame_chain_valid): Use frame_pc_unwind.
(generic_file_frame_chain_valid): Ditto.
* stack.c (frame_info): Ditto.
Index: blockframe.c
===================================================================
RCS file: /cvs/src/src/gdb/blockframe.c,v
retrieving revision 1.46
diff -u -r1.46 blockframe.c
--- blockframe.c 8 Nov 2002 20:48:55 -0000 1.46
+++ blockframe.c 9 Nov 2002 00:36:22 -0000
@@ -49,7 +49,7 @@
file_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
{
return ((chain) != 0
- && !inside_entry_file (FRAME_SAVED_PC (thisframe)));
+ && !inside_entry_file (frame_pc_unwind (thisframe)));
}
/* Use the alternate method of avoiding running up off the end of the
@@ -753,12 +753,12 @@
int
generic_file_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
{
- if (PC_IN_CALL_DUMMY (FRAME_SAVED_PC (fi), fp, fp))
+ if (PC_IN_CALL_DUMMY (frame_pc_unwind (fi), fp, fp))
return 1; /* don't prune CALL_DUMMY frames */
else /* fall back to default algorithm (see frame.h) */
return (fp != 0
&& (INNER_THAN (fi->frame, fp) || fi->frame == fp)
- && !inside_entry_file (FRAME_SAVED_PC (fi)));
+ && !inside_entry_file (frame_pc_unwind (fi)));
}
int
Index: dummy-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.c,v
retrieving revision 1.2
diff -u -r1.2 dummy-frame.c
--- dummy-frame.c 8 Nov 2002 23:12:52 -0000 1.2
+++ dummy-frame.c 9 Nov 2002 00:36:22 -0000
@@ -37,6 +37,8 @@
{
struct dummy_frame *next;
+ /* These values belong to the caller (the previous frame, the frame
+ that this unwinds back to). */
CORE_ADDR pc;
CORE_ADDR fp;
CORE_ADDR sp;
@@ -306,5 +308,13 @@
register cache. */
regcache_cooked_read (dummy->regcache, regnum, bufferp);
}
+}
+
+CORE_ADDR
+dummy_frame_pc_unwind (struct frame_info *frame,
+ void **cache)
+{
+ struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
+ return dummy->pc;
}
Index: dummy-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.h,v
retrieving revision 1.2
diff -u -r1.2 dummy-frame.h
--- dummy-frame.h 8 Nov 2002 23:12:52 -0000 1.2
+++ dummy-frame.h 9 Nov 2002 00:36:22 -0000
@@ -54,6 +54,12 @@
int *realnump,
void *valuep);
+/* Assuming that FRAME is a dummy, return the resume address for the
+ previous frame. */
+
+extern CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame,
+ void **unwind_cache);
+
/* Return the regcache that belongs to the dummy-frame identifed by PC
and FP, or NULL if no such frame exists. */
/* FIXME: cagney/2002-11-08: The function only exists because of
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.23
diff -u -r1.23 frame.c
--- frame.c 8 Nov 2002 23:12:52 -0000 1.23
+++ frame.c 9 Nov 2002 00:36:22 -0000
@@ -84,6 +84,17 @@
return NULL;
}
+CORE_ADDR
+frame_pc_unwind (struct frame_info *frame)
+{
+ if (!frame->pc_unwind_cache_p)
+ {
+ frame->pc_unwind_cache = frame->pc_unwind (frame, &frame->unwind_cache);
+ frame->pc_unwind_cache_p = 1;
+ }
+ return frame->pc_unwind_cache;
+}
+
void
frame_register_unwind (struct frame_info *frame, int regnum,
int *optimizedp, enum lval_type *lvalp,
@@ -124,7 +135,7 @@
}
/* Ask this frame to unwind its register. */
- frame->register_unwind (frame, &frame->register_unwind_cache, regnum,
+ frame->register_unwind (frame, &frame->unwind_cache, regnum,
optimizedp, lvalp, addrp, realnump, bufferp);
}
@@ -524,6 +535,12 @@
}
}
+static CORE_ADDR
+frame_saved_regs_pc_unwind (struct frame_info *frame, void **cache)
+{
+ return FRAME_SAVED_PC (frame);
+}
+
/* Function: get_saved_register
Find register number REGNUM relative to FRAME and put its (raw,
target format) contents in *RAW_BUFFER.
@@ -627,18 +644,28 @@
static void
set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp,
- frame_register_unwind_ftype **unwind)
+ frame_register_unwind_ftype **unwind_register,
+ frame_pc_unwind_ftype **unwind_pc)
{
if (!USE_GENERIC_DUMMY_FRAMES)
- /* Still need to set this to something. The ``info frame'' code
- calls this function to find out where the saved registers are.
- Hopefully this is robust enough to stop any core dumps and
- return vaguely correct values.. */
- *unwind = frame_saved_regs_register_unwind;
+ {
+ /* Still need to set this to something. The ``info frame'' code
+ calls this function to find out where the saved registers are.
+ Hopefully this is robust enough to stop any core dumps and
+ return vaguely correct values.. */
+ *unwind_register = frame_saved_regs_register_unwind;
+ *unwind_pc = frame_saved_regs_pc_unwind;
+ }
else if (PC_IN_CALL_DUMMY (pc, fp, fp))
- *unwind = dummy_frame_register_unwind;
+ {
+ *unwind_register = dummy_frame_register_unwind;
+ *unwind_pc = dummy_frame_pc_unwind;
+ }
else
- *unwind = frame_saved_regs_register_unwind;
+ {
+ *unwind_register = frame_saved_regs_register_unwind;
+ *unwind_pc = frame_saved_regs_pc_unwind;
+ }
}
/* Create an arbitrary (i.e. address specified by user) or innermost frame.
@@ -666,7 +693,8 @@
INIT_EXTRA_FRAME_INFO (0, fi);
/* Select/initialize an unwind function. */
- set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind);
+ set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind,
+ &fi->pc_unwind);
return fi;
}
@@ -874,7 +902,8 @@
(and probably other architectural information). The PC lets you
check things like the debug info at that point (dwarf2cfi?) and
use that to decide how the frame should be unwound. */
- set_unwind_by_pc (prev->pc, prev->frame, &prev->register_unwind);
+ set_unwind_by_pc (prev->pc, prev->frame, &prev->register_unwind,
+ &prev->pc_unwind);
find_pc_partial_function (prev->pc, &name,
(CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.29
diff -u -r1.29 frame.h
--- frame.h 5 Nov 2002 21:44:05 -0000 1.29
+++ frame.h 9 Nov 2002 00:36:22 -0000
@@ -46,6 +46,12 @@
int *realnump,
void *valuep);
+/* Same as for registers above, but return the address at which the
+ calling frame would resume. */
+
+typedef CORE_ADDR (frame_pc_unwind_ftype) (struct frame_info *frame,
+ void **unwind_cache);
+
/* Describe the saved registers of a frame. */
#if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS)
@@ -135,10 +141,18 @@
related unwind data. */
struct context *context;
- /* See description above. Return the register value for the
- previous frame. */
+ /* Unwind cache shared between the unwind functions - they had
+ better all agree as to the contents. */
+ void *unwind_cache;
+
+ /* See description above. The previous frame's registers. */
frame_register_unwind_ftype *register_unwind;
- void *register_unwind_cache;
+
+ /* See description above. The previous frame's resume address.
+ Save the previous PC in a local cache. */
+ frame_pc_unwind_ftype *pc_unwind;
+ int pc_unwind_cache_p;
+ CORE_ADDR pc_unwind_cache;
/* Pointers to the next (down, inner) and previous (up, outer)
frame_info's in the frame cache. */
@@ -340,6 +354,12 @@
struct frame_info *frame,
int regnum,
enum lval_type *lval);
+
+/* Unwind the PC. Strictly speaking return the resume address of the
+ calling frame. For GDB, `pc' is the resume address and not a
+ specific register. */
+
+extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
/* Unwind the stack frame so that the value of REGNUM, in the previous
frame is returned. If VALUEP is NULL, don't fetch/compute the
Index: stack.c
===================================================================
RCS file: /cvs/src/src/gdb/stack.c,v
retrieving revision 1.46
diff -u -r1.46 stack.c
--- stack.c 3 Oct 2002 22:34:58 -0000 1.46
+++ stack.c 9 Nov 2002 00:36:22 -0000
@@ -866,7 +866,7 @@
puts_filtered ("; ");
wrap_here (" ");
printf_filtered ("saved %s ", REGISTER_NAME (PC_REGNUM));
- print_address_numeric (FRAME_SAVED_PC (fi), 1, gdb_stdout);
+ print_address_numeric (frame_pc_unwind (fi), 1, gdb_stdout);
printf_filtered ("\n");
{