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).
This commit is contained in:
Andrew Cagney 2004-08-02 17:39:53 +00:00
parent d67ec5db39
commit 96860204a5
6 changed files with 90 additions and 76 deletions

View file

@ -1,3 +1,23 @@
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.

View file

@ -1828,7 +1828,7 @@ dsrec.o: dsrec.c $(defs_h) $(serial_h) $(srec_h) $(gdb_assert_h) \
$(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)
@ -2043,7 +2043,8 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_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) \

View file

@ -31,6 +31,7 @@
#include "frame-unwind.h"
#include "command.h"
#include "gdbcmd.h"
#include "gdb_string.h"
static int pc_in_dummy_frame (CORE_ADDR pc);
@ -94,27 +95,24 @@ 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);
@ -124,31 +122,19 @@ generic_push_dummy_frame (void)
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

View file

@ -1,6 +1,6 @@
/* 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.
@ -27,6 +27,22 @@ struct regcache;
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. */

View file

@ -521,8 +521,6 @@ extern void *frame_obstack_zalloc (unsigned long size);
/* 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);
@ -575,12 +573,8 @@ extern void print_frame_info (struct frame_info *, int print_level,
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

View file

@ -35,6 +35,7 @@
#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?
@ -308,6 +309,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
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 ();
@ -325,23 +329,12 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
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. */
{
@ -491,10 +484,6 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
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");
@ -660,13 +649,14 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
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);
/* Now proceed, having reached the desired place. */
clear_proceed_status ();
dummy_id = frame_id_build (sp, bp_addr);
/* Create a momentary breakpoint at the return address of the
inferior. That way it breaks when it returns. */
@ -674,22 +664,29 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
{
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.