This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[offbyone] Merge in posted frame_pop patch
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Mon, 10 Mar 2003 16:02:43 -0500
- Subject: [offbyone] Merge in posted frame_pop patch
Just FYI,
This merges the just posted frame_pop patch (and the associated regcache
change) into my offbyone branch.
Andrew
2003-03-10 Andrew Cagney <cagney at redhat dot com>
* frame.c: Merge in posted frame_pop patch.
* regcache.h, regcache.c: Merge with mainline.
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.71.2.5
diff -u -r1.71.2.5 frame.c
--- frame.c 7 Mar 2003 14:24:29 -0000 1.71.2.5
+++ frame.c 10 Mar 2003 20:57:58 -0000
@@ -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 @@
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 ();
}
Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.71.2.1
diff -u -r1.71.2.1 regcache.c
--- regcache.c 7 Mar 2003 14:24:29 -0000 1.71.2.1
+++ regcache.c 10 Mar 2003 20:58:00 -0000
@@ -389,59 +389,79 @@
}
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 @@
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 @@
{
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)
{
Index: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.29
diff -u -r1.29 regcache.h
--- regcache.h 28 Feb 2003 17:47:43 -0000 1.29
+++ regcache.h 10 Mar 2003 20:58:00 -0000
@@ -155,15 +155,19 @@
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. */
+/* 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. */
-extern void regcache_save (struct regcache *dst, struct regcache *src);
-extern void regcache_restore (struct regcache *dst, struct regcache *src);
+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