/* Perform an inferior function call, for GDB, the GNU debugger.
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GDB.
#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?
with "set coerce-float-to-double 0". */
static int coerce_float_to_double_p = 1;
+static void
+show_coerce_float_to_double_p (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+Coercion of floats to doubles when calling functions is %s.\n"),
+ value);
+}
/* This boolean tells what gdb should do if a signal is received while
in a function called from gdb (call dummy). If set, gdb unwinds
The default is to stop in the frame where the signal was received. */
int unwind_on_signal_p = 0;
+static void
+show_unwind_on_signal_p (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+Unwinding of stack if a signal is received while in a call dummy is %s.\n"),
+ value);
+}
+
/* Perform the standard coercions that are specified
for arguments to be passed to C functions.
value_arg_coerce (struct value *arg, struct type *param_type,
int is_prototyped)
{
- struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ struct type *arg_type = check_typedef (value_type (arg));
struct type *type
= param_type ? check_typedef (param_type) : arg_type;
&& TYPE_CODE (arg_type) != TYPE_CODE_PTR)
{
arg = value_addr (arg);
- VALUE_TYPE (arg) = param_type;
+ deprecated_set_value_type (arg, param_type);
return arg;
}
break;
CORE_ADDR
find_function_addr (struct value *function, struct type **retval_type)
{
- struct type *ftype = check_typedef (VALUE_TYPE (function));
+ struct type *ftype = check_typedef (value_type (function));
enum type_code code = TYPE_CODE (ftype);
struct type *value_type;
CORE_ADDR funaddr;
value_type = builtin_type_int;
}
else
- error ("Invalid data type for function to be called.");
+ error (_("Invalid data type for function to be called."));
if (retval_type != NULL)
*retval_type = value_type;
{
CORE_ADDR sp;
CORE_ADDR dummy_addr;
- struct type *value_type;
+ struct type *values_type;
unsigned char struct_return;
CORE_ADDR struct_addr = 0;
struct regcache *retbuf;
CORE_ADDR funaddr;
int using_gcc; /* Set to version of gcc in use, or zero if not gcc */
CORE_ADDR real_pc;
- struct type *ftype = check_typedef (SYMBOL_TYPE (function));
+ struct type *ftype = check_typedef (value_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. */
{
sp = old_sp;
}
- funaddr = find_function_addr (function, &value_type);
- CHECK_TYPEDEF (value_type);
+ funaddr = find_function_addr (function, &values_type);
+ CHECK_TYPEDEF (values_type);
{
struct block *b = block_for_pc (funaddr);
/* Are we returning a value using a structure return or a normal
value return? */
- struct_return = using_struct_return (value_type, using_gcc);
+ struct_return = using_struct_return (values_type, using_gcc);
/* Determine the location of the breakpoint (and possibly other
stuff) that the called function will return to. The SPARC, for a
if (INNER_THAN (1, 2))
{
sp = push_dummy_code (current_gdbarch, sp, funaddr,
- using_gcc, args, nargs, value_type,
+ using_gcc, args, nargs, values_type,
&real_pc, &bp_addr);
dummy_addr = sp;
}
{
dummy_addr = sp;
sp = push_dummy_code (current_gdbarch, sp, funaddr,
- using_gcc, args, nargs, value_type,
+ using_gcc, args, nargs, values_type,
&real_pc, &bp_addr);
}
break;
break;
}
default:
- internal_error (__FILE__, __LINE__, "bad switch");
+ 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");
+ error (_("too few arguments in function call"));
{
int i;
this point. */
/* Go see if the actual parameter is a variable of
type pointer to function or just a function. */
- if (args[i]->lval == not_lval)
+ if (VALUE_LVAL (args[i]) == not_lval)
{
char *arg_name;
- if (find_pc_partial_function ((CORE_ADDR) args[i]->aligner.contents[0], &arg_name, NULL, NULL))
- error ("\
+ /* NOTE: cagney/2005-01-02: THIS IS BOGUS. */
+ if (find_pc_partial_function ((CORE_ADDR) value_contents (args[i])[0], &arg_name, NULL, NULL))
+ error (_("\
You cannot use function <%s> as argument. \n\
-You must use a pointer to function type variable. Command ignored.", arg_name);
+You must use a pointer to function type variable. Command ignored."), arg_name);
}
}
}
pointer to the structure, not the structure itself. */
for (i = nargs - 1; i >= 0; i--)
{
- struct type *arg_type = check_typedef (VALUE_TYPE (args[i]));
+ struct type *arg_type = check_typedef (value_type (args[i]));
if ((TYPE_CODE (arg_type) == TYPE_CODE_STRUCT
|| TYPE_CODE (arg_type) == TYPE_CODE_UNION
|| TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
CORE_ADDR addr;
int len; /* = TYPE_LENGTH (arg_type); */
int aligned_len;
- arg_type = check_typedef (VALUE_ENCLOSING_TYPE (args[i]));
+ arg_type = check_typedef (value_enclosing_type (args[i]));
len = TYPE_LENGTH (arg_type);
aligned_len = len;
sp += aligned_len;
}
/* Push the structure. */
- write_memory (addr, VALUE_CONTENTS_ALL (args[i]), len);
+ write_memory (addr, value_contents_all (args[i]), len);
/* The value we're going to pass is the address of the
thing we just pushed. */
- /*args[i] = value_from_longest (lookup_pointer_type (value_type),
+ /*args[i] = value_from_longest (lookup_pointer_type (values_type),
(LONGEST) addr); */
args[i] = value_from_pointer (lookup_pointer_type (arg_type),
addr);
if (struct_return)
{
- int len = TYPE_LENGTH (value_type);
+ int len = TYPE_LENGTH (values_type);
if (INNER_THAN (1, 2))
{
/* Stack grows downward. Align STRUCT_ADDR and SP after
sp = DEPRECATED_PUSH_ARGUMENTS (nargs, args, sp, struct_return,
struct_addr);
else
- error ("This target does not support function calls");
+ 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.
{
/* Can't use a cleanup here. It is discarded, instead use
an alloca. */
- char *tmp = xstrprintf ("at %s", local_hex_string (funaddr));
+ char *tmp = xstrprintf ("at %s", hex_string (funaddr));
char *a = alloca (strlen (tmp) + 1);
strcpy (a, tmp);
xfree (tmp);
/* FIXME: Insert a bunch of wrap_here; name can be very
long if it's a C++ name with arguments and stuff. */
- error ("\
+ error (_("\
The program being debugged was signaled while in a function called from GDB.\n\
GDB has restored the context to what it was before the call.\n\
To change this behavior use \"set unwindonsignal off\"\n\
-Evaluation of the expression containing the function (%s) will be abandoned.",
+Evaluation of the expression containing the function (%s) will be abandoned."),
name);
}
else
discard_inferior_status (inf_status);
/* FIXME: Insert a bunch of wrap_here; name can be very
long if it's a C++ name with arguments and stuff. */
- error ("\
+ error (_("\
The program being debugged was signaled while in a function called from GDB.\n\
GDB remains in the frame where the signal was received.\n\
To change this behavior use \"set unwindonsignal on\"\n\
-Evaluation of the expression containing the function (%s) will be abandoned.",
+Evaluation of the expression containing the function (%s) will be abandoned."),
name);
}
}
someday this will be implemented (it would not be easy). */
/* FIXME: Insert a bunch of wrap_here; name can be very long if it's
a C++ name with arguments and stuff. */
- error ("\
+ error (_("\
The program being debugged stopped while in a function called from GDB.\n\
When the function (%s) is done executing, GDB will silently\n\
stop (instead of continuing to evaluate the expression containing\n\
-the function call).", name);
+the function call)."), name);
}
/* The above code errors out, so ... */
- internal_error (__FILE__, __LINE__, "... should not be here");
+ internal_error (__FILE__, __LINE__, _("... should not be here"));
}
/* If we get here the called FUNCTION run to completion. */
/* Figure out the value returned by the function, return that. */
{
struct value *retval;
- if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
+ if (TYPE_CODE (values_type) == TYPE_CODE_VOID)
/* If the function returns void, don't bother fetching the
return value. */
- retval = allocate_value (value_type);
+ retval = allocate_value (values_type);
else if (struct_return)
/* NOTE: cagney/2003-09-27: This assumes that PUSH_DUMMY_CALL
has correctly stored STRUCT_ADDR in the target. In the past
you're seeing problems with values being returned using the
"struct return convention", check that PUSH_DUMMY_CALL isn't
playing tricks. */
- retval = value_at (value_type, struct_addr, NULL);
+ retval = value_at (values_type, struct_addr);
else
{
/* This code only handles "register convention". */
- retval = allocate_value (value_type);
- gdb_assert (gdbarch_return_value (current_gdbarch, value_type,
+ retval = allocate_value (values_type);
+ gdb_assert (gdbarch_return_value (current_gdbarch, values_type,
NULL, NULL, NULL)
== RETURN_VALUE_REGISTER_CONVENTION);
- gdbarch_return_value (current_gdbarch, value_type, retbuf,
- VALUE_CONTENTS_RAW (retval) /*read*/,
+ gdbarch_return_value (current_gdbarch, values_type, retbuf,
+ value_contents_raw (retval) /*read*/,
NULL /*write*/);
}
do_cleanups (retbuf_cleanup);
_initialize_infcall (void)
{
add_setshow_boolean_cmd ("coerce-float-to-double", class_obscure,
- &coerce_float_to_double_p, "\
-Set coercion of floats to doubles when calling functions.", "\
-Show coercion of floats to doubles when calling functions", "\
+ &coerce_float_to_double_p, _("\
+Set coercion of floats to doubles when calling functions."), _("\
+Show coercion of floats to doubles when calling functions"), _("\
Variables of type float should generally be converted to doubles before\n\
calling an unprototyped function, and left alone when calling a prototyped\n\
function. However, some older debug info formats do not provide enough\n\
information to determine that a function is prototyped. If this flag is\n\
set, GDB will perform the conversion for a function it considers\n\
unprototyped.\n\
-The default is to perform the conversion.\n", "\
-Coercion of floats to doubles when calling functions is %s.",
- NULL, NULL, &setlist, &showlist);
+The default is to perform the conversion.\n"),
+ NULL,
+ show_coerce_float_to_double_p,
+ &setlist, &showlist);
add_setshow_boolean_cmd ("unwindonsignal", no_class,
- &unwind_on_signal_p, "\
-Set unwinding of stack if a signal is received while in a call dummy.", "\
-Show unwinding of stack if a signal is received while in a call dummy.", "\
+ &unwind_on_signal_p, _("\
+Set unwinding of stack if a signal is received while in a call dummy."), _("\
+Show unwinding of stack if a signal is received while in a call dummy."), _("\
The unwindonsignal lets the user determine what gdb should do if a signal\n\
is received while in a function called from gdb (call dummy). If set, gdb\n\
unwinds the stack and restore the context to what as it was before the call.\n\
-The default is to stop in the frame where the signal was received.", "\
-Unwinding of stack if a signal is received while in a call dummy is %s.",
- NULL, NULL, &setlist, &showlist);
+The default is to stop in the frame where the signal was received."),
+ NULL,
+ show_unwind_on_signal_p,
+ &setlist, &showlist);
}