diff options
author | Andrew Cagney <cagney@redhat.com> | 2003-03-07 14:24:29 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2003-03-07 14:24:29 +0000 |
commit | 462569a5de2e62a99f85d65a55899de2456b81be (patch) | |
tree | a1ecaeb4e0562d04e6863dd8fbeb6a54c247618a | |
parent | f4ab3f81e8643c5b4c865df463f0cba56062ba96 (diff) | |
download | fsf-binutils-gdb-462569a5de2e62a99f85d65a55899de2456b81be.zip fsf-binutils-gdb-462569a5de2e62a99f85d65a55899de2456b81be.tar.gz fsf-binutils-gdb-462569a5de2e62a99f85d65a55899de2456b81be.tar.bz2 |
2003-03-06 Andrew Cagney <cagney@redhat.com>
* d10v-tdep.c (d10v_frame_pop): Delete function.
(d10v_frame_unwind): Update.
* frame.c: Include "reggroups.h".
* regcache.c (regcache_raw_write): Allow writes to a readonly
regcache.
* frame.c (frame_saved_regs_pop): Delete function.
(trad_frame_unwinder): Update
(frame_pop): Rewrite.
* 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.
-rw-r--r-- | gdb/ChangeLog | 26 | ||||
-rw-r--r-- | gdb/d10v-tdep.c | 35 | ||||
-rw-r--r-- | gdb/dummy-frame.c | 32 | ||||
-rw-r--r-- | gdb/frame-unwind.h | 24 | ||||
-rw-r--r-- | gdb/frame.c | 70 | ||||
-rw-r--r-- | gdb/regcache.c | 9 | ||||
-rw-r--r-- | gdb/sentinel-frame.c | 9 |
7 files changed, 78 insertions, 127 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b2510c3..8b9d6f6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,31 @@ 2003-03-06 Andrew Cagney <cagney@redhat.com> + * d10v-tdep.c (d10v_frame_pop): Delete function. + (d10v_frame_unwind): Update. + + * frame.c: Include "reggroups.h". + + * regcache.c (regcache_raw_write): Allow writes to a readonly + regcache. + + * frame.c (frame_saved_regs_pop): Delete function. + (trad_frame_unwinder): Update + (frame_pop): Rewrite. + + * 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. + * gdbarch.sh (POP): New method + * gdbarch.h, gdbarch.c: Re-generate. + + +2003-03-06 Andrew Cagney <cagney@redhat.com> + * gdbarch.sh (gdbarch_unwind_pc): New method. * gdbarch.h, gdbarch.c: Regenerate. * frame.c (frame_pc_unwind): Rewrite. Prefer gdbarch_unwind_pc, diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index 0fe222e..1848bf1 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -1578,42 +1578,7 @@ d10v_frame_register_unwind (struct frame_info *next_frame, lvalp, addrp, realnump, bufferp); } -static void -d10v_frame_pop (struct frame_info *next_frame, void **this_cache, - struct regcache *regcache) -{ - struct d10v_unwind_cache *info - = d10v_frame_unwind_cache (next_frame, this_cache); - CORE_ADDR fp; - int regnum; - char raw_buffer[8]; - - /* now update the current registers with the old values */ - for (regnum = A0_REGNUM; regnum < A0_REGNUM + NR_A_REGS; regnum++) - { - saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer); - regcache_cooked_write (regcache, regnum, raw_buffer); - } - for (regnum = 0; regnum < SP_REGNUM; regnum++) - { - saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer); - regcache_cooked_write (regcache, regnum, raw_buffer); - } - saved_regs_unwind (next_frame, info->saved_regs, PSW_REGNUM, raw_buffer); - regcache_cooked_write (regcache, PSW_REGNUM, raw_buffer); - - saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, raw_buffer); - regcache_cooked_write (regcache, PC_REGNUM, raw_buffer); - - saved_regs_unwind (next_frame, info->saved_regs, SP_REGNUM, raw_buffer); - 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 a44f451..c00e3c1 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -288,37 +288,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 *next_frame, void **this_cache, - struct regcache *regcache) -{ - struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_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) { @@ -405,7 +374,6 @@ dummy_frame_id_unwind (struct frame_info *next_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 4d00b2f..3efe1e2 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -102,35 +102,11 @@ typedef void (frame_unwind_reg_ftype) (struct frame_info *next_frame, CORE_ADDR *addrp, int *realnump, void *valuep); -/* Assuming the frame chain: (outer) prev <-> this <-> next (inner); - use the NEXT frame, and its register unwind method, to unwind THIS - frame's entire stack, writing PREV's frames register values into - REGCACHE. - - 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. - - FIXME: cagney/2003-03-04: Isn't this entire function redundant? - Shouldn't the code instead just iterate through the restore - reggroup unwinding those registers? */ - -typedef void (frame_unwind_pop_ftype) (struct frame_info *next_frame, - void **this_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 d61ec08..1a1c050 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -38,6 +38,7 @@ #include "frame-unwind.h" #include "command.h" #include "gdbcmd.h" +#include "reggroups.h" /* Flag to control debugging. */ @@ -135,9 +136,9 @@ frame_find_by_id (struct frame_id id) } CORE_ADDR -frame_pc_unwind (struct frame_info *next_frame) +frame_pc_unwind (struct frame_info *this_frame) { - if (!next_frame->pc_unwind_cache_p) + if (!this_frame->pc_unwind_cache_p) { CORE_ADDR pc; if (gdbarch_unwind_pc_p (current_gdbarch)) @@ -148,7 +149,7 @@ frame_pc_unwind (struct frame_info *next_frame) the value of this frame's PC (resume address). A typical implementation is no more than: - frame_unwind_register (next_frame, ISA_PC_REGNUM, buf); + frame_unwind_register (this_frame, ISA_PC_REGNUM, buf); return extract_address (buf, size of ISA_PC_REGNUM); Note: this method is very heavily dependent on a correct @@ -158,9 +159,9 @@ frame_pc_unwind (struct frame_info *next_frame) frame. This is all in stark contrast to the old FRAME_SAVED_PC which would try to directly handle all the different ways that a PC could be unwound. */ - pc = gdbarch_unwind_pc (current_gdbarch, next_frame); + pc = gdbarch_unwind_pc (current_gdbarch, this_frame); } - else if (next_frame->level < 0) + else if (this_frame->level < 0) { /* FIXME: cagney/2003-03-06: Old code and and a sentinel frame. Do like was always done. Fetch the PC's value @@ -175,26 +176,52 @@ frame_pc_unwind (struct frame_info *next_frame) frame. Do like was always done. Note that this method, unlike unwind_pc(), tries to handle all the different frame cases directly. It fails. */ - pc = FRAME_SAVED_PC (next_frame); + pc = FRAME_SAVED_PC (this_frame); } else internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method"); - next_frame->pc_unwind_cache = pc; - next_frame->pc_unwind_cache_p = 1; + this_frame->pc_unwind_cache = pc; + this_frame->pc_unwind_cache_p = 1; } - return next_frame->pc_unwind_cache; + return this_frame->pc_unwind_cache; } 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->next, &frame->unwind_cache, current_regcache); + if (POP_FRAME_P ()) + { + POP_FRAME; + } + else + { + /* Note, the dummy-frame code does something very similar to + this. Perhaphs a common routine is in order. */ + struct regcache *scratch_regcache = regcache_xmalloc (current_gdbarch); + struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch_regcache); + void *buf = alloca (max_register_size (current_gdbarch)); + int regnum; + + /* Copy over any registers (identified by their membership in + the save_reggroup) and mark them as valid. The full [0 + .. NUM_REGS+NUM_PSEUDO_REGS) range is checked since some + architectures need to save/restore `cooked' registers that + live in memory. */ + for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) + { + if (gdbarch_register_reggroup_p (current_gdbarch, regnum, + save_reggroup)) + { + frame_unwind_register (this_frame, regnum, buf); + regcache_cooked_write (scratch_regcache, regnum, buf); + } + } + + /* Now write the unwound registers, en-mass, back into the + regcache. */ + regcache_cpy (current_regcache, scratch_regcache); + do_cleanups (cleanups); + } flush_cached_frames (); } @@ -770,16 +797,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/regcache.c b/gdb/regcache.c index 3f2be7b..1b862e1 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -929,7 +929,14 @@ regcache_raw_write (struct regcache *regcache, int regnum, const void *buf) { gdb_assert (regcache != NULL && buf != NULL); gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers); - gdb_assert (!regcache->readonly_p); + + if (regcache->readonly_p) + { + memcpy (register_buffer (regcache, regnum), buf, + regcache->descr->sizeof_register[regnum]); + regcache->register_valid_p[regnum] = 1; + return; + } if (regcache->descr->legacy_p) { diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c index 046655f..8d92bfc 100644 --- a/gdb/sentinel-frame.c +++ b/gdb/sentinel-frame.c @@ -84,17 +84,8 @@ sentinel_frame_id_unwind (struct frame_info *next_frame, internal_error (__FILE__, __LINE__, "sentinel_frame_id_unwind called"); } -static void -sentinel_frame_pop (struct frame_info *next_frame, - void **this_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 }; |