* dummy-frame.c: Include "gdb_string.h".
(generic_save_call_dummy_addr, generic_push_dummy_frame)
(generic_save_dummy_frame_tos): Delete.
(dummy_frame_push): New function, replaces above.
* dummy-frame.h: Update copyright.
(dummy_frame_push): Declare.
* frame.h (generic_save_dummy_frame_tos, generic_push_dummy_frame)
(generic_save_call_dummy_addr): Delete declarations.
* infcall.c: Include "dummy-frame.h".
(call_function_by_hand): Add locals caller_regcache,
caller_regcache_cleanup and dummy_id. Replace push_dummy_frame
with call to frame_save_as_regcache plus cleanup. Delete calls to
generic_save_call_dummy_addr and generic_save_dummy_frame_tos.
Move clear_proceed_status to just before the resume, add call to
dummy_frame_push (discard cleanup).
* Makefile.in (infcall.o): Add $(dummy_frame_h).
(dummy-frame.o): Add $(gdb_string_h).
+2004-08-02 Andrew Cagney <cagney@gnu.org>
+
+ * dummy-frame.c: Include "gdb_string.h".
+ (generic_save_call_dummy_addr, generic_push_dummy_frame)
+ (generic_save_dummy_frame_tos): Delete.
+ (dummy_frame_push): New function, replaces above.
+ * dummy-frame.h: Update copyright.
+ (dummy_frame_push): Declare.
+ * frame.h (generic_save_dummy_frame_tos, generic_push_dummy_frame)
+ (generic_save_call_dummy_addr): Delete declarations.
+ * infcall.c: Include "dummy-frame.h".
+ (call_function_by_hand): Add locals caller_regcache,
+ caller_regcache_cleanup and dummy_id. Replace push_dummy_frame
+ with call to frame_save_as_regcache plus cleanup. Delete calls to
+ generic_save_call_dummy_addr and generic_save_dummy_frame_tos.
+ Move clear_proceed_status to just before the resume, add call to
+ dummy_frame_push (discard cleanup).
+ * Makefile.in (infcall.o): Add $(dummy_frame_h).
+ (dummy-frame.o): Add $(gdb_string_h).
+
2004-08-01 Andrew Cagney <cagney@gnu.org>
* dummy-frame.h (dummy_frame_unwind): Replace dummy_frame_sniffer.
$(gdb_string_h)
dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
$(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h) \
- $(command_h) $(gdbcmd_h)
+ $(command_h) $(gdbcmd_h) $(gdb_string_h)
dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
$(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h) \
$(mips_tdep_h)
$(libunwind_frame_h) $(libunwind_ia64_h)
infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
$(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
- $(objfiles_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h)
+ $(objfiles_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h) \
+ $(dummy_frame_h)
infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(frame_h) $(inferior_h) $(environ_h) $(value_h) $(gdbcmd_h) \
$(symfile_h) $(gdbcore_h) $(target_h) $(language_h) $(symfile_h) \
#include "frame-unwind.h"
#include "command.h"
#include "gdbcmd.h"
+#include "gdb_string.h"
static int pc_in_dummy_frame (CORE_ADDR pc);
return 0;
}
-/* Save all the registers on the dummy frame stack. Most ports save the
- registers on the target stack. This results in lots of unnecessary memory
- references, which are slow when debugging via a serial line. Instead, we
- save all the registers internally, and never write them to the stack. The
- registers get restored when the called function returns to the entry point,
- where a breakpoint is laying in wait. */
+/* Push the caller's state, along with the dummy frame info, onto a
+ dummy-frame stack. */
void
-generic_push_dummy_frame (void)
+dummy_frame_push (struct regcache *caller_regcache,
+ const struct frame_id *dummy_id)
{
struct dummy_frame *dummy_frame;
- CORE_ADDR fp = get_frame_base (get_current_frame ());
-
- /* check to see if there are stale dummy frames,
- perhaps left over from when a longjump took us out of a
- function that was called by the debugger */
+ /* Check to see if there are stale dummy frames, perhaps left over
+ from when a longjump took us out of a function that was called by
+ the debugger. */
dummy_frame = dummy_frame_stack;
while (dummy_frame)
- if (gdbarch_inner_than (current_gdbarch, dummy_frame->top, fp))
- /* stale -- destroy! */
+ /* FIXME: cagney/2004-08-02: Should just test IDs. */
+ if (gdbarch_inner_than (current_gdbarch, dummy_frame->top,
+ dummy_id->stack_addr))
+ /* Stale -- destroy! */
{
dummy_frame_stack = dummy_frame->next;
regcache_xfree (dummy_frame->regcache);
else
dummy_frame = dummy_frame->next;
- dummy_frame = xmalloc (sizeof (struct dummy_frame));
- dummy_frame->regcache = frame_save_as_regcache (get_current_frame ());
-
- dummy_frame->pc = read_pc ();
- dummy_frame->top = 0;
- dummy_frame->id = get_frame_id (get_current_frame ());
+ dummy_frame = XZALLOC (struct dummy_frame);
+ dummy_frame->regcache = caller_regcache;
+ dummy_frame->id = (*dummy_id);
+ /* FIXME: cagney/2004-08-02: Retain for compatibility - trust the
+ ID. */
+ dummy_frame->pc = dummy_id->code_addr;
+ dummy_frame->top = dummy_id->stack_addr;
+ dummy_frame->call_lo = dummy_id->code_addr + 0;
+ dummy_frame->call_hi = dummy_id->code_addr + 1;
dummy_frame->next = dummy_frame_stack;
dummy_frame_stack = dummy_frame;
}
-void
-generic_save_dummy_frame_tos (CORE_ADDR sp)
-{
- dummy_frame_stack->top = sp;
-}
-
-/* Record the upper/lower bounds on the address of the call dummy. */
-
-void
-generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi)
-{
- dummy_frame_stack->call_lo = lo;
- dummy_frame_stack->call_hi = hi;
-}
-
/* Return the dummy frame cache, it contains both the ID, and a
pointer to the regcache. */
struct dummy_frame_cache
/* Code dealing with dummy stack frames, for GDB, the GNU debugger.
- Copyright 2002 Free Software Foundation, Inc.
+ Copyright 2002, 2004 Free Software Foundation, Inc.
This file is part of GDB.
struct frame_unwind;
struct frame_id;
+/* Push the information needed to identify, and unwind from, a dummy
+ frame onto the dummy frame stack. */
+
+/* NOTE: cagney/2004-08-02: This interface will eventually need to be
+ parameterized with the caller's thread - that will allow per-thread
+ dummy-frame stacks and, hence, per-thread inferior function
+ calls. */
+
+/* NOTE: cagney/2004-08-02: In the case of ABIs using push_dummy_code
+ containing more than one instruction, this interface many need to
+ be expanded so that it knowns the lower/upper extent of the dummy
+ frame's code. */
+
+extern void dummy_frame_push (struct regcache *regcache,
+ const struct frame_id *dummy_id);
+
/* If the PC falls in a dummy frame, return a dummy frame
unwinder. */
/* Create a regcache, and copy the frame's registers into it. */
struct regcache *frame_save_as_regcache (struct frame_info *this_frame);
-extern void generic_save_dummy_frame_tos (CORE_ADDR sp);
-
extern struct block *get_frame_block (struct frame_info *,
CORE_ADDR *addr_in_block);
extern struct frame_info *block_innermost_frame (struct block *);
-extern void generic_push_dummy_frame (void);
-
extern int deprecated_pc_in_call_dummy (CORE_ADDR pc);
-extern void generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi);
-
/* FIXME: cagney/2003-02-02: Should be deprecated or replaced with a
function called get_frame_register_p(). This slightly weird (and
older) variant of get_frame_register() returns zero (indicating the
#include "command.h"
#include "gdb_string.h"
#include "infcall.h"
+#include "dummy-frame.h"
/* NOTE: cagney/2003-04-16: What's the future of this code?
CORE_ADDR real_pc;
struct type *ftype = check_typedef (SYMBOL_TYPE (function));
CORE_ADDR bp_addr;
+ struct regcache *caller_regcache;
+ struct cleanup *caller_regcache_cleanup;
+ struct frame_id dummy_id;
if (!target_has_execution)
noprocess ();
inf_status = save_inferior_status (1);
inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
- /* FIXME: cagney/2003-02-26: Step zero of this little tinker is to
- extract the generic dummy frame code from the architecture
- vector. Hence this direct call.
-
- A follow-on change is to modify this interface so that it takes
- thread OR frame OR ptid as a parameter, and returns a dummy frame
- handle. The handle can then be used further down as a parameter
- to generic_save_dummy_frame_tos(). Hmm, thinking about it, since
- everything is ment to be using generic dummy frames, why not even
- use some of the dummy frame code to here - do a regcache dup and
- then pass the duped regcache, along with all the other stuff, at
- one single point.
-
- In fact, you can even save the structure's return address in the
- dummy frame and fix one of those nasty lost struct return edge
- conditions. */
- generic_push_dummy_frame ();
+ /* Save the caller's registers so that they can be restored once the
+ callee returns. To allow nested calls the registers are (further
+ down) pushed onto a dummy frame stack. Include a cleanup (which
+ is tossed once the regcache has been pushed). */
+ caller_regcache = frame_save_as_regcache (get_current_frame ());
+ caller_regcache_cleanup = make_cleanup_regcache_xfree (caller_regcache);
/* Ensure that the initial SP is correctly aligned. */
{
internal_error (__FILE__, __LINE__, "bad switch");
}
- /* Save where the breakpoint is going to be inserted so that the
- dummy-frame code is later able to re-identify it. */
- generic_save_call_dummy_addr (bp_addr, bp_addr + 1);
-
if (nargs < TYPE_NFIELDS (ftype))
error ("too few arguments in function call");
else
error ("This target does not support function calls");
+ /* Set up a frame ID for the dummy frame so we can pass it to
+ set_momentary_breakpoint. We need to give the breakpoint a frame
+ ID so that the breakpoint code can correctly re-identify the
+ dummy breakpoint. */
/* Sanity. The exact same SP value is returned by PUSH_DUMMY_CALL,
saved as the dummy-frame TOS, and used by unwind_dummy_id to form
the frame ID's stack address. */
- generic_save_dummy_frame_tos (sp);
+ dummy_id = frame_id_build (sp, bp_addr);
- /* Now proceed, having reached the desired place. */
- clear_proceed_status ();
-
/* Create a momentary breakpoint at the return address of the
inferior. That way it breaks when it returns. */
{
struct breakpoint *bpt;
struct symtab_and_line sal;
- struct frame_id frame;
init_sal (&sal); /* initialize to zeroes */
sal.pc = bp_addr;
sal.section = find_pc_overlay (sal.pc);
- /* Set up a frame ID for the dummy frame so we can pass it to
- set_momentary_breakpoint. We need to give the breakpoint a
- frame ID so that the breakpoint code can correctly re-identify
- the dummy breakpoint. */
/* Sanity. The exact same SP value is returned by
PUSH_DUMMY_CALL, saved as the dummy-frame TOS, and used by
unwind_dummy_id to form the frame ID's stack address. */
- frame = frame_id_build (sp, sal.pc);
- bpt = set_momentary_breakpoint (sal, frame, bp_call_dummy);
+ bpt = set_momentary_breakpoint (sal, dummy_id, bp_call_dummy);
bpt->disposition = disp_del;
}
+ /* Everything's ready, push all the info needed to restore the
+ caller (and identify the dummy-frame) onto the dummy-frame
+ stack. */
+ dummy_frame_push (caller_regcache, &dummy_id);
+ discard_cleanups (caller_regcache_cleanup);
+
+ /* - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP -
+ If you're looking to implement asynchronous dummy-frames, then
+ just below is the place to chop this function in two.. */
+
+ /* Now proceed, having reached the desired place. */
+ clear_proceed_status ();
+
/* Execute a "stack dummy", a piece of code stored in the stack by
the debugger to be executed in the inferior.