diff options
author | Andrew Cagney <cagney@redhat.com> | 2003-03-12 15:39:30 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2003-03-12 15:39:30 +0000 |
commit | 7a25a7c1cc419c2f4106843387e0c8be92471523 (patch) | |
tree | e5d344262a55505f1431211070aed2ee1a9667bf /gdb/frame.c | |
parent | c4d8feb262fa437232fb144da11b9f449d3b7715 (diff) | |
download | gdb-7a25a7c1cc419c2f4106843387e0c8be92471523.zip gdb-7a25a7c1cc419c2f4106843387e0c8be92471523.tar.gz gdb-7a25a7c1cc419c2f4106843387e0c8be92471523.tar.bz2 |
2003-03-12 Andrew Cagney <cagney@redhat.com>
Eliminate the need for POP_FRAME.
* frame.c (do_frame_unwind_register): New function.
(frame_pop): When no POP_FRAME, pop the frame using register
unwind and a scratch regcache.
(frame_saved_regs_pop): Delete function.
(trad_frame_unwinder): Update.
* d10v-tdep.c (d10v_frame_pop): Delete function.
(d10v_frame_unwind): Update.
* sentinel-frame.c (sentinel_frame_pop): Delete function.
(sentinel_frame_unwinder): Update.
* dummy-frame.c (dummy_frame_pop): Delete function.
(dummy_frame_unwind): Update.
* frame-unwind.h (frame_unwind_pop_ftype): Delete definition.
(struct frame_unwind): Update.
Diffstat (limited to 'gdb/frame.c')
-rw-r--r-- | gdb/frame.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/gdb/frame.c b/gdb/frame.c index 0bef68b..7af6ad1 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -185,16 +185,44 @@ frame_pc_unwind (struct frame_info *this_frame) return this_frame->pc_unwind_cache; } +static int +do_frame_unwind_register (void *src, int regnum, void *buf) +{ + frame_unwind_register (src, regnum, buf); + return 1; +} + void -frame_pop (struct frame_info *frame) +frame_pop (struct frame_info *this_frame) { - /* FIXME: cagney/2003-01-18: There is probably a chicken-egg problem - with passing in current_regcache. The pop function needs to be - written carefully so as to not overwrite registers whose [old] - values are needed to restore other registers. Instead, this code - should pass in a scratch cache and, as a second step, restore the - registers using that. */ - frame->unwind->pop (frame, &frame->unwind_cache, current_regcache); + struct regcache *scratch_regcache; + struct cleanup *cleanups; + + if (POP_FRAME_P ()) + { + /* A legacy architecture that has implemented a custom pop + function. All new architectures should instead be using the + generic code below. */ + POP_FRAME; + } + else + { + /* Make a copy of all the register values unwound from this + frame. Save them in a scratch buffer so that there isn't a + race betweening trying to extract the old values from the + current_regcache while, at the same time writing new values + into that same cache. */ + struct regcache *scratch = regcache_xmalloc (current_gdbarch); + struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch); + regcache_save (scratch, do_frame_unwind_register, this_frame); + /* Now copy those saved registers into the current regcache. + Here, regcache_cpy() calls regcache_restore(). */ + regcache_cpy (current_regcache, scratch); + do_cleanups (cleanups); + } + /* We've made right mess of GDB's local state, just discard + everything. */ + target_store_registers (-1); flush_cached_frames (); } @@ -768,16 +796,7 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache, id->base = base; } -static void -frame_saved_regs_pop (struct frame_info *fi, void **cache, - struct regcache *regcache) -{ - gdb_assert (POP_FRAME_P ()); - POP_FRAME; -} - const struct frame_unwind trad_frame_unwinder = { - frame_saved_regs_pop, frame_saved_regs_id_unwind, frame_saved_regs_register_unwind }; |