summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-01-12 00:06:19 +0000
committerAndrew Cagney <cagney@redhat.com>2003-01-12 00:06:19 +0000
commit4ae8416d2a336001d4d80df949214b69b89bd713 (patch)
tree64d94774170241b660025fdbe3144ac5a8e1b122
parent46c2fdb8b75e20f54bfe86eeecd57bd4ebdbad24 (diff)
downloadgdb-4ae8416d2a336001d4d80df949214b69b89bd713.tar.gz
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.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/frame.c112
-rw-r--r--gdb/frame.h23
3 files changed, 98 insertions, 48 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7f562ccd1ed..41389f08a72 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+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.
+
2003-01-10 Andrew Cagney <ac131313@redhat.com>
* frame.c (create_sentinel_frame): Initialize sentinel frame's PC.
diff --git a/gdb/frame.c b/gdb/frame.c
index 0bac5808a2d..daa243a8478 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -57,6 +57,29 @@ get_frame_id (struct frame_info *fi)
}
}
+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 @@ frame_find_by_id (struct frame_id id)
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 @@ create_sentinel_frame (struct regcache *regcache)
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 @@ legacy_get_prev_frame (struct frame_info *next_frame)
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 @@ legacy_get_prev_frame (struct frame_info *next_frame)
/* 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 @@ get_prev_frame (struct frame_info *next_frame)
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 @@ get_prev_frame (struct frame_info *next_frame)
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 @@ get_prev_frame (struct frame_info *next_frame)
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 @@ get_prev_frame (struct frame_info *next_frame)
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)
{
@@ -1141,20 +1189,6 @@ frame_extra_info_zalloc (struct frame_info *fi, long size)
}
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
deprecated_set_frame_saved_regs_hack (struct frame_info *frame,
CORE_ADDR *saved_regs)
{
diff --git a/gdb/frame.h b/gdb/frame.h
index 98dace6cb1e..f77a05edf63 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -663,17 +663,22 @@ extern struct frame_extra_info *get_frame_extra_info (struct frame_info *fi);
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);