diff options
author | Andrew Cagney <cagney@redhat.com> | 2003-03-10 21:00:56 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2003-03-10 21:00:56 +0000 |
commit | 271f220ec11e6d684deefd3462f4f2846e2fe1c2 (patch) | |
tree | 897caad12fe7c4650856a6418500abf79cb62355 | |
parent | 462569a5de2e62a99f85d65a55899de2456b81be (diff) | |
download | gdb-271f220ec11e6d684deefd3462f4f2846e2fe1c2.zip gdb-271f220ec11e6d684deefd3462f4f2846e2fe1c2.tar.gz gdb-271f220ec11e6d684deefd3462f4f2846e2fe1c2.tar.bz2 |
2003-03-10 Andrew Cagney <cagney@redhat.com>
* frame.c: Merge in posted frame_pop patch.
* regcache.h, regcache.c: Merge with mainline.
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/frame.c | 53 | ||||
-rw-r--r-- | gdb/regcache.c | 79 | ||||
-rw-r--r-- | gdb/regcache.h | 22 |
4 files changed, 92 insertions, 68 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8b9d6f6..8a1224f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2003-03-10 Andrew Cagney <cagney@redhat.com> + + * frame.c (frame_pop): Merge with mainline + (do_frame_unwind_register): Merge with mainline. + * regcache.h, regcache.c: Merge with mainline. + 2003-03-06 Andrew Cagney <cagney@redhat.com> * d10v-tdep.c (d10v_frame_pop): Delete function. diff --git a/gdb/frame.c b/gdb/frame.c index 1a1c050..b891463 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -38,7 +38,6 @@ #include "frame-unwind.h" #include "command.h" #include "gdbcmd.h" -#include "reggroups.h" /* Flag to control debugging. */ @@ -186,42 +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 *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 { - /* 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); + /* 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 (); } diff --git a/gdb/regcache.c b/gdb/regcache.c index 1b862e1..5475cf68 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -389,59 +389,79 @@ register_buffer (struct regcache *regcache, int regnum) } void -regcache_save (struct regcache *dst, struct regcache *src) +regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read, + void *src) { struct gdbarch *gdbarch = dst->descr->gdbarch; + void *buf = alloca (max_register_size (gdbarch)); int regnum; - /* The SRC and DST register caches had better belong to the same - architecture. */ - gdb_assert (src->descr->gdbarch == dst->descr->gdbarch); /* The DST should be `read-only', if it wasn't then the save would - end up trying to write the register values out through to the + end up trying to write the register values back out to the target. */ - gdb_assert (!src->readonly_p); gdb_assert (dst->readonly_p); /* Clear the dest. */ memset (dst->registers, 0, dst->descr->sizeof_cooked_registers); memset (dst->register_valid_p, 0, dst->descr->sizeof_cooked_register_valid_p); /* 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. */ + 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 < dst->descr->nr_cooked_registers; regnum++) { if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup)) { - regcache_cooked_read (src, regnum, register_buffer (dst, regnum)); - dst->register_valid_p[regnum] = 1; + int valid = cooked_read (src, regnum, buf); + if (valid) + { + memcpy (register_buffer (dst, regnum), buf, + register_size (gdbarch, regnum)); + dst->register_valid_p[regnum] = 1; + } } } } void -regcache_restore (struct regcache *dst, struct regcache *src) +regcache_restore (struct regcache *dst, + regcache_cooked_read_ftype *cooked_read, + void *src) { struct gdbarch *gdbarch = dst->descr->gdbarch; + void *buf = alloca (max_register_size (gdbarch)); int regnum; - gdb_assert (src->descr->gdbarch == dst->descr->gdbarch); + /* The dst had better not be read-only. If it is, the `restore' + doesn't make much sense. */ gdb_assert (!dst->readonly_p); - gdb_assert (src->readonly_p); /* Copy over any registers, being careful to only restore those that - were both saved and need to be restored. 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 < src->descr->nr_cooked_registers; regnum++) + were both saved and need to be restored. 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 < dst->descr->nr_cooked_registers; regnum++) { - if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup) - && src->register_valid_p[regnum]) + if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup)) { - regcache_cooked_write (dst, regnum, register_buffer (src, regnum)); + int valid = cooked_read (src, regnum, buf); + if (valid) + regcache_cooked_write (dst, regnum, buf); } } } +static int +do_cooked_read (void *src, int regnum, void *buf) +{ + struct regcache *regcache = src; + if (!regcache_valid_p (regcache, regnum) + && regcache->readonly_p) + /* Don't even think about fetching a register from a read-only + cache when the register isn't yet valid. There isn't a target + from which the register value can be fetched. */ + return 0; + regcache_cooked_read (regcache, regnum, buf); + return 1; +} + + void regcache_cpy (struct regcache *dst, struct regcache *src) { @@ -452,9 +472,9 @@ regcache_cpy (struct regcache *dst, struct regcache *src) gdb_assert (src != dst); gdb_assert (src->readonly_p || dst->readonly_p); if (!src->readonly_p) - regcache_save (dst, src); + regcache_save (dst, do_cooked_read, src); else if (!dst->readonly_p) - regcache_restore (dst, src); + regcache_restore (dst, do_cooked_read, src); else regcache_cpy_no_passthrough (dst, src); } @@ -929,14 +949,7 @@ 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); - - if (regcache->readonly_p) - { - memcpy (register_buffer (regcache, regnum), buf, - regcache->descr->sizeof_register[regnum]); - regcache->register_valid_p[regnum] = 1; - return; - } + gdb_assert (!regcache->readonly_p); if (regcache->descr->legacy_p) { diff --git a/gdb/regcache.h b/gdb/regcache.h index ee10505..dd62938 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -155,15 +155,19 @@ extern int max_register_size (struct gdbarch *gdbarch); extern int register_size (struct gdbarch *gdbarch, int regnum); -/* Save/restore a register cache. The registers saved/restored is - determined by the save_reggroup and restore_reggroup (although you - can't restore a register that wasn't saved as well :-). You can - only save to a read-only cache (default from regcache_xmalloc()) - from a live cache and you can only restore from a read-only cache - to a live cache. */ - -extern void regcache_save (struct regcache *dst, struct regcache *src); -extern void regcache_restore (struct regcache *dst, struct regcache *src); +/* Save/restore a register cache. The set of registers saved / + restored into the DST regcache determined by the save_reggroup / + restore_reggroup respectively. COOKED_READ returns zero iff the + register's value can't be returned. */ + +typedef int (regcache_cooked_read_ftype) (void *src, int regnum, void *buf); + +extern void regcache_save (struct regcache *dst, + regcache_cooked_read_ftype *cooked_read, + void *src); +extern void regcache_restore (struct regcache *dst, + regcache_cooked_read_ftype *cooked_read, + void *src); /* Copy/duplicate the contents of a register cache. By default, the operation is pass-through. Writes to DST and reads from SRC will |