This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [patch rfc] per-architecture unwind_pc()
Date: Thu, 06 Mar 2003 14:00:13 -0500
From: Andrew Cagney <ac131313 at redhat dot com>
The attached patch replaces the per-frame pc_unwind() method with the=20
per-architecture, frame agnostic, unwind_pc() method:
The doco part is okay with me, but please make sure there are two
spaces after a period that ends a sentence.
Ok, done.
The atached is exactly what I checked in.
Andrew
2003-03-10 Andrew Cagney <cagney at redhat dot com>
* gdbarch.sh (gdbarch_unwind_pc): New method.
* gdbarch.h, gdbarch.c: Regenerate.
* frame.c (frame_pc_unwind): Rewrite. Prefer gdbarch_unwind_pc,
but use read_pc and FRAME_SAVED_PC as fall backs.
(frame_saved_regs_pc_unwind): Delete function.
(trad_frame_unwinder): Update.
* frame-unwind.h (frame_unwind_pc_ftype): Delete declaration.
(struct frame_unwind): Update.
* dummy-frame.c (dummy_frame_pc_unwind): Delete function.
(dummy_frame_unwind): Update.
* sentinel-frame.c (sentinel_frame_pc_unwind): Delete function.
(sentinel_frame_unwinder): Update.
* d10v-tdep.c (d10v_frame_pc_unwind): Delete function.
(d10v_frame_unwind): Update.
(d10v_unwind_pc): New function.
(d10v_gdbarch_init): Set unwind_pc.
Index: doc/ChangeLog
2003-03-10 Andrew Cagney <cagney at redhat dot com>
* gdbint.texinfo (Target Architecture Definition): Cross reference
FRAME_SAVED_PC to unwind_pc. Document unwind_pc.
Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.84
diff -u -r1.84 d10v-tdep.c
--- d10v-tdep.c 10 Mar 2003 14:43:15 -0000 1.84
+++ d10v-tdep.c 10 Mar 2003 14:58:54 -0000
@@ -1445,13 +1445,12 @@
}
}
-
static CORE_ADDR
-d10v_frame_pc_unwind (struct frame_info *frame,
- void **cache)
+d10v_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache);
- return info->return_pc;
+ ULONGEST pc;
+ frame_unwind_unsigned_register (next_frame, PC_REGNUM, &pc);
+ return d10v_make_iaddr (pc);
}
/* Given a GDB frame, determine the address of the calling function's
@@ -1612,7 +1611,6 @@
static struct frame_unwind d10v_frame_unwind = {
d10v_frame_pop,
- d10v_frame_pc_unwind,
d10v_frame_id_unwind,
d10v_frame_register_unwind
};
@@ -1779,6 +1777,9 @@
/* Methods for saving / extracting a dummy frame's ID. */
set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id);
set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
+
+ /* Return the unwound PC value. */
+ set_gdbarch_unwind_pc (gdbarch, d10v_unwind_pc);
return gdbarch;
}
Index: dummy-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.c,v
retrieving revision 1.10
diff -u -r1.10 dummy-frame.c
--- dummy-frame.c 19 Jan 2003 17:39:16 -0000 1.10
+++ dummy-frame.c 10 Mar 2003 14:58:54 -0000
@@ -370,23 +370,6 @@
}
}
-/* Assuming that FRAME is a dummy, return the resume address for the
- previous frame. */
-
-static CORE_ADDR
-dummy_frame_pc_unwind (struct frame_info *frame,
- void **cache)
-{
- struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
- /* Oops! In a dummy-frame but can't find the stack dummy. Pretend
- that the frame doesn't unwind. Should this function instead
- return a has-no-caller indication? */
- if (dummy == NULL)
- return 0;
- return dummy->pc;
-}
-
-
/* Assuming that FRAME is a dummy, return the ID of the calling frame
(the frame that the dummy has the saved state of). */
@@ -408,7 +391,6 @@
static struct frame_unwind dummy_frame_unwind =
{
dummy_frame_pop,
- dummy_frame_pc_unwind,
dummy_frame_id_unwind,
dummy_frame_register_unwind
};
Index: frame-unwind.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.h,v
retrieving revision 1.3
diff -u -r1.3 frame-unwind.h
--- frame-unwind.h 19 Jan 2003 17:39:16 -0000 1.3
+++ frame-unwind.h 10 Mar 2003 14:58:54 -0000
@@ -69,12 +69,6 @@
CORE_ADDR *addrp,
int *realnump, void *valuep);
-/* Same as for registers above, but return the address at which the
- calling frame would resume. */
-
-typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info * frame,
- void **unwind_cache);
-
/* Same as for registers above, but return the ID of the frame that
called this one. */
@@ -103,7 +97,6 @@
/* Should an attribute indicating the frame's address-in-block go
here? */
frame_unwind_pop_ftype *pop;
- frame_unwind_pc_ftype *pc;
frame_unwind_id_ftype *id;
frame_unwind_reg_ftype *reg;
};
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.74
diff -u -r1.74 frame.c
--- frame.c 5 Mar 2003 23:14:17 -0000 1.74
+++ frame.c 10 Mar 2003 14:58:55 -0000
@@ -135,14 +135,54 @@
}
CORE_ADDR
-frame_pc_unwind (struct frame_info *frame)
+frame_pc_unwind (struct frame_info *this_frame)
{
- if (!frame->pc_unwind_cache_p)
+ if (!this_frame->pc_unwind_cache_p)
{
- frame->pc_unwind_cache = frame->unwind->pc (frame, &frame->unwind_cache);
- frame->pc_unwind_cache_p = 1;
+ CORE_ADDR pc;
+ if (gdbarch_unwind_pc_p (current_gdbarch))
+ {
+ /* The right way. The `pure' way. The one true way. This
+ method depends solely on the register-unwind code to
+ determine the value of registers in THIS frame, and hence
+ the value of this frame's PC (resume address). A typical
+ implementation is no more than:
+
+ frame_unwind_register (this_frame, ISA_PC_REGNUM, buf);
+ return extract_address (buf, size of ISA_PC_REGNUM);
+
+ Note: this method is very heavily dependent on a correct
+ register-unwind implementation, it pays to fix that
+ method first; this method is frame type agnostic, since
+ it only deals with register values, it works with any
+ frame. This is all in stark contrast to the old
+ FRAME_SAVED_PC which would try to directly handle all the
+ different ways that a PC could be unwound. */
+ pc = gdbarch_unwind_pc (current_gdbarch, this_frame);
+ }
+ else if (this_frame->level < 0)
+ {
+ /* FIXME: cagney/2003-03-06: Old code and and a sentinel
+ frame. Do like was always done. Fetch the PC's value
+ direct from the global registers array (via read_pc).
+ This assumes that this frame belongs to the current
+ global register cache. The assumption is dangerous. */
+ pc = read_pc ();
+ }
+ else if (FRAME_SAVED_PC_P ())
+ {
+ /* FIXME: cagney/2003-03-06: Old code, but not a sentinel
+ frame. Do like was always done. Note that this method,
+ unlike unwind_pc(), tries to handle all the different
+ frame cases directly. It fails. */
+ pc = FRAME_SAVED_PC (this_frame);
+ }
+ else
+ internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method");
+ this_frame->pc_unwind_cache = pc;
+ this_frame->pc_unwind_cache_p = 1;
}
- return frame->pc_unwind_cache;
+ return this_frame->pc_unwind_cache;
}
void
@@ -667,13 +707,6 @@
bufferp);
}
-static CORE_ADDR
-frame_saved_regs_pc_unwind (struct frame_info *frame, void **cache)
-{
- gdb_assert (FRAME_SAVED_PC_P ());
- return FRAME_SAVED_PC (frame);
-}
-
static void
frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache,
struct frame_id *id)
@@ -745,7 +778,6 @@
const struct frame_unwind trad_frame_unwinder = {
frame_saved_regs_pop,
- frame_saved_regs_pc_unwind,
frame_saved_regs_id_unwind,
frame_saved_regs_register_unwind
};
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.187
diff -u -r1.187 gdbarch.c
--- gdbarch.c 5 Mar 2003 23:14:17 -0000 1.187
+++ gdbarch.c 10 Mar 2003 14:58:55 -0000
@@ -242,6 +242,7 @@
gdbarch_frame_chain_ftype *frame_chain;
gdbarch_frame_chain_valid_ftype *frame_chain_valid;
gdbarch_frame_saved_pc_ftype *frame_saved_pc;
+ gdbarch_unwind_pc_ftype *unwind_pc;
gdbarch_frame_args_address_ftype *frame_args_address;
gdbarch_frame_locals_address_ftype *frame_locals_address;
gdbarch_saved_pc_after_call_ftype *saved_pc_after_call;
@@ -433,6 +434,7 @@
0,
0,
0,
+ 0,
generic_in_function_epilogue_p,
construct_inferior_arguments,
0,
@@ -759,6 +761,7 @@
/* Skip verify of frame_chain, has predicate */
/* Skip verify of frame_chain_valid, has predicate */
/* Skip verify of frame_saved_pc, has predicate */
+ /* Skip verify of unwind_pc, has predicate */
/* Skip verify of frame_args_address, invalid_p == 0 */
/* Skip verify of frame_locals_address, invalid_p == 0 */
if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
@@ -2578,6 +2581,14 @@
fprintf_unfiltered (file,
"gdbarch_dump: unwind_dummy_id = 0x%08lx\n",
(long) current_gdbarch->unwind_dummy_id);
+ if (GDB_MULTI_ARCH)
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_unwind_pc_p() = %d\n",
+ gdbarch_unwind_pc_p (current_gdbarch));
+ if (GDB_MULTI_ARCH)
+ fprintf_unfiltered (file,
+ "gdbarch_dump: unwind_pc = 0x%08lx\n",
+ (long) current_gdbarch->unwind_pc);
#ifdef USE_STRUCT_CONVENTION
fprintf_unfiltered (file,
"gdbarch_dump: %s # %s\n",
@@ -4843,6 +4854,32 @@
gdbarch_frame_saved_pc_ftype frame_saved_pc)
{
gdbarch->frame_saved_pc = frame_saved_pc;
+}
+
+int
+gdbarch_unwind_pc_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->unwind_pc != 0;
+}
+
+CORE_ADDR
+gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ gdb_assert (gdbarch != NULL);
+ if (gdbarch->unwind_pc == 0)
+ internal_error (__FILE__, __LINE__,
+ "gdbarch: gdbarch_unwind_pc invalid");
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_pc called\n");
+ return gdbarch->unwind_pc (gdbarch, next_frame);
+}
+
+void
+set_gdbarch_unwind_pc (struct gdbarch *gdbarch,
+ gdbarch_unwind_pc_ftype unwind_pc)
+{
+ gdbarch->unwind_pc = unwind_pc;
}
CORE_ADDR
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.150
diff -u -r1.150 gdbarch.h
--- gdbarch.h 10 Mar 2003 14:54:58 -0000 1.150
+++ gdbarch.h 10 Mar 2003 14:58:56 -0000
@@ -2228,6 +2228,8 @@
#endif
#endif
+/* NOTE: FRAME_SAVED_PC is replaced by UNWIND_PC */
+
#if defined (FRAME_SAVED_PC)
/* Legacy for systems yet to multi-arch FRAME_SAVED_PC */
#if !defined (FRAME_SAVED_PC_P)
@@ -2264,6 +2266,12 @@
#define FRAME_SAVED_PC(fi) (gdbarch_frame_saved_pc (current_gdbarch, fi))
#endif
#endif
+
+extern int gdbarch_unwind_pc_p (struct gdbarch *gdbarch);
+
+typedef CORE_ADDR (gdbarch_unwind_pc_ftype) (struct gdbarch *gdbarch, struct frame_info *next_frame);
+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);
/* Default (function) for non- multi-arch platforms. */
#if (!GDB_MULTI_ARCH) && !defined (FRAME_ARGS_ADDRESS)
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.202
diff -u -r1.202 gdbarch.sh
--- gdbarch.sh 8 Mar 2003 22:16:45 -0000 1.202
+++ gdbarch.sh 10 Mar 2003 14:58:58 -0000
@@ -591,7 +591,9 @@
f:2:FRAMELESS_FUNCTION_INVOCATION:int:frameless_function_invocation:struct frame_info *fi:fi:::generic_frameless_function_invocation_not::0
F:2:FRAME_CHAIN:CORE_ADDR:frame_chain:struct frame_info *frame:frame::0:0
F:2:FRAME_CHAIN_VALID:int:frame_chain_valid:CORE_ADDR chain, struct frame_info *thisframe:chain, thisframe::0:0
+# NOTE: FRAME_SAVED_PC is replaced by UNWIND_PC
F:2:FRAME_SAVED_PC:CORE_ADDR:frame_saved_pc:struct frame_info *fi:fi::0:0
+M::UNWIND_PC:CORE_ADDR:unwind_pc: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:2:SAVED_PC_AFTER_CALL:CORE_ADDR:saved_pc_after_call:struct frame_info *frame:frame::0:0
Index: sentinel-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/sentinel-frame.c,v
retrieving revision 1.2
diff -u -r1.2 sentinel-frame.c
--- sentinel-frame.c 27 Jan 2003 21:41:41 -0000 1.2
+++ sentinel-frame.c 10 Mar 2003 14:58:58 -0000
@@ -70,17 +70,6 @@
}
}
-CORE_ADDR
-sentinel_frame_pc_unwind (struct frame_info *frame,
- void **cache)
-{
- /* FIXME: cagney/2003-01-08: This should be using a per-architecture
- method that doesn't suffer from DECR_PC_AFTER_BREAK problems.
- Such a method would take unwind_cache, regcache and stop reason
- parameters. */
- return read_pc ();
-}
-
void
sentinel_frame_id_unwind (struct frame_info *frame,
void **cache,
@@ -105,7 +94,6 @@
const struct frame_unwind sentinel_frame_unwinder =
{
sentinel_frame_pop,
- sentinel_frame_pc_unwind,
sentinel_frame_id_unwind,
sentinel_frame_register_unwind
};
Index: doc/gdbint.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
retrieving revision 1.127
diff -u -r1.127 gdbint.texinfo
--- doc/gdbint.texinfo 5 Mar 2003 23:14:18 -0000 1.127
+++ doc/gdbint.texinfo 10 Mar 2003 14:59:12 -0000
@@ -3270,8 +3270,28 @@
@item FRAME_SAVED_PC(@var{frame})
@findex FRAME_SAVED_PC
-Given @var{frame}, return the pc saved there. This is the return
-address.
+ at anchor{FRAME_SAVED_PC} Given @var{frame}, return the pc saved there.
+This is the return address.
+
+This method is deprecated. @xref{unwind_pc}.
+
+ at item CORE_ADDR unwind_pc (struct frame_info * at var{this_frame})
+ at findex unwind_pc
+ at anchor{unwind_pc} Return the instruction address, in @var{this_frame}'s
+caller, at which execution will resume after @var{this_frame} returns.
+This is commonly refered to as the return address.
+
+The implementation, which must be frame agnostic (work with any frame),
+is typically no more than:
+
+ at smallexample
+ULONGEST pc;
+frame_unwind_unsigned_register (this_frame, D10V_PC_REGNUM, &pc);
+return d10v_make_iaddr (pc);
+ at end smallexample
+
+ at noindent
+ at xref{FRAME_SAVED_PC}, which this method replaces.
@item FUNCTION_EPILOGUE_SIZE
@findex FUNCTION_EPILOGUE_SIZE