summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-03-12 15:39:30 +0000
committerAndrew Cagney <cagney@redhat.com>2003-03-12 15:39:30 +0000
commit3ed1e96806cb7d524c9b941f4588de1b02b0675d (patch)
tree82506fd9b1d757a84a1acda8fa88ca769edce745
parent7de62df25bbabbf032c215eec345b30f5057d07b (diff)
downloadgdb-3ed1e96806cb7d524c9b941f4588de1b02b0675d.tar.gz
2003-03-12 Andrew Cagney <cagney@redhat.com>
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.
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/d10v-tdep.c38
-rw-r--r--gdb/dummy-frame.c32
-rw-r--r--gdb/frame-unwind.h16
-rw-r--r--gdb/frame.c53
-rw-r--r--gdb/sentinel-frame.c9
6 files changed, 53 insertions, 112 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 037fc7476ac..889570abfd6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2003-03-12 Andrew Cagney <cagney@redhat.com>
+
+ 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 <kevinb@redhat.com>
* mips-tdep.c (mips_ecoff_reg_to_regnum): Rename to
diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c
index 516cde468ad..b60ce7fad3a 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 95c859889a8..bf4a31c1ef4 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 7f4a866b1eb..5d85efe9c09 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 0bef68b2a11..7af6ad1a713 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;
}
+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 *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, &frame->unwind_cache, current_regcache);
+ 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 2b1616a1f8c..961e0300ea6 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
};