summaryrefslogtreecommitdiff
path: root/gdb/dummy-frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dummy-frame.c')
-rw-r--r--gdb/dummy-frame.c87
1 files changed, 76 insertions, 11 deletions
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
index fab10c08e02..5b638306fd3 100644
--- a/gdb/dummy-frame.c
+++ b/gdb/dummy-frame.c
@@ -28,6 +28,7 @@
#include "frame.h"
#include "inferior.h"
#include "gdb_assert.h"
+#include "frame-unwind.h"
/* Dummy frame. This saves the processor state just prior to setting
up the inferior function call. Older targets save the registers
@@ -269,8 +270,48 @@ generic_pop_current_frame (void (*popper) (struct frame_info * frame))
(*popper) (frame);
}
-/* Function: pop_dummy_frame
- Restore the machine state from a saved dummy stack frame. */
+/* Discard the innermost dummy frame from the dummy frame stack
+ (passed in as a parameter). */
+
+static void
+discard_innermost_dummy (struct dummy_frame **stack)
+{
+ struct dummy_frame *tbd = (*stack);
+ (*stack) = (*stack)->next;
+ regcache_xfree (tbd->regcache);
+ 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)
@@ -282,12 +323,10 @@ generic_pop_dummy_frame (void)
if (!dummy_frame)
error ("Can't pop dummy frame!");
- dummy_frame_stack = dummy_frame->next;
regcache_cpy (current_regcache, dummy_frame->regcache);
flush_cached_frames ();
- regcache_xfree (dummy_frame->regcache);
- xfree (dummy_frame);
+ discard_innermost_dummy (&dummy_frame_stack);
}
/* Function: fix_call_dummy
@@ -304,7 +343,7 @@ generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
/* Given a call-dummy dummy-frame, return the registers. Here the
register value is taken from the local copy of the register buffer. */
-void
+static void
dummy_frame_register_unwind (struct frame_info *frame, void **cache,
int regnum, int *optimized,
enum lval_type *lvalp, CORE_ADDR *addrp,
@@ -331,7 +370,10 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache,
}
}
-CORE_ADDR
+/* Assuming that FRAME is a dummy, return the resume address for the
+ previous frame. */
+
+static CORE_ADDR
dummy_frame_pc_unwind (struct frame_info *frame,
void **cache)
{
@@ -345,16 +387,39 @@ dummy_frame_pc_unwind (struct frame_info *frame,
}
-struct frame_id
+/* Assuming that FRAME is a dummy, return the ID of the calling frame
+ (the frame that the dummy has the saved state of). */
+
+static void
dummy_frame_id_unwind (struct frame_info *frame,
- void **cache)
+ void **cache,
+ struct frame_id *id)
{
struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
/* Oops! In a dummy-frame but can't find the stack dummy. Pretend
that the frame doesn't unwind. Should this function instead
return a has-no-caller indication? */
if (dummy == NULL)
- return null_frame_id;
- return dummy->id;
+ (*id) = null_frame_id;
+ else
+ (*id) = dummy->id;
}
+static struct frame_unwind dummy_frame_unwind =
+{
+ dummy_frame_pop,
+ dummy_frame_pc_unwind,
+ dummy_frame_id_unwind,
+ dummy_frame_register_unwind
+};
+
+const struct frame_unwind *
+dummy_frame_p (CORE_ADDR pc)
+{
+ if (DEPRECATED_PC_IN_CALL_DUMMY_P ()
+ ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)
+ : pc_in_dummy_frame (pc))
+ return &dummy_frame_unwind;
+ else
+ return NULL;
+}