This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[unwind-20030108-branch] Make certain that the duplicated PC's arein sync
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Sat, 11 Jan 2003 18:17:18 -0500
- Subject: [unwind-20030108-branch] Make certain that the duplicated PC's arein sync
Hello,
Some cleanups:
- make certain that the PC(s) is always in sync. Once `struct
frame_info' is made opaque, the redundency can be removed.
- to keep things simple, have sentinel frame's next loop back on itself.
Andrew
2003-01-11 Andrew Cagney <ac131313@redhat.com>
* frame.c (deprecated_update_frame_pc_hack)
(deprecated_update_frame_base_hack): Also update the next frame's
ID/PC cache.
(create_sentinel_frame): Link the sentinel frame to itself.
* frame.h: Expand comments describing update PC and FP hacks.
* frame.c (get_prev_frame): Add comment explaining why
INIT_EXTRA_FRAME_INFO call is needed.
(legacy_get_prev_frame): Use get_next_frame.
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.56.2.2
diff -u -r1.56.2.2 frame.c
--- frame.c 10 Jan 2003 21:56:43 -0000 1.56.2.2
+++ frame.c 11 Jan 2003 21:15:31 -0000
@@ -57,6 +57,29 @@
}
}
+struct frame_id
+frame_id_unwind (struct frame_info *frame)
+{
+ if (!frame->id_unwind_cache_p)
+ {
+ frame->id_unwind (frame, &frame->unwind_cache, &frame->id_unwind_cache);
+ frame->id_unwind_cache_p = 1;
+ }
+ return frame->id_unwind_cache;
+}
+
+void
+deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
+{
+ /* See comment in "frame.h". */
+ frame->frame = base;
+ gdb_assert (frame->next != NULL);
+ gdb_assert (frame->next->id_unwind_cache_p);
+ gdb_assert (frame->next->pc_unwind_cache_p);
+ frame->next->id_unwind_cache.base = base;
+ frame->next->id_unwind_cache.pc = frame->next->pc_unwind_cache;
+}
+
const struct frame_id null_frame_id; /* All zeros. */
struct frame_id
@@ -125,28 +148,6 @@
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;
-}
-
-struct frame_id
-frame_id_unwind (struct frame_info *frame)
-{
- if (!frame->id_unwind_cache_p)
- {
- frame->id_unwind (frame, &frame->unwind_cache, &frame->id_unwind_cache);
- frame->id_unwind_cache_p = 1;
- }
- return frame->id_unwind_cache;
-}
-
void
frame_register_unwind (struct frame_info *frame, int regnum,
@@ -411,6 +412,10 @@
frame->pc_unwind = sentinel_frame_pc_unwind;
frame->id_unwind = sentinel_frame_id_unwind;
frame->register_unwind = sentinel_frame_register_unwind;
+ /* Link this frame back to itself. The frame is self referential
+ (the unwound PC is the same as the pc for instance, so make it
+ so. */
+ frame->next = frame;
/* Always unwind the PC as part of creating this frame. This
ensures that the frame's PC points into something valid. */
/* FIXME: cagney/2003-01-10: Problem here. Unwinding a sentinel
@@ -686,6 +691,9 @@
struct frame_info *prev;
int fromleaf;
+ /* This code doesn't work with the sentinal frame. */
+ gdb_assert (next_frame->level >= 0);
+
/* On some machines it is possible to call a function without
setting up a stack frame for it. On these machines, we
define this macro to take two args; a frameinfo pointer
@@ -695,7 +703,7 @@
/* Still don't want to worry about this except on the innermost
frame. This macro will set FROMLEAF if NEXT_FRAME is a frameless
function invocation. */
- if (next_frame->next == NULL)
+ if (get_next_frame (next_frame) == NULL)
/* FIXME: 2002-11-09: Frameless functions can occure anywhere in
the frame chain, not just the inner most frame! The generic,
per-architecture, frame code should handle this and the below
@@ -906,7 +914,15 @@
NOTE: cagney/2003-01-10: Talk about code behaving badly. Check
block_innermost_frame(). It does the sequence: frame = NULL;
while (1) { frame = get_prev_frame (frame); .... }. Ulgh! Why
- it couldn't be written better, I don't know. */
+ it couldn't be written better, I don't know.
+
+ NOTE: cagney/2003-01-11: I suspect what is happening is
+ block_innermost_frame() is, when the target has no state
+ (registers, memory, ...), still calling this function. The
+ assumption being that this function will return NULL indicating
+ that a frame isn't possible, rather than checking that the target
+ has state and then calling get_current_frame() and
+ get_prev_frame(). This is a guess mind. */
if (next_frame == NULL)
{
/* NOTE: cagney/2002-11-09: There was a code segment here that
@@ -957,7 +973,7 @@
if ((DEPRECATED_INIT_FRAME_PC_P ()
|| DEPRECATED_INIT_FRAME_PC_FIRST_P ())
&& next_frame->level >= 0)
- /* Don't try to unwind the sentinal frame using the old code. */
+ /* Don't try to unwind the sentinal frame using the old code. */
return legacy_get_prev_frame (next_frame);
/* Allocate the new frame but do not wire it in. Some (bad) code in
@@ -1024,6 +1040,8 @@
Instead of initializing extra info, all frames will use the
frame_cache (passed to the unwind functions) to store extra frame
info. */
+ /* NOTE: cagney/2003-01-11: Legacy targets, when having the sentinel
+ frame unwound, rely on this call. */
if (INIT_EXTRA_FRAME_INFO_P ())
/* NOTE: This code doesn't bother trying to sort out frameless
functions. That is left to the target. */
@@ -1035,9 +1053,39 @@
CORE_ADDR
get_frame_pc (struct frame_info *frame)
{
+ /* This should just call frame_pc_unwind(). */
return frame->pc;
}
+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
+deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
+{
+ /* See comment in "frame.h". */
+ frame->pc = pc;
+ gdb_assert (frame->next != NULL);
+ /* Got a bucket? Legacy code that handles dummy frames directly
+ doesn't always use the unwind function to determine the dummy
+ frame's PC. Consequently, it is possible for this function to be
+ called when the next frame's pc unwind cache isn't valid. */
+ if (frame->next->pc_unwind_cache_p)
+ frame->next->pc_unwind_cache = pc;
+ /* Since the PC is unwound before the frame ID, only need to update
+ the frame ID's PC when it has been unwound. */
+ if (frame->next->id_unwind_cache_p)
+ frame->next->id_unwind_cache.pc = pc;
+}
+
static int
pc_notcurrent (struct frame_info *frame)
{
@@ -1138,20 +1186,6 @@
{
fi->extra_info = frame_obstack_zalloc (size);
return fi->extra_info;
-}
-
-void
-deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
-{
- /* See comment in "frame.h". */
- frame->pc = pc;
-}
-
-void
-deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
-{
- /* See comment in "frame.h". */
- frame->frame = base;
}
void
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.59.2.1
diff -u -r1.59.2.1 frame.h
--- frame.h 10 Jan 2003 15:22:39 -0000 1.59.2.1
+++ frame.h 11 Jan 2003 21:16:37 -0000
@@ -663,17 +663,22 @@
extern CORE_ADDR *frame_saved_regs_zalloc (struct frame_info *);
extern CORE_ADDR *get_frame_saved_regs (struct frame_info *);
-/* FIXME: cagney/2002-12-06: Has the PC in the current frame changed?
- "infrun.c", Thanks to DECR_PC_AFTER_BREAK, can change the PC after
- the initial frame create. This puts things back in sync. */
+/* FIXME: cagney/2003-01-11: Fix up this frame's frame ID / PC (which
+ is cached in the next frame). The problem here is with read_fp()/
+ FRAME_CHAIN() and read_pc() / FRAME_SAVED_PC. Legacy code, instead
+ of returning the correct frame base from the word go, returns a
+ draft frame base and then fixes it up in INIT_FRAME_PC,
+ INIT_FRAME_PC_FIRST or INIT_EXTRA_FRAME_INFO. Back patch the next
+ frame's frame ID so that it will now return the correct id.
+
+ For the PC, the problems are caused by DECR_PC_AFTER_BREAK and
+ DECR_PC_AFTER_HW_BREAK.
+
+ For the FP, the problems are caused by GDB requesting the FP
+ instead of the SP and, as a consequence, code trying to avoid the
+ overhead of unnecessary prologue analysis. */
extern void deprecated_update_frame_pc_hack (struct frame_info *frame,
CORE_ADDR pc);
-
-/* FIXME: cagney/2002-12-18: Has the frame's base changed? Or to be
- more exact, whas that initial guess at the frame's base as returned
- by read_fp() wrong. If it was, fix it. This shouldn't be
- necessary since the code should be getting the frame's base correct
- from the outset. */
extern void deprecated_update_frame_base_hack (struct frame_info *frame,
CORE_ADDR base);