aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-03-07 14:24:29 +0000
committerAndrew Cagney <cagney@redhat.com>2003-03-07 14:24:29 +0000
commit462569a5de2e62a99f85d65a55899de2456b81be (patch)
treea1ecaeb4e0562d04e6863dd8fbeb6a54c247618a
parentf4ab3f81e8643c5b4c865df463f0cba56062ba96 (diff)
downloadfsf-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/ChangeLog26
-rw-r--r--gdb/d10v-tdep.c35
-rw-r--r--gdb/dummy-frame.c32
-rw-r--r--gdb/frame-unwind.h24
-rw-r--r--gdb/frame.c70
-rw-r--r--gdb/regcache.c9
-rw-r--r--gdb/sentinel-frame.c9
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
};