From 7a25a7c1cc419c2f4106843387e0c8be92471523 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Wed, 12 Mar 2003 15:39:30 +0000 Subject: [PATCH] 2003-03-12 Andrew Cagney 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. --- gdb/ChangeLog | 17 ++++++++++++++ gdb/d10v-tdep.c | 38 ------------------------------ gdb/dummy-frame.c | 32 -------------------------- gdb/frame-unwind.h | 16 ------------- gdb/frame.c | 55 +++++++++++++++++++++++++++++--------------- gdb/sentinel-frame.c | 9 -------- 6 files changed, 54 insertions(+), 113 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 037fc7476a..889570abfd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2003-03-12 Andrew Cagney + + 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. + 2003-03-11 Kevin Buettner * mips-tdep.c (mips_ecoff_reg_to_regnum): Rename to diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index 516cde468a..b60ce7fad3 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -1572,45 +1572,7 @@ d10v_frame_register_unwind (struct frame_info *frame, } -static void -d10v_frame_pop (struct frame_info *fi, void **unwind_cache, - struct regcache *regcache) -{ - struct d10v_unwind_cache *info = d10v_frame_unwind_cache (fi, unwind_cache); - CORE_ADDR fp; - int regnum; - char raw_buffer[8]; - - fp = get_frame_base (fi); - - /* now update the current registers with the old values */ - for (regnum = A0_REGNUM; regnum < A0_REGNUM + NR_A_REGS; regnum++) - { - frame_unwind_register (fi, regnum, raw_buffer); - regcache_cooked_write (regcache, regnum, raw_buffer); - } - for (regnum = 0; regnum < SP_REGNUM; regnum++) - { - frame_unwind_register (fi, regnum, raw_buffer); - regcache_cooked_write (regcache, regnum, raw_buffer); - } - frame_unwind_register (fi, PSW_REGNUM, raw_buffer); - regcache_cooked_write (regcache, PSW_REGNUM, raw_buffer); - - frame_unwind_register (fi, PC_REGNUM, raw_buffer); - regcache_cooked_write (regcache, PC_REGNUM, raw_buffer); - - store_unsigned_integer (raw_buffer, - register_size (current_gdbarch, SP_REGNUM), - fp + info->size); - regcache_cooked_write (regcache, SP_REGNUM, raw_buffer); - - target_store_registers (-1); - flush_cached_frames (); -} - static struct frame_unwind d10v_frame_unwind = { - d10v_frame_pop, d10v_frame_id_unwind, d10v_frame_register_unwind }; diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index 95c859889a..bf4a31c1ef 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -282,37 +282,6 @@ discard_innermost_dummy (struct dummy_frame **stack) xfree (tbd); } -/* Function: dummy_frame_pop. Restore the machine state from a saved - dummy stack frame. */ - -static void -dummy_frame_pop (struct frame_info *fi, void **cache, - struct regcache *regcache) -{ - struct dummy_frame *dummy = cached_find_dummy_frame (fi, cache); - - /* If it isn't, what are we even doing here? */ - gdb_assert (get_frame_type (fi) == DUMMY_FRAME); - - if (dummy == NULL) - error ("Can't pop dummy frame!"); - - /* Discard all dummy frames up-to but not including this one. */ - while (dummy_frame_stack != dummy) - discard_innermost_dummy (&dummy_frame_stack); - - /* Restore this one. */ - regcache_cpy (regcache, dummy->regcache); - flush_cached_frames (); - - /* Now discard it. */ - discard_innermost_dummy (&dummy_frame_stack); - - /* Note: target changed would be better. Registers, memory and - frame are all invalid. */ - flush_cached_frames (); -} - void generic_pop_dummy_frame (void) { @@ -390,7 +359,6 @@ dummy_frame_id_unwind (struct frame_info *frame, static struct frame_unwind dummy_frame_unwind = { - dummy_frame_pop, dummy_frame_id_unwind, dummy_frame_register_unwind }; diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index 7f4a866b1e..5d85efe9c0 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -76,27 +76,11 @@ typedef void (frame_unwind_id_ftype) (struct frame_info * frame, void **unwind_cache, struct frame_id * id); -/* Discard the frame by restoring the registers (in regcache) back to - that of the caller. */ -/* NOTE: cagney/2003-01-19: While at present the callers all pop each - frame in turn, the implementor should try to code things so that - any frame can be popped directly. */ -/* FIXME: cagney/2003-01-19: Since both FRAME and REGCACHE refer to a - common register cache, care must be taken when restoring the - registers. The `correct fix' is to first first save the registers - in a scratch cache, and second write that scratch cache back to to - the real register cache. */ - -typedef void (frame_unwind_pop_ftype) (struct frame_info *frame, - void **unwind_cache, - struct regcache *regcache); - struct frame_unwind { /* Should the frame's type go here? */ /* Should an attribute indicating the frame's address-in-block go here? */ - frame_unwind_pop_ftype *pop; frame_unwind_id_ftype *id; frame_unwind_reg_ftype *reg; }; diff --git a/gdb/frame.c b/gdb/frame.c index 0bef68b2a1..7af6ad1a71 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; } -void -frame_pop (struct frame_info *frame) +static int +do_frame_unwind_register (void *src, int regnum, void *buf) { - /* 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); + frame_unwind_register (src, regnum, buf); + return 1; +} + +void +frame_pop (struct frame_info *this_frame) +{ + 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 }; diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c index 2b1616a1f8..961e0300ea 100644 --- a/gdb/sentinel-frame.c +++ b/gdb/sentinel-frame.c @@ -83,17 +83,8 @@ sentinel_frame_id_unwind (struct frame_info *frame, id->pc = read_pc (); } -static void -sentinel_frame_pop (struct frame_info *frame, - void **cache, - struct regcache *regcache) -{ - internal_error (__FILE__, __LINE__, "Function sentinal_frame_pop called"); -} - const struct frame_unwind sentinel_frame_unwinder = { - sentinel_frame_pop, sentinel_frame_id_unwind, sentinel_frame_register_unwind };