diff options
author | Andrew Cagney <cagney@redhat.com> | 2003-01-12 00:06:19 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2003-01-12 00:06:19 +0000 |
commit | 4ae8416d2a336001d4d80df949214b69b89bd713 (patch) | |
tree | 64d94774170241b660025fdbe3144ac5a8e1b122 | |
parent | 46c2fdb8b75e20f54bfe86eeecd57bd4ebdbad24 (diff) | |
download | gdb-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/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/frame.c | 112 | ||||
-rw-r--r-- | gdb/frame.h | 23 |
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); |