* infcall.c: New file.
* infcall.h: New file.
* valarith.c: Include "infcall.h".
* scm-lang.c, objc-lang.cm, hppa-tdep.c, gcore.c: Ditto.
* eval.c, ada-valprint.c, ada-lang.c: Ditto.
* Makefile.in (valarith.o, scm-lang.o): Update dependencies.
(objc-lang.o, hppa-tdep.o, gcore.o): Update dependencies.
(eval.o, ada-valprint.o, ada-lang.o): Update dependencies.
(SFILES): Add "infcall.c"
(COMMON_OBS): Add "infcall.o".
(infcall.o): Specify dependencies.
* value.h (call_function_by_hand): Delete declaration.
* inferior.h (run_stack_dummy): Delete declaration.
* infcmd.c (breakpoint_auto_delete_contents): Move to "infcall.c".
(run_stack_dummy): Move to "infcall.c", merged into
call_function_by_hand.
* valops.c (call_function_by_hand): Moved to "infcall.c".
(find_function_addr, value_arg_coerce): Ditto.
(unwindonsignal_p, coerce_float_to_double): Ditto.
(_initialize_valops): Move "set/show coerce-float-to-double", and
"set/show unwindonsignal" commands to "infcall.c".
* v850-tdep.c, target.h: Update comments.
* sparc-tdep.c (sparc_fix_call_dummy): Update comments.
* sh-tdep.c (sh_init_extra_frame_info): Update comments.
(sh64_init_extra_frame_info): Update comments.
* mn10300-tdep.c: Update comments.
* mcore-tdep.c (mcore_init_extra_frame_info): Update comments.
* config/sparc/tm-sparc.h: Update comments.
* breakpoint.h: Update comments.
* avr-tdep.c (avr_init_extra_frame_info): Update comments.
* arm-tdep.c: Update comment.
+2003-04-21 Andrew Cagney <cagney@redhat.com>
+
+ * infcall.c: New file.
+ * infcall.h: New file.
+ * valarith.c: Include "infcall.h".
+ * scm-lang.c, objc-lang.cm, hppa-tdep.c, gcore.c: Ditto.
+ * eval.c, ada-valprint.c, ada-lang.c: Ditto.
+ * Makefile.in (valarith.o, scm-lang.o): Update dependencies.
+ (objc-lang.o, hppa-tdep.o, gcore.o): Update dependencies.
+ (eval.o, ada-valprint.o, ada-lang.o): Update dependencies.
+ (SFILES): Add "infcall.c"
+ (COMMON_OBS): Add "infcall.o".
+ (infcall.o): Specify dependencies.
+ * value.h (call_function_by_hand): Delete declaration.
+ * inferior.h (run_stack_dummy): Delete declaration.
+ * infcmd.c (breakpoint_auto_delete_contents): Move to "infcall.c".
+ (run_stack_dummy): Move to "infcall.c", merged into
+ call_function_by_hand.
+ * valops.c (call_function_by_hand): Moved to "infcall.c".
+ (find_function_addr, value_arg_coerce): Ditto.
+ (unwindonsignal_p, coerce_float_to_double): Ditto.
+ (_initialize_valops): Move "set/show coerce-float-to-double", and
+ "set/show unwindonsignal" commands to "infcall.c".
+ * v850-tdep.c, target.h: Update comments.
+ * sparc-tdep.c (sparc_fix_call_dummy): Update comments.
+ * sh-tdep.c (sh_init_extra_frame_info): Update comments.
+ (sh64_init_extra_frame_info): Update comments.
+ * mn10300-tdep.c: Update comments.
+ * mcore-tdep.c (mcore_init_extra_frame_info): Update comments.
+ * config/sparc/tm-sparc.h: Update comments.
+ * breakpoint.h: Update comments.
+ * avr-tdep.c (avr_init_extra_frame_info): Update comments.
+ * arm-tdep.c: Update comment.
+
2003-04-19 Mark Kettenis <kettenis@gnu.org>
* i386-tdep.c (i386_num_register_names): New variable.
frame-unwind.c \
gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
hpacc-abi.c \
- inf-loop.c infcmd.c inflow.c infrun.c \
+ inf-loop.c \
+ infcall.c \
+ infcmd.c inflow.c infrun.c \
interps.c \
jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
kod.c kod-cisco.c \
i386_tdep_h = i386-tdep.h
i387_tdep_h = i387-tdep.h
inf_loop_h = inf-loop.h
+infcall_h = infcall.h
inferior_h = inferior.h $(breakpoint_h) $(target_h) $(frame_h)
inflow_h = inflow.h $(terminal_h)
interps_h = interps.h
COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
charset.o disasm.o dummy-frame.o \
source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
- block.o symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \
+ block.o symtab.o symfile.o symmisc.o linespec.o \
+ infcall.o \
+ infcmd.o infrun.o \
expprint.o environ.o stack.o thread.o \
interps.o \
macrotab.o macrocmd.o macroexp.o macroscope.o \
ada-lang.o: ada-lang.c $(gdb_string_h) $(demangle_h) $(defs_h) $(symtab_h) \
$(gdbtypes_h) $(gdbcmd_h) $(expression_h) $(parser_defs_h) \
$(language_h) $(c_lang_h) $(inferior_h) $(symfile_h) $(objfiles_h) \
- $(breakpoint_h) $(gdbcore_h) $(ada_lang_h) $(ui_out_h) $(block_h)
+ $(breakpoint_h) $(gdbcore_h) $(ada_lang_h) $(ui_out_h) $(block_h) \
+ $(infcall_h)
ada-tasks.o: ada-tasks.c $(defs_h) $(command_h) $(value_h) $(language_h) \
$(inferior_h) $(symtab_h) $(target_h) $(gdbcore_h) $(gregset_h) \
$(ada_lang_h)
$(c_lang_h) $(typeprint_h) $(ada_lang_h) $(gdb_string_h)
ada-valprint.o: ada-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(value_h) $(demangle_h) $(valprint_h) $(language_h) \
- $(annotate_h) $(ada_lang_h) $(c_lang_h)
+ $(annotate_h) $(ada_lang_h) $(c_lang_h) $(infcall_h)
aix-thread.o: aix-thread.c $(defs_h) $(gdb_assert_h) $(gdbthread_h) \
$(target_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) $(language_h) \
$(ppc_tdep_h)
environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
- $(f_lang_h) $(cp_abi_h)
+ $(f_lang_h) $(cp_abi_h) $(infcall_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \
$(arch_utils_h) $(regcache_h)
gcore.o: gcore.c $(defs_h) $(cli_decode_h) $(inferior_h) $(gdbcore_h) \
- $(elf_bfd_h) $(symfile_h) $(objfiles_h)
+ $(elf_bfd_h) $(symfile_h) $(objfiles_h) $(infcall_h)
gdb.o: gdb.c $(defs_h) $(main_h) $(gdb_string_h) $(interps_h)
gdb-events.o: gdb-events.c $(defs_h) $(gdb_events_h) $(gdbcmd_h)
gdbarch.o: gdbarch.c $(defs_h) $(arch_utils_h) $(gdbcmd_h) $(inferior_h) \
$(gdbtypes_h) $(gdbcore_h) $(cp_abi_h)
hppa-tdep.o: hppa-tdep.c $(defs_h) $(frame_h) $(bfd_h) $(inferior_h) \
$(value_h) $(regcache_h) $(completer_h) $(language_h) $(osabi_h) \
- $(gdb_assert_h) $(infttrace_h) $(symtab_h) $(a_out_encap_h) \
- $(gdb_stat_h) $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) \
- $(symfile_h) $(objfiles_h)
+ $(gdb_assert_h) $(infttrace_h) $(symtab_h) $(infcall_h) \
+ $(a_out_encap_h) $(gdb_stat_h) $(gdb_wait_h) $(gdbcore_h) \
+ $(gdbcmd_h) $(target_h) $(symfile_h) $(objfiles_h)
hppa-hpux-tdep.o: hppa-hpux-tdep.c $(defs_h) $(arch_utils_h) $(gdbcore_h) \
$(osabi_h) $(gdb_string_h)
hppab-nat.o: hppab-nat.c $(defs_h) $(inferior_h) $(target_h) $(regcache_h)
$(value_h) $(objfiles_h) $(elf_common_h) $(elf_bfd_h)
inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \
$(event_top_h) $(inf_loop_h) $(remote_h)
+infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
+ $(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
+ $(symfile_h) $(gdbcmd_h) $(command_h) $(gdb_string_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) \
$(osabi_h)
objc-lang.o: objc-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(c_lang_h) $(objc_lang_h) \
- $(complaints_h) $(value_h) $(symfile_h) $(objfiles_h) \
- $(gdb_string_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(frame_h) \
- $(gdb_regex_h) $(regcache_h) $(block_h)
+ $(complaints_h) $(value_h) $(symfile_h) $(objfiles_h) $(gdb_string_h) \
+ $(target_h) $(gdbcore_h) $(gdbcmd_h) $(frame_h) $(gdb_regex_h) \
+ $(regcache_h) $(block_h) $(infcall_h)
objfiles.o: objfiles.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) \
$(objfiles_h) $(gdb_stabs_h) $(target_h) $(bcache_h) $(gdb_stat_h) \
$(gdb_obstack_h) $(gdb_string_h) $(breakpoint_h) $(mmalloc_h) \
$(scm_tags_h)
scm-lang.o: scm-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
- $(scm_tags_h) $(gdb_string_h) $(gdbcore_h) $(source_h)
+ $(scm_tags_h) $(source_h) $(gdb_string_h) $(gdbcore_h) $(infcall_h)
scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(parser_defs_h) $(language_h) $(value_h) \
$(scm_lang_h) $(valprint_h) $(gdbcore_h)
$(gdbcore_h) $(value_h) $(command_h) $(regcache_h)
valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(target_h) $(language_h) $(gdb_string_h) \
- $(doublest_h)
+ $(doublest_h) $(infcall_h)
valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(gdb_string_h) \
#include "ada-lang.h"
#include "ui-out.h"
#include "block.h"
+#include "infcall.h"
struct cleanup *unresolved_names;
#include "annotate.h"
#include "ada-lang.h"
#include "c-lang.h"
+#include "infcall.h"
/* Encapsulates arguments to ada_val_print. */
struct ada_val_print_args
FIXME rearnsha 2002-02018: Tweeking current_gdbarch is not an
optimal solution, but the call to arm_fix_call_dummy is immediately
- followed by a call to run_stack_dummy, which is the only function
- where call_dummy_breakpoint_offset is actually used. */
+ followed by a call to call_function_by_hand, which is the only
+ function where call_dummy_breakpoint_offset is actually used. */
static void
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
get_frame_base (fi)))
{
- /* We need to setup fi->frame here because run_stack_dummy gets it wrong
- by assuming it's always FP. */
+ /* We need to setup fi->frame here because call_function_by_hand
+ gets it wrong by assuming it's always FP. */
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi),
AVR_PC_REGNUM));
}
enabled watchpoints. When disabled, the watchpoints are marked
call_disabled. When reenabled, they are marked enabled.
- The intended client of these functions is infcmd.c\run_stack_dummy.
+ The intended client of these functions is call_function_by_hand.
The inferior must be stopped, and all breakpoints removed, when
these functions are used.
*
* call_function then writes CALL_DUMMY, pushes the args onto the
* stack, and adjusts the stack pointer.
- *
- * run_stack_dummy then starts execution (in the middle of
- * CALL_DUMMY, as directed by call_function). */
+
+ call_function_by_hand then starts execution (in the middle of
+ CALL_DUMMY, as directed by call_function). */
#ifndef CALL_DUMMY
/* This sequence of words is the instructions
get_frame_base (fi),
get_frame_base (fi)))
{
- /* We need to setup fi->frame here because run_stack_dummy gets it wrong
- by assuming it's always FP. */
+ /* We need to setup fi->frame here because call_function_by_hand
+ gets it wrong by assuming it's always FP. */
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi), SP_REGNUM));
get_frame_extra_info (fi)->return_pc =
deprecated_read_register_dummy (get_frame_pc (fi),
#include "language.h" /* For CAST_IS_CONVERSION */
#include "f-lang.h" /* for array bound stuff */
#include "cp-abi.h"
+#include "infcall.h"
/* Defined in symtab.c */
extern int hp_som_som_object_present;
#include "elf-bfd.h"
#include "symfile.h"
#include "objfiles.h"
+#include "infcall.h"
static char *default_gcore_target (void);
static enum bfd_architecture default_gcore_arch (void);
#include "infttrace.h"
/* For argument passing to the inferior */
#include "symtab.h"
+#include "infcall.h"
#ifdef USG
#include <sys/types.h>
--- /dev/null
+/* 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 Free Software
+ Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "breakpoint.h"
+#include "target.h"
+#include "regcache.h"
+#include "inferior.h"
+#include "gdb_assert.h"
+#include "block.h"
+#include "gdbcore.h"
+#include "language.h"
+#include "symfile.h"
+#include "gdbcmd.h"
+#include "command.h"
+#include "gdb_string.h"
+
+/* NOTE: cagney/2003-04-16: What's the future of this code?
+
+ GDB needs an asynchronous expression evaluator, that means an
+ asynchronous inferior function call implementation, and that in
+ turn means restructuring the code so that it is event driven. */
+
+/* How you should pass arguments to a function depends on whether it
+ was defined in K&R style or prototype style. If you define a
+ function using the K&R syntax that takes a `float' argument, then
+ callers must pass that argument as a `double'. If you define the
+ function using the prototype syntax, then you must pass the
+ argument as a `float', with no promotion.
+
+ Unfortunately, on certain older platforms, the debug info doesn't
+ indicate reliably how each function was defined. A function type's
+ TYPE_FLAG_PROTOTYPED flag may be clear, even if the function was
+ defined in prototype style. When calling a function whose
+ TYPE_FLAG_PROTOTYPED flag is clear, GDB consults this flag to
+ decide what to do.
+
+ For modern targets, it is proper to assume that, if the prototype
+ flag is clear, that can be trusted: `float' arguments should be
+ promoted to `double'. For some older targets, if the prototype
+ flag is clear, that doesn't tell us anything. The default is to
+ trust the debug information; the user can override this behavior
+ with "set coerce-float-to-double 0". */
+
+static int coerce_float_to_double_p = 1;
+
+/* 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 stack and restore the context to what as it was before the
+ call.
+
+ The default is to stop in the frame where the signal was received. */
+
+int unwind_on_signal_p = 0;
+
+/* Perform the standard coercions that are specified
+ for arguments to be passed to C functions.
+
+ If PARAM_TYPE is non-NULL, it is the expected parameter type.
+ IS_PROTOTYPED is non-zero if the function declaration is prototyped. */
+
+static struct value *
+value_arg_coerce (struct value *arg, struct type *param_type,
+ int is_prototyped)
+{
+ register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ register struct type *type
+ = param_type ? check_typedef (param_type) : arg_type;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_REF:
+ if (TYPE_CODE (arg_type) != TYPE_CODE_REF
+ && TYPE_CODE (arg_type) != TYPE_CODE_PTR)
+ {
+ arg = value_addr (arg);
+ VALUE_TYPE (arg) = param_type;
+ return arg;
+ }
+ break;
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ /* If we don't have a prototype, coerce to integer type if necessary. */
+ if (!is_prototyped)
+ {
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ type = builtin_type_int;
+ }
+ /* Currently all target ABIs require at least the width of an integer
+ type for an argument. We may have to conditionalize the following
+ type coercion for future targets. */
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ type = builtin_type_int;
+ break;
+ case TYPE_CODE_FLT:
+ if (!is_prototyped && coerce_float_to_double_p)
+ {
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
+ type = builtin_type_double;
+ else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double))
+ type = builtin_type_long_double;
+ }
+ break;
+ case TYPE_CODE_FUNC:
+ type = lookup_pointer_type (type);
+ break;
+ case TYPE_CODE_ARRAY:
+ /* Arrays are coerced to pointers to their first element, unless
+ they are vectors, in which case we want to leave them alone,
+ because they are passed by value. */
+ if (current_language->c_style_arrays)
+ if (!TYPE_VECTOR (type))
+ type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
+ break;
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_COMPLEX:
+ default:
+ break;
+ }
+
+ return value_cast (type, arg);
+}
+
+/* Determine a function's address and its return type from its value.
+ Calls error() if the function is not valid for calling. */
+
+static CORE_ADDR
+find_function_addr (struct value *function, struct type **retval_type)
+{
+ register struct type *ftype = check_typedef (VALUE_TYPE (function));
+ register enum type_code code = TYPE_CODE (ftype);
+ struct type *value_type;
+ CORE_ADDR funaddr;
+
+ /* If it's a member function, just look at the function
+ part of it. */
+
+ /* Determine address to call. */
+ if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
+ {
+ funaddr = VALUE_ADDRESS (function);
+ value_type = TYPE_TARGET_TYPE (ftype);
+ }
+ else if (code == TYPE_CODE_PTR)
+ {
+ funaddr = value_as_address (function);
+ ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+ if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+ || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ {
+ funaddr = CONVERT_FROM_FUNC_PTR_ADDR (funaddr);
+ value_type = TYPE_TARGET_TYPE (ftype);
+ }
+ else
+ value_type = builtin_type_int;
+ }
+ else if (code == TYPE_CODE_INT)
+ {
+ /* Handle the case of functions lacking debugging info.
+ Their values are characters since their addresses are char */
+ if (TYPE_LENGTH (ftype) == 1)
+ funaddr = value_as_address (value_addr (function));
+ else
+ /* Handle integer used as address of a function. */
+ funaddr = (CORE_ADDR) value_as_long (function);
+
+ value_type = builtin_type_int;
+ }
+ else
+ error ("Invalid data type for function to be called.");
+
+ *retval_type = value_type;
+ return funaddr;
+}
+
+/* Call breakpoint_auto_delete on the current contents of the bpstat
+ pointed to by arg (which is really a bpstat *). */
+
+static void
+breakpoint_auto_delete_contents (void *arg)
+{
+ breakpoint_auto_delete (*(bpstat *) arg);
+}
+
+/* All this stuff with a dummy frame may seem unnecessarily complicated
+ (why not just save registers in GDB?). The purpose of pushing a dummy
+ frame which looks just like a real frame is so that if you call a
+ function and then hit a breakpoint (get a signal, etc), "backtrace"
+ will look right. Whether the backtrace needs to actually show the
+ stack at the time the inferior function was called is debatable, but
+ it certainly needs to not display garbage. So if you are contemplating
+ making dummy frames be different from normal frames, consider that. */
+
+/* Perform a function call in the inferior.
+ ARGS is a vector of values of arguments (NARGS of them).
+ FUNCTION is a value, the function to be called.
+ Returns a value representing what the function returned.
+ May fail to return, if a breakpoint or signal is hit
+ during the execution of the function.
+
+ ARGS is modified to contain coerced values. */
+
+struct value *
+call_function_by_hand (struct value *function, int nargs, struct value **args)
+{
+ register CORE_ADDR sp;
+ register int i;
+ int rc;
+ CORE_ADDR start_sp;
+ /* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
+ is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
+ and remove any extra bytes which might exist because ULONGEST is
+ bigger than REGISTER_SIZE.
+
+ NOTE: This is pretty wierd, as the call dummy is actually a
+ sequence of instructions. But CISC machines will have
+ to pack the instructions into REGISTER_SIZE units (and
+ so will RISC machines for which INSTRUCTION_SIZE is not
+ REGISTER_SIZE).
+
+ NOTE: This is pretty stupid. CALL_DUMMY should be in strict
+ target byte order. */
+
+ static ULONGEST *dummy;
+ int sizeof_dummy1;
+ char *dummy1;
+ CORE_ADDR dummy_addr;
+ CORE_ADDR old_sp;
+ struct type *value_type;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr = 0;
+ struct regcache *retbuf;
+ struct cleanup *retbuf_cleanup;
+ struct inferior_status *inf_status;
+ struct cleanup *inf_status_cleanup;
+ CORE_ADDR funaddr;
+ int using_gcc; /* Set to version of gcc in use, or zero if not gcc */
+ CORE_ADDR real_pc;
+ struct type *param_type = NULL;
+ struct type *ftype = check_typedef (SYMBOL_TYPE (function));
+ int n_method_args = 0;
+
+ dummy = alloca (SIZEOF_CALL_DUMMY_WORDS);
+ sizeof_dummy1 = REGISTER_SIZE * SIZEOF_CALL_DUMMY_WORDS / sizeof (ULONGEST);
+ dummy1 = alloca (sizeof_dummy1);
+ memcpy (dummy, CALL_DUMMY_WORDS, SIZEOF_CALL_DUMMY_WORDS);
+
+ if (!target_has_execution)
+ noprocess ();
+
+ /* Create a cleanup chain that contains the retbuf (buffer
+ containing the register values). This chain is create BEFORE the
+ inf_status chain so that the inferior status can cleaned up
+ (restored or discarded) without having the retbuf freed. */
+ retbuf = regcache_xmalloc (current_gdbarch);
+ retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
+
+ /* A cleanup for the inferior status. Create this AFTER the retbuf
+ so that this can be discarded or applied without interfering with
+ the regbuf. */
+ inf_status = save_inferior_status (1);
+ inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
+
+ if (DEPRECATED_PUSH_DUMMY_FRAME_P ())
+ {
+ /* DEPRECATED_PUSH_DUMMY_FRAME is responsible for saving the
+ inferior registers (and frame_pop() for restoring them). (At
+ least on most machines) they are saved on the stack in the
+ inferior. */
+ DEPRECATED_PUSH_DUMMY_FRAME;
+ }
+ else
+ {
+ /* 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 tpid as a parameter, and returns a dummy
+ frame handle. The handle can then be used further down as a
+ parameter 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 ();
+ }
+
+ old_sp = read_sp ();
+
+ /* Ensure that the initial SP is correctly aligned. */
+ if (gdbarch_frame_align_p (current_gdbarch))
+ {
+ /* NOTE: cagney/2002-09-18:
+
+ On a RISC architecture, a void parameterless generic dummy
+ frame (i.e., no parameters, no result) typically does not
+ need to push anything the stack and hence can leave SP and
+ FP. Similarly, a framelss (possibly leaf) function does not
+ push anything on the stack and, hence, that too can leave FP
+ and SP unchanged. As a consequence, a sequence of void
+ parameterless generic dummy frame calls to frameless
+ functions will create a sequence of effectively identical
+ frames (SP, FP and TOS and PC the same). This, not
+ suprisingly, results in what appears to be a stack in an
+ infinite loop --- when GDB tries to find a generic dummy
+ frame on the internal dummy frame stack, it will always find
+ the first one.
+
+ To avoid this problem, the code below always grows the stack.
+ That way, two dummy frames can never be identical. It does
+ burn a few bytes of stack but that is a small price to pay
+ :-). */
+ sp = gdbarch_frame_align (current_gdbarch, old_sp);
+ if (sp == old_sp)
+ {
+ if (INNER_THAN (1, 2))
+ /* Stack grows down. */
+ sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
+ else
+ /* Stack grows up. */
+ sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
+ }
+ gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp)
+ || (INNER_THAN (2, 1) && sp >= old_sp));
+ }
+ else
+ /* FIXME: cagney/2002-09-18: Hey, you loose! Who knows how badly
+ aligned the SP is! Further, per comment above, if the generic
+ dummy frame ends up empty (because nothing is pushed) GDB won't
+ be able to correctly perform back traces. If a target is
+ having trouble with backtraces, first thing to do is add
+ FRAME_ALIGN() to its architecture vector. After that, try
+ adding SAVE_DUMMY_FRAME_TOS() and modifying
+ DEPRECATED_FRAME_CHAIN so that when the next outer frame is a
+ generic dummy, it returns the current frame's base. */
+ sp = old_sp;
+
+ if (INNER_THAN (1, 2))
+ {
+ /* Stack grows down */
+ sp -= sizeof_dummy1;
+ start_sp = sp;
+ }
+ else
+ {
+ /* Stack grows up */
+ start_sp = sp;
+ sp += sizeof_dummy1;
+ }
+
+ /* NOTE: cagney/2002-09-10: Don't bother re-adjusting the stack
+ after allocating space for the call dummy. A target can specify
+ a SIZEOF_DUMMY1 (via SIZEOF_CALL_DUMMY_WORDS) such that all local
+ alignment requirements are met. */
+
+ funaddr = find_function_addr (function, &value_type);
+ CHECK_TYPEDEF (value_type);
+
+ {
+ struct block *b = block_for_pc (funaddr);
+ /* If compiled without -g, assume GCC 2. */
+ using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
+ }
+
+ /* Are we returning a value using a structure return or a normal
+ value return? */
+
+ struct_return = using_struct_return (function, funaddr, value_type,
+ using_gcc);
+
+ /* Create a call sequence customized for this function
+ and the number of arguments for it. */
+ for (i = 0; i < (int) (SIZEOF_CALL_DUMMY_WORDS / sizeof (dummy[0])); i++)
+ store_unsigned_integer (&dummy1[i * REGISTER_SIZE],
+ REGISTER_SIZE,
+ (ULONGEST) dummy[i]);
+
+#ifdef GDB_TARGET_IS_HPPA
+ real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+ value_type, using_gcc);
+#else
+ if (FIX_CALL_DUMMY_P ())
+ {
+ /* gdb_assert (CALL_DUMMY_LOCATION == ON_STACK) true? */
+ FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args, value_type,
+ using_gcc);
+ }
+ real_pc = start_sp;
+#endif
+
+ switch (CALL_DUMMY_LOCATION)
+ {
+ case ON_STACK:
+ dummy_addr = start_sp;
+ write_memory (start_sp, (char *) dummy1, sizeof_dummy1);
+ if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
+ generic_save_call_dummy_addr (start_sp, start_sp + sizeof_dummy1);
+ break;
+ case AT_ENTRY_POINT:
+ real_pc = funaddr;
+ dummy_addr = CALL_DUMMY_ADDRESS ();
+ if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
+ /* NOTE: cagney/2002-04-13: The entry point is going to be
+ modified with a single breakpoint. */
+ generic_save_call_dummy_addr (CALL_DUMMY_ADDRESS (),
+ CALL_DUMMY_ADDRESS () + 1);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
+ }
+
+#ifdef lint
+ sp = old_sp; /* It really is used, for some ifdef's... */
+#endif
+
+ if (nargs < TYPE_NFIELDS (ftype))
+ error ("too few arguments in function call");
+
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ int prototyped;
+
+ /* FIXME drow/2002-05-31: Should just always mark methods as
+ prototyped. Can we respect TYPE_VARARGS? Probably not. */
+ if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ prototyped = 1;
+ else
+ prototyped = TYPE_PROTOTYPED (ftype);
+
+ if (i < TYPE_NFIELDS (ftype))
+ args[i] = value_arg_coerce (args[i], TYPE_FIELD_TYPE (ftype, i),
+ prototyped);
+ else
+ args[i] = value_arg_coerce (args[i], NULL, 0);
+
+ /*elz: this code is to handle the case in which the function to be called
+ has a pointer to function as parameter and the corresponding actual argument
+ is the address of a function and not a pointer to function variable.
+ In aCC compiled code, the calls through pointers to functions (in the body
+ of the function called by hand) are made via $$dyncall_external which
+ requires some registers setting, this is taken care of if we call
+ via a function pointer variable, but not via a function address.
+ In cc this is not a problem. */
+
+ if (using_gcc == 0)
+ if (param_type && TYPE_CODE (ftype) != TYPE_CODE_METHOD)
+ /* if this parameter is a pointer to function */
+ if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
+ if (TYPE_CODE (TYPE_TARGET_TYPE (param_type)) == TYPE_CODE_FUNC)
+ /* elz: FIXME here should go the test about the compiler used
+ to compile the target. We want to issue the error
+ message only if the compiler used was HP's aCC.
+ If we used HP's cc, then there is no problem and no need
+ to return at this point */
+ if (using_gcc == 0) /* && compiler == aCC */
+ /* go see if the actual parameter is a variable of type
+ pointer to function or just a function */
+ if (args[i]->lval == not_lval)
+ {
+ char *arg_name;
+ if (find_pc_partial_function ((CORE_ADDR) args[i]->aligner.contents[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);
+ }
+ }
+
+ if (REG_STRUCT_HAS_ADDR_P ())
+ {
+ /* This is a machine like the sparc, where we may need to pass a
+ 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]));
+ if ((TYPE_CODE (arg_type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (arg_type) == TYPE_CODE_UNION
+ || TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
+ || TYPE_CODE (arg_type) == TYPE_CODE_STRING
+ || TYPE_CODE (arg_type) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (arg_type) == TYPE_CODE_SET
+ || (TYPE_CODE (arg_type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (arg_type) > 8)
+ )
+ && REG_STRUCT_HAS_ADDR (using_gcc, arg_type))
+ {
+ CORE_ADDR addr;
+ int len; /* = TYPE_LENGTH (arg_type); */
+ int aligned_len;
+ arg_type = check_typedef (VALUE_ENCLOSING_TYPE (args[i]));
+ len = TYPE_LENGTH (arg_type);
+
+ if (STACK_ALIGN_P ())
+ /* MVS 11/22/96: I think at least some of this
+ stack_align code is really broken. Better to let
+ PUSH_ARGUMENTS adjust the stack in a target-defined
+ manner. */
+ aligned_len = STACK_ALIGN (len);
+ else
+ aligned_len = len;
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= aligned_len;
+ /* ... so the address of the thing we push is the
+ stack pointer after we push it. */
+ addr = sp;
+ }
+ else
+ {
+ /* The stack grows up, so the address of the thing
+ we push is the stack pointer before we push it. */
+ addr = sp;
+ sp += aligned_len;
+ }
+ /* Push the structure. */
+ 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),
+ (LONGEST) addr); */
+ args[i] = value_from_pointer (lookup_pointer_type (arg_type),
+ addr);
+ }
+ }
+ }
+
+
+ /* Reserve space for the return structure to be written on the
+ stack, if necessary. Make certain that the value is correctly
+ aligned. */
+
+ if (struct_return)
+ {
+ int len = TYPE_LENGTH (value_type);
+ if (STACK_ALIGN_P ())
+ /* NOTE: cagney/2003-03-22: Should rely on frame align, rather
+ than stack align to force the alignment of the stack. */
+ len = STACK_ALIGN (len);
+ if (INNER_THAN (1, 2))
+ {
+ /* Stack grows downward. Align STRUCT_ADDR and SP after
+ making space for the return value. */
+ sp -= len;
+ if (gdbarch_frame_align_p (current_gdbarch))
+ sp = gdbarch_frame_align (current_gdbarch, sp);
+ struct_addr = sp;
+ }
+ else
+ {
+ /* Stack grows upward. Align the frame, allocate space, and
+ then again, re-align the frame??? */
+ if (gdbarch_frame_align_p (current_gdbarch))
+ sp = gdbarch_frame_align (current_gdbarch, sp);
+ struct_addr = sp;
+ sp += len;
+ if (gdbarch_frame_align_p (current_gdbarch))
+ sp = gdbarch_frame_align (current_gdbarch, sp);
+ }
+ }
+
+ /* elz: on HPPA no need for this extra alignment, maybe it is needed
+ on other architectures. This is because all the alignment is
+ taken care of in the above code (ifdef REG_STRUCT_HAS_ADDR) and
+ in hppa_push_arguments */
+ /* NOTE: cagney/2003-03-24: The below code is very broken. Given an
+ odd sized parameter the below will mis-align the stack. As was
+ suggested back in '96, better to let PUSH_ARGUMENTS handle it. */
+ if (DEPRECATED_EXTRA_STACK_ALIGNMENT_NEEDED)
+ {
+ /* MVS 11/22/96: I think at least some of this stack_align code
+ is really broken. Better to let push_dummy_call() adjust the
+ stack in a target-defined manner. */
+ if (STACK_ALIGN_P () && INNER_THAN (1, 2))
+ {
+ /* If stack grows down, we must leave a hole at the top. */
+ int len = 0;
+
+ for (i = nargs - 1; i >= 0; i--)
+ len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
+ if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
+ len += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
+ sp -= STACK_ALIGN (len) - len;
+ }
+ }
+
+ /* Create the dummy stack frame. Pass in the call dummy address as,
+ presumably, the ABI code knows where, in the call dummy, the
+ return address should be pointed. */
+ if (gdbarch_push_dummy_call_p (current_gdbarch))
+ /* When there is no push_dummy_call method, should this code
+ simply error out. That would the implementation of this method
+ for all ABIs (which is probably a good thing). */
+ sp = gdbarch_push_dummy_call (current_gdbarch, current_regcache,
+ dummy_addr, nargs, args, sp, struct_return,
+ struct_addr);
+ else if (DEPRECATED_PUSH_ARGUMENTS_P ())
+ /* Keep old targets working. */
+ sp = DEPRECATED_PUSH_ARGUMENTS (nargs, args, sp, struct_return,
+ struct_addr);
+ else
+ sp = legacy_push_arguments (nargs, args, sp, struct_return, struct_addr);
+
+ if (DEPRECATED_PUSH_RETURN_ADDRESS_P ())
+ /* for targets that use no CALL_DUMMY */
+ /* There are a number of targets now which actually don't write
+ any CALL_DUMMY instructions into the target, but instead just
+ save the machine state, push the arguments, and jump directly
+ to the callee function. Since this doesn't actually involve
+ executing a JSR/BSR instruction, the return address must be set
+ up by hand, either by pushing onto the stack or copying into a
+ return-address register as appropriate. Formerly this has been
+ done in PUSH_ARGUMENTS, but that's overloading its
+ functionality a bit, so I'm making it explicit to do it here. */
+ sp = DEPRECATED_PUSH_RETURN_ADDRESS (real_pc, sp);
+
+ /* NOTE: cagney/2003-03-23: Diable this code when there is a
+ push_dummy_call() method. Since that method will have already
+ handled any alignment issues, the code below is entirely
+ redundant. */
+ if (!gdbarch_push_dummy_call_p (current_gdbarch)
+ && STACK_ALIGN_P () && !INNER_THAN (1, 2))
+ {
+ /* If stack grows up, we must leave a hole at the bottom, note
+ that sp already has been advanced for the arguments! */
+ if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
+ sp += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
+ sp = STACK_ALIGN (sp);
+ }
+
+/* XXX This seems wrong. For stacks that grow down we shouldn't do
+ anything here! */
+ /* MVS 11/22/96: I think at least some of this stack_align code is
+ really broken. Better to let PUSH_ARGUMENTS adjust the stack in
+ a target-defined manner. */
+ if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= DEPRECATED_CALL_DUMMY_STACK_ADJUST;
+ }
+
+ /* Store the address at which the structure is supposed to be
+ written. */
+ /* NOTE: 2003-03-24: Since PUSH_ARGUMENTS can (and typically does)
+ store the struct return address, this call is entirely redundant. */
+ if (struct_return && DEPRECATED_STORE_STRUCT_RETURN_P ())
+ DEPRECATED_STORE_STRUCT_RETURN (struct_addr, sp);
+
+ /* Write the stack pointer. This is here because the statements above
+ might fool with it. On SPARC, this write also stores the register
+ window into the right place in the new stack frame, which otherwise
+ wouldn't happen. (See store_inferior_registers in sparc-nat.c.) */
+ /* NOTE: cagney/2003-03-23: Disable this code when there is a
+ push_dummy_call() method. Since that method will have already
+ stored the stack pointer (as part of creating the fake call
+ frame), and none of the code following that code adjusts the
+ stack-pointer value, the below call is entirely redundant. */
+ if (DEPRECATED_DUMMY_WRITE_SP_P ())
+ DEPRECATED_DUMMY_WRITE_SP (sp);
+
+ if (SAVE_DUMMY_FRAME_TOS_P ())
+ SAVE_DUMMY_FRAME_TOS (sp);
+
+ {
+ char *name;
+ struct symbol *symbol;
+
+ name = NULL;
+ symbol = find_pc_function (funaddr);
+ if (symbol)
+ {
+ name = SYMBOL_PRINT_NAME (symbol);
+ }
+ else
+ {
+ /* Try the minimal symbols. */
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
+
+ if (msymbol)
+ {
+ name = SYMBOL_PRINT_NAME (msymbol);
+ }
+ }
+ if (name == NULL)
+ {
+ char format[80];
+ sprintf (format, "at %s", local_hex_format ());
+ name = alloca (80);
+ /* FIXME-32x64: assumes funaddr fits in a long. */
+ sprintf (name, format, (unsigned long) funaddr);
+ }
+
+ {
+ /* Execute a "stack dummy", a piece of code stored in the stack
+ by the debugger to be executed in the inferior.
+
+ The dummy's frame is automatically popped whenever that break
+ is hit. If that is the first time the program stops,
+ call_function_by_hand returns to its caller with that frame
+ already gone and sets RC to 0.
+
+ Otherwise, set RC to a non-zero value. If the called
+ function receives a random signal, we do not allow the user
+ to continue executing it as this may not work. The dummy
+ frame is poped and we return 1. If we hit a breakpoint, we
+ leave the frame in place and return 2 (the frame will
+ eventually be popped when we do hit the dummy end
+ breakpoint). */
+
+ CORE_ADDR addr = real_pc + CALL_DUMMY_START_OFFSET;
+ struct regcache *buffer = retbuf;
+ struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+ int saved_async = 0;
+ struct breakpoint *bpt;
+ struct symtab_and_line sal;
+
+ /* Now proceed, having reached the desired place. */
+ clear_proceed_status ();
+
+ init_sal (&sal); /* initialize to zeroes */
+ if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
+ {
+ sal.pc = CALL_DUMMY_ADDRESS ();
+ }
+ else
+ {
+ /* If defined, CALL_DUMMY_BREAKPOINT_OFFSET is where we need
+ to put a breakpoint instruction. If not, the call dummy
+ already has the breakpoint instruction in it.
+
+ ADDR IS THE ADDRESS of the call dummy plus the
+ CALL_DUMMY_START_OFFSET, so we need to subtract the
+ CALL_DUMMY_START_OFFSET. */
+ sal.pc = (addr - (CALL_DUMMY_START_OFFSET
+ + CALL_DUMMY_BREAKPOINT_OFFSET));
+ }
+ 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. */
+ struct frame_id frame = frame_id_build (read_fp (), sal.pc);
+ /* Create a momentary breakpoint at the return address of the
+ inferior. That way it breaks when it returns. */
+ bpt = set_momentary_breakpoint (sal, frame, bp_call_dummy);
+ bpt->disposition = disp_del;
+ }
+
+ /* If all error()s out of proceed ended up calling normal_stop
+ (and perhaps they should; it already does in the special case
+ of error out of resume()), then we wouldn't need this. */
+ make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
+
+ disable_watchpoints_before_interactive_call_start ();
+ proceed_to_finish = 1; /* We want stop_registers, please... */
+
+ if (target_can_async_p ())
+ saved_async = target_async_mask (0);
+
+ proceed (addr, TARGET_SIGNAL_0, 0);
+
+ if (saved_async)
+ target_async_mask (saved_async);
+
+ enable_watchpoints_after_interactive_call_stop ();
+
+ discard_cleanups (old_cleanups);
+
+ if (stopped_by_random_signal)
+ /* We can stop during an inferior call because a signal is
+ received. */
+ rc = 1;
+ else if (!stop_stack_dummy)
+ /* We may also stop prematurely because we hit a breakpoint in
+ the called routine. */
+ rc = 2;
+ else
+ {
+ /* On normal return, the stack dummy has been popped
+ already. */
+ regcache_cpy_no_passthrough (buffer, stop_registers);
+ rc = 0;
+ }
+ }
+
+ if (rc == 1)
+ {
+ /* We stopped inside the FUNCTION because of a random signal.
+ Further execution of the FUNCTION is not allowed. */
+
+ if (unwind_on_signal_p)
+ {
+ /* The user wants the context restored. */
+
+ /* We must get back to the frame we were before the dummy
+ call. */
+ frame_pop (get_current_frame ());
+
+ /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
+ a C++ name with arguments and stuff. */
+ 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.",
+ name);
+ }
+ else
+ {
+ /* The user wants to stay in the frame where we stopped (default).*/
+
+ /* If we restored the inferior status (via the cleanup),
+ we would print a spurious error message (Unable to
+ restore previously selected frame), would write the
+ registers from the inf_status (which is wrong), and
+ would do other wrong things. */
+ discard_cleanups (inf_status_cleanup);
+ 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 ("\
+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.",
+ name);
+ }
+ }
+
+ if (rc == 2)
+ {
+ /* We hit a breakpoint inside the FUNCTION. */
+
+ /* If we restored the inferior status (via the cleanup), we
+ would print a spurious error message (Unable to restore
+ previously selected frame), would write the registers from
+ the inf_status (which is wrong), and would do other wrong
+ things. */
+ discard_cleanups (inf_status_cleanup);
+ discard_inferior_status (inf_status);
+
+ /* The following error message used to say "The expression
+ which contained the function call has been discarded." It
+ is a hard concept to explain in a few words. Ideally, GDB
+ would be able to resume evaluation of the expression when
+ the function finally is done executing. Perhaps 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 ("\
+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);
+ }
+
+ /* If we get here the called FUNCTION run to completion. */
+
+ /* Restore the inferior status, via its cleanup. At this stage,
+ leave the RETBUF alone. */
+ do_cleanups (inf_status_cleanup);
+
+ /* Figure out the value returned by the function. */
+ /* elz: I defined this new macro for the hppa architecture only.
+ this gives us a way to get the value returned by the function
+ from the stack, at the same address we told the function to put
+ it. We cannot assume on the pa that r28 still contains the
+ address of the returned structure. Usually this will be
+ overwritten by the callee. I don't know about other
+ architectures, so I defined this macro */
+#ifdef VALUE_RETURNED_FROM_STACK
+ if (struct_return)
+ {
+ do_cleanups (retbuf_cleanup);
+ return VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
+ }
+#endif
+ /* NOTE: cagney/2002-09-10: Only when the stack has been correctly
+ aligned (using frame_align()) do we can trust STRUCT_ADDR and
+ fetch the return value direct from the stack. This lack of
+ trust comes about because legacy targets have a nasty habit of
+ silently, and local to PUSH_ARGUMENTS(), moving STRUCT_ADDR.
+ For such targets, just hope that value_being_returned() can
+ find the adjusted value. */
+ if (struct_return && gdbarch_frame_align_p (current_gdbarch))
+ {
+ struct value *retval = value_at (value_type, struct_addr, NULL);
+ do_cleanups (retbuf_cleanup);
+ return retval;
+ }
+ else
+ {
+ struct value *retval = value_being_returned (value_type, retbuf,
+ struct_return);
+ do_cleanups (retbuf_cleanup);
+ return retval;
+ }
+ }
+}
+
+void _initialize_infcall (void);
+
+void
+_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\n\
+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", "\
+Show coercion of floats to doubles when calling functions\n\
+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",
+ NULL, NULL, &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.\n\
+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.", "\
+Set unwinding of stack if a signal is received while in a call dummy.\n\
+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.",
+ NULL, NULL, &setlist, &showlist);
+}
--- /dev/null
+/* Perform an inferior function call, for GDB, the GNU debugger.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef INFCALL_H
+#define INFCALL_H
+
+struct value;
+
+/* Perform a function call in the inferior.
+
+ ARGS is a vector of values of arguments (NARGS of them). FUNCTION
+ is a value, the function to be called. Returns a value
+ representing what the function returned. May fail to return, if a
+ breakpoint or signal is hit during the execution of the function.
+
+ ARGS is modified to contain coerced values. */
+
+extern struct value *call_function_by_hand (struct value *function, int nargs,
+ struct value **args);
+
+#endif
#define GO_USAGE "Usage: go <location>\n"
-static void breakpoint_auto_delete_contents (void *);
-
#define ERROR_NO_INFERIOR \
if (!target_has_execution) error ("The program is not being run.");
proceed (oursig == TARGET_SIGNAL_0 ? (CORE_ADDR) -1 : stop_pc, oursig, 0);
}
-/* Call breakpoint_auto_delete on the current contents of the bpstat
- pointed to by arg (which is really a bpstat *). */
-
-static void
-breakpoint_auto_delete_contents (void *arg)
-{
- breakpoint_auto_delete (*(bpstat *) arg);
-}
-
-
-/* Execute a "stack dummy", a piece of code stored in the stack
- by the debugger to be executed in the inferior.
-
- To call: first, do PUSH_DUMMY_FRAME.
- Then push the contents of the dummy. It should end with a breakpoint insn.
- Then call here, passing address at which to start the dummy.
-
- The contents of all registers are saved before the dummy frame is popped
- and copied into the buffer BUFFER.
-
- The dummy's frame is automatically popped whenever that break is hit.
- If that is the first time the program stops, run_stack_dummy
- returns to its caller with that frame already gone and returns 0.
-
- Otherwise, run_stack-dummy returns a non-zero value.
- If the called function receives a random signal, we do not allow the user
- to continue executing it as this may not work. The dummy frame is poped
- and we return 1.
- If we hit a breakpoint, we leave the frame in place and return 2 (the frame
- will eventually be popped when we do hit the dummy end breakpoint). */
-
-int
-run_stack_dummy (CORE_ADDR addr, struct regcache *buffer)
-{
- struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
- int saved_async = 0;
- struct breakpoint *bpt;
- struct symtab_and_line sal;
-
- /* Now proceed, having reached the desired place. */
- clear_proceed_status ();
-
- init_sal (&sal); /* initialize to zeroes */
- if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
- {
- sal.pc = CALL_DUMMY_ADDRESS ();
- }
- else
- {
- /* If defined, CALL_DUMMY_BREAKPOINT_OFFSET is where we need to
- put a breakpoint instruction. If not, the call dummy already
- has the breakpoint instruction in it.
-
- ADDR IS THE ADDRESS of the call dummy plus the
- CALL_DUMMY_START_OFFSET, so we need to subtract the
- CALL_DUMMY_START_OFFSET. */
- sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET;
- }
- 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. */
- struct frame_id frame = frame_id_build (read_fp (), sal.pc);
- /* Create a momentary breakpoint at the return address of the
- inferior. That way it breaks when it returns. */
- bpt = set_momentary_breakpoint (sal, frame, bp_call_dummy);
- bpt->disposition = disp_del;
- }
-
- /* If all error()s out of proceed ended up calling normal_stop (and
- perhaps they should; it already does in the special case of error
- out of resume()), then we wouldn't need this. */
- make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
-
- disable_watchpoints_before_interactive_call_start ();
- proceed_to_finish = 1; /* We want stop_registers, please... */
-
- if (target_can_async_p ())
- saved_async = target_async_mask (0);
-
- proceed (addr, TARGET_SIGNAL_0, 0);
-
- if (saved_async)
- target_async_mask (saved_async);
-
- enable_watchpoints_after_interactive_call_stop ();
-
- discard_cleanups (old_cleanups);
-
- /* We can stop during an inferior call because a signal is received. */
- if (stopped_by_random_signal)
- return 1;
-
- /* We may also stop prematurely because we hit a breakpoint in the
- called routine. */
- if (!stop_stack_dummy)
- return 2;
-
- /* On normal return, the stack dummy has been popped already. */
- regcache_cpy_no_passthrough (buffer, stop_registers);
- return 0;
-}
-\f
/* Proceed until we reach a different source line with pc greater than
our current one or exit the function. We skip calls in both cases.
extern void terminal_ours (void);
-extern int run_stack_dummy (CORE_ADDR , struct regcache *);
-
extern CORE_ADDR read_pc (void);
extern CORE_ADDR read_pc_pid (ptid_t);
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
get_frame_base (fi)))
{
- /* We need to setup fi->frame here because run_stack_dummy gets it wrong
- by assuming it's always FP. */
+ /* We need to setup fi->frame here because call_function_by_hand
+ gets it wrong by assuming it's always FP. */
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi), SP_REGNUM));
}
else
always be correct. mn10300_analyze_prologue will fix fi->frame if
it's not valid.
- We can be called with the PC in the call dummy under two circumstances.
- First, during normal backtracing, second, while figuring out the frame
- pointer just prior to calling the target function (see run_stack_dummy). */
+ We can be called with the PC in the call dummy under two
+ circumstances. First, during normal backtracing, second, while
+ figuring out the frame pointer just prior to calling the target
+ function (see call_function_by_hand). */
static void
mn10300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
#include "gdb_regex.h"
#include "regcache.h"
#include "block.h"
+#include "infcall.h"
#include <ctype.h>
#include "source.h"
#include "gdb_string.h"
#include "gdbcore.h"
+#include "infcall.h"
extern void _initialize_scheme_language (void);
static struct value *evaluate_subexp_scm (struct type *, struct expression *,
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
get_frame_base (fi)))
{
- /* We need to setup fi->frame here because run_stack_dummy gets it wrong
- by assuming it's always FP. */
+ /* We need to setup fi->frame here because call_function_by_hand
+ gets it wrong by assuming it's always FP. */
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi),
SP_REGNUM));
get_frame_extra_info (fi)->return_pc = deprecated_read_register_dummy (get_frame_pc (fi),
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
get_frame_base (fi)))
{
- /* We need to setup fi->frame here because run_stack_dummy gets it wrong
- by assuming it's always FP. */
+ /* We need to setup fi->frame here because call_function_by_hand
+ gets it wrong by assuming it's always FP. */
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi), SP_REGNUM));
get_frame_extra_info (fi)->return_pc =
deprecated_read_register_dummy (get_frame_pc (fi),
Adjust the call_dummy_breakpoint_offset for the bp_call_dummy breakpoint
to the proper address in the call dummy, so that `finish' after a stop
in a call dummy works.
- Tweeking current_gdbarch is not an optimal solution, but the call to
- sparc_fix_call_dummy is immediately followed by a call to run_stack_dummy,
- which is the only function where dummy_breakpoint_offset is actually
- used, if it is non-zero. */
+
+ Tweeking current_gdbarch is not an optimal solution, but the call
+ to sparc_fix_call_dummy is immediately followed by a call to
+ call_function_by_hand, which is the only function where
+ dummy_breakpoint_offset is actually used, if it is non-zero. */
if (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
|| TYPE_CODE (value_type) == TYPE_CODE_UNION)
{
#define target_async(CALLBACK,CONTEXT) \
(current_target.to_async((CALLBACK), (CONTEXT)))
-/* This is to be used ONLY within run_stack_dummy(). It
- provides a workaround, to have inferior function calls done in
- sychronous mode, even though the target is asynchronous. After
+/* This is to be used ONLY within call_function_by_hand(). It provides
+ a workaround, to have inferior function calls done in sychronous
+ mode, even though the target is asynchronous. After
target_async_mask(0) is called, calls to target_can_async_p() will
return FALSE , so that target_resume() will not try to start the
target asynchronously. After the inferior stops, we IMMEDIATELY
restore the previous nature of the target, by calling
target_async_mask(1). After that, target_can_async_p() will return
- TRUE. ANY OTHER USE OF THIS FEATURE IS DEPRECATED.
+ TRUE. ANY OTHER USE OF THIS FEATURE IS DEPRECATED.
FIXME ezannoni 1999-12-13: we won't need this once we move
the turning async on and off to the single execution commands,
be valid only if this routine uses FP. For previous frames, fi-frame will
always be correct (since that is derived from v850_frame_chain ()).
- We can be called with the PC in the call dummy under two circumstances.
- First, during normal backtracing, second, while figuring out the frame
- pointer just prior to calling the target function (see run_stack_dummy). */
+ We can be called with the PC in the call dummy under two
+ circumstances. First, during normal backtracing, second, while
+ figuring out the frame pointer just prior to calling the target
+ function (see call_function_by_hand). */
static void
v850_init_extra_frame_info (int fromleaf, struct frame_info *fi)
#include "gdb_string.h"
#include "doublest.h"
#include <math.h>
+#include "infcall.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C). */
#include "regcache.h"
#include "cp-abi.h"
#include "block.h"
+#include "infcall.h"
#include <errno.h>
#include "gdb_string.h"
static int typecmp (int staticp, int varargs, int nargs,
struct field t1[], struct value *t2[]);
-static CORE_ADDR find_function_addr (struct value *, struct type **);
-static struct value *value_arg_coerce (struct value *, struct type *, int);
-
-
static CORE_ADDR value_push (CORE_ADDR, struct value *);
static struct value *search_struct_field (char *, struct value *, int,
int overload_resolution = 0;
-/* 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 stack
- and restore the context to what as it was before the call.
- The default is to stop in the frame where the signal was received. */
-
-int unwind_on_signal_p = 0;
-
-/* How you should pass arguments to a function depends on whether it
- was defined in K&R style or prototype style. If you define a
- function using the K&R syntax that takes a `float' argument, then
- callers must pass that argument as a `double'. If you define the
- function using the prototype syntax, then you must pass the
- argument as a `float', with no promotion.
-
- Unfortunately, on certain older platforms, the debug info doesn't
- indicate reliably how each function was defined. A function type's
- TYPE_FLAG_PROTOTYPED flag may be clear, even if the function was
- defined in prototype style. When calling a function whose
- TYPE_FLAG_PROTOTYPED flag is clear, GDB consults this flag to decide
- what to do.
-
- For modern targets, it is proper to assume that, if the prototype
- flag is clear, that can be trusted: `float' arguments should be
- promoted to `double'. For some older targets, if the prototype
- flag is clear, that doesn't tell us anything. The default is to
- trust the debug information; the user can override this behavior
- with "set coerce-float-to-double 0". */
-
-static int coerce_float_to_double;
-\f
-
/* Find the address of function name NAME in the inferior. */
struct value *
return sp;
}
-/* Perform the standard coercions that are specified
- for arguments to be passed to C functions.
-
- If PARAM_TYPE is non-NULL, it is the expected parameter type.
- IS_PROTOTYPED is non-zero if the function declaration is prototyped. */
-
-static struct value *
-value_arg_coerce (struct value *arg, struct type *param_type,
- int is_prototyped)
-{
- register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
- register struct type *type
- = param_type ? check_typedef (param_type) : arg_type;
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_REF:
- if (TYPE_CODE (arg_type) != TYPE_CODE_REF
- && TYPE_CODE (arg_type) != TYPE_CODE_PTR)
- {
- arg = value_addr (arg);
- VALUE_TYPE (arg) = param_type;
- return arg;
- }
- break;
- case TYPE_CODE_INT:
- case TYPE_CODE_CHAR:
- case TYPE_CODE_BOOL:
- case TYPE_CODE_ENUM:
- /* If we don't have a prototype, coerce to integer type if necessary. */
- if (!is_prototyped)
- {
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
- type = builtin_type_int;
- }
- /* Currently all target ABIs require at least the width of an integer
- type for an argument. We may have to conditionalize the following
- type coercion for future targets. */
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
- type = builtin_type_int;
- break;
- case TYPE_CODE_FLT:
- if (!is_prototyped && coerce_float_to_double)
- {
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
- type = builtin_type_double;
- else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double))
- type = builtin_type_long_double;
- }
- break;
- case TYPE_CODE_FUNC:
- type = lookup_pointer_type (type);
- break;
- case TYPE_CODE_ARRAY:
- /* Arrays are coerced to pointers to their first element, unless
- they are vectors, in which case we want to leave them alone,
- because they are passed by value. */
- if (current_language->c_style_arrays)
- if (!TYPE_VECTOR (type))
- type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
- break;
- case TYPE_CODE_UNDEF:
- case TYPE_CODE_PTR:
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_VOID:
- case TYPE_CODE_SET:
- case TYPE_CODE_RANGE:
- case TYPE_CODE_STRING:
- case TYPE_CODE_BITSTRING:
- case TYPE_CODE_ERROR:
- case TYPE_CODE_MEMBER:
- case TYPE_CODE_METHOD:
- case TYPE_CODE_COMPLEX:
- default:
- break;
- }
-
- return value_cast (type, arg);
-}
-
-/* Determine a function's address and its return type from its value.
- Calls error() if the function is not valid for calling. */
-
-static CORE_ADDR
-find_function_addr (struct value *function, struct type **retval_type)
-{
- register struct type *ftype = check_typedef (VALUE_TYPE (function));
- register enum type_code code = TYPE_CODE (ftype);
- struct type *value_type;
- CORE_ADDR funaddr;
-
- /* If it's a member function, just look at the function
- part of it. */
-
- /* Determine address to call. */
- if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
- {
- funaddr = VALUE_ADDRESS (function);
- value_type = TYPE_TARGET_TYPE (ftype);
- }
- else if (code == TYPE_CODE_PTR)
- {
- funaddr = value_as_address (function);
- ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
- if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
- || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
- {
- funaddr = CONVERT_FROM_FUNC_PTR_ADDR (funaddr);
- value_type = TYPE_TARGET_TYPE (ftype);
- }
- else
- value_type = builtin_type_int;
- }
- else if (code == TYPE_CODE_INT)
- {
- /* Handle the case of functions lacking debugging info.
- Their values are characters since their addresses are char */
- if (TYPE_LENGTH (ftype) == 1)
- funaddr = value_as_address (value_addr (function));
- else
- /* Handle integer used as address of a function. */
- funaddr = (CORE_ADDR) value_as_long (function);
-
- value_type = builtin_type_int;
- }
- else
- error ("Invalid data type for function to be called.");
-
- *retval_type = value_type;
- return funaddr;
-}
-
-/* All this stuff with a dummy frame may seem unnecessarily complicated
- (why not just save registers in GDB?). The purpose of pushing a dummy
- frame which looks just like a real frame is so that if you call a
- function and then hit a breakpoint (get a signal, etc), "backtrace"
- will look right. Whether the backtrace needs to actually show the
- stack at the time the inferior function was called is debatable, but
- it certainly needs to not display garbage. So if you are contemplating
- making dummy frames be different from normal frames, consider that. */
-
-/* Perform a function call in the inferior.
- ARGS is a vector of values of arguments (NARGS of them).
- FUNCTION is a value, the function to be called.
- Returns a value representing what the function returned.
- May fail to return, if a breakpoint or signal is hit
- during the execution of the function.
-
- ARGS is modified to contain coerced values. */
-
-struct value *
-call_function_by_hand (struct value *function, int nargs, struct value **args)
-{
- register CORE_ADDR sp;
- register int i;
- int rc;
- CORE_ADDR start_sp;
- /* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
- is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
- and remove any extra bytes which might exist because ULONGEST is
- bigger than REGISTER_SIZE.
-
- NOTE: This is pretty wierd, as the call dummy is actually a
- sequence of instructions. But CISC machines will have
- to pack the instructions into REGISTER_SIZE units (and
- so will RISC machines for which INSTRUCTION_SIZE is not
- REGISTER_SIZE).
-
- NOTE: This is pretty stupid. CALL_DUMMY should be in strict
- target byte order. */
-
- static ULONGEST *dummy;
- int sizeof_dummy1;
- char *dummy1;
- CORE_ADDR dummy_addr;
- CORE_ADDR old_sp;
- struct type *value_type;
- unsigned char struct_return;
- CORE_ADDR struct_addr = 0;
- struct regcache *retbuf;
- struct cleanup *retbuf_cleanup;
- struct inferior_status *inf_status;
- struct cleanup *inf_status_cleanup;
- CORE_ADDR funaddr;
- int using_gcc; /* Set to version of gcc in use, or zero if not gcc */
- CORE_ADDR real_pc;
- struct type *param_type = NULL;
- struct type *ftype = check_typedef (SYMBOL_TYPE (function));
- int n_method_args = 0;
-
- dummy = alloca (SIZEOF_CALL_DUMMY_WORDS);
- sizeof_dummy1 = REGISTER_SIZE * SIZEOF_CALL_DUMMY_WORDS / sizeof (ULONGEST);
- dummy1 = alloca (sizeof_dummy1);
- memcpy (dummy, CALL_DUMMY_WORDS, SIZEOF_CALL_DUMMY_WORDS);
-
- if (!target_has_execution)
- noprocess ();
-
- /* Create a cleanup chain that contains the retbuf (buffer
- containing the register values). This chain is create BEFORE the
- inf_status chain so that the inferior status can cleaned up
- (restored or discarded) without having the retbuf freed. */
- retbuf = regcache_xmalloc (current_gdbarch);
- retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
-
- /* A cleanup for the inferior status. Create this AFTER the retbuf
- so that this can be discarded or applied without interfering with
- the regbuf. */
- inf_status = save_inferior_status (1);
- inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
-
- if (DEPRECATED_PUSH_DUMMY_FRAME_P ())
- {
- /* DEPRECATED_PUSH_DUMMY_FRAME is responsible for saving the
- inferior registers (and frame_pop() for restoring them). (At
- least on most machines) they are saved on the stack in the
- inferior. */
- DEPRECATED_PUSH_DUMMY_FRAME;
- }
- else
- {
- /* 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 tpid as a parameter, and returns a dummy
- frame handle. The handle can then be used further down as a
- parameter 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 ();
- }
-
- old_sp = read_sp ();
-
- /* Ensure that the initial SP is correctly aligned. */
- if (gdbarch_frame_align_p (current_gdbarch))
- {
- /* NOTE: cagney/2002-09-18:
-
- On a RISC architecture, a void parameterless generic dummy
- frame (i.e., no parameters, no result) typically does not
- need to push anything the stack and hence can leave SP and
- FP. Similarly, a framelss (possibly leaf) function does not
- push anything on the stack and, hence, that too can leave FP
- and SP unchanged. As a consequence, a sequence of void
- parameterless generic dummy frame calls to frameless
- functions will create a sequence of effectively identical
- frames (SP, FP and TOS and PC the same). This, not
- suprisingly, results in what appears to be a stack in an
- infinite loop --- when GDB tries to find a generic dummy
- frame on the internal dummy frame stack, it will always find
- the first one.
-
- To avoid this problem, the code below always grows the stack.
- That way, two dummy frames can never be identical. It does
- burn a few bytes of stack but that is a small price to pay
- :-). */
- sp = gdbarch_frame_align (current_gdbarch, old_sp);
- if (sp == old_sp)
- {
- if (INNER_THAN (1, 2))
- /* Stack grows down. */
- sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
- else
- /* Stack grows up. */
- sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
- }
- gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp)
- || (INNER_THAN (2, 1) && sp >= old_sp));
- }
- else
- /* FIXME: cagney/2002-09-18: Hey, you loose! Who knows how badly
- aligned the SP is! Further, per comment above, if the generic
- dummy frame ends up empty (because nothing is pushed) GDB won't
- be able to correctly perform back traces. If a target is
- having trouble with backtraces, first thing to do is add
- FRAME_ALIGN() to its architecture vector. After that, try
- adding SAVE_DUMMY_FRAME_TOS() and modifying
- DEPRECATED_FRAME_CHAIN so that when the next outer frame is a
- generic dummy, it returns the current frame's base. */
- sp = old_sp;
-
- if (INNER_THAN (1, 2))
- {
- /* Stack grows down */
- sp -= sizeof_dummy1;
- start_sp = sp;
- }
- else
- {
- /* Stack grows up */
- start_sp = sp;
- sp += sizeof_dummy1;
- }
-
- /* NOTE: cagney/2002-09-10: Don't bother re-adjusting the stack
- after allocating space for the call dummy. A target can specify
- a SIZEOF_DUMMY1 (via SIZEOF_CALL_DUMMY_WORDS) such that all local
- alignment requirements are met. */
-
- funaddr = find_function_addr (function, &value_type);
- CHECK_TYPEDEF (value_type);
-
- {
- struct block *b = block_for_pc (funaddr);
- /* If compiled without -g, assume GCC 2. */
- using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
- }
-
- /* Are we returning a value using a structure return or a normal
- value return? */
-
- struct_return = using_struct_return (function, funaddr, value_type,
- using_gcc);
-
- /* Create a call sequence customized for this function
- and the number of arguments for it. */
- for (i = 0; i < (int) (SIZEOF_CALL_DUMMY_WORDS / sizeof (dummy[0])); i++)
- store_unsigned_integer (&dummy1[i * REGISTER_SIZE],
- REGISTER_SIZE,
- (ULONGEST) dummy[i]);
-
-#ifdef GDB_TARGET_IS_HPPA
- real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
- value_type, using_gcc);
-#else
- if (FIX_CALL_DUMMY_P ())
- {
- /* gdb_assert (CALL_DUMMY_LOCATION == ON_STACK) true? */
- FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args, value_type,
- using_gcc);
- }
- real_pc = start_sp;
-#endif
-
- switch (CALL_DUMMY_LOCATION)
- {
- case ON_STACK:
- dummy_addr = start_sp;
- write_memory (start_sp, (char *) dummy1, sizeof_dummy1);
- if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
- generic_save_call_dummy_addr (start_sp, start_sp + sizeof_dummy1);
- break;
- case AT_ENTRY_POINT:
- real_pc = funaddr;
- dummy_addr = CALL_DUMMY_ADDRESS ();
- if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
- /* NOTE: cagney/2002-04-13: The entry point is going to be
- modified with a single breakpoint. */
- generic_save_call_dummy_addr (CALL_DUMMY_ADDRESS (),
- CALL_DUMMY_ADDRESS () + 1);
- break;
- default:
- internal_error (__FILE__, __LINE__, "bad switch");
- }
-
-#ifdef lint
- sp = old_sp; /* It really is used, for some ifdef's... */
-#endif
-
- if (nargs < TYPE_NFIELDS (ftype))
- error ("too few arguments in function call");
-
- for (i = nargs - 1; i >= 0; i--)
- {
- int prototyped;
-
- /* FIXME drow/2002-05-31: Should just always mark methods as
- prototyped. Can we respect TYPE_VARARGS? Probably not. */
- if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
- prototyped = 1;
- else
- prototyped = TYPE_PROTOTYPED (ftype);
-
- if (i < TYPE_NFIELDS (ftype))
- args[i] = value_arg_coerce (args[i], TYPE_FIELD_TYPE (ftype, i),
- prototyped);
- else
- args[i] = value_arg_coerce (args[i], NULL, 0);
-
- /*elz: this code is to handle the case in which the function to be called
- has a pointer to function as parameter and the corresponding actual argument
- is the address of a function and not a pointer to function variable.
- In aCC compiled code, the calls through pointers to functions (in the body
- of the function called by hand) are made via $$dyncall_external which
- requires some registers setting, this is taken care of if we call
- via a function pointer variable, but not via a function address.
- In cc this is not a problem. */
-
- if (using_gcc == 0)
- if (param_type && TYPE_CODE (ftype) != TYPE_CODE_METHOD)
- /* if this parameter is a pointer to function */
- if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
- if (TYPE_CODE (TYPE_TARGET_TYPE (param_type)) == TYPE_CODE_FUNC)
- /* elz: FIXME here should go the test about the compiler used
- to compile the target. We want to issue the error
- message only if the compiler used was HP's aCC.
- If we used HP's cc, then there is no problem and no need
- to return at this point */
- if (using_gcc == 0) /* && compiler == aCC */
- /* go see if the actual parameter is a variable of type
- pointer to function or just a function */
- if (args[i]->lval == not_lval)
- {
- char *arg_name;
- if (find_pc_partial_function ((CORE_ADDR) args[i]->aligner.contents[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);
- }
- }
-
- if (REG_STRUCT_HAS_ADDR_P ())
- {
- /* This is a machine like the sparc, where we may need to pass a
- 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]));
- if ((TYPE_CODE (arg_type) == TYPE_CODE_STRUCT
- || TYPE_CODE (arg_type) == TYPE_CODE_UNION
- || TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
- || TYPE_CODE (arg_type) == TYPE_CODE_STRING
- || TYPE_CODE (arg_type) == TYPE_CODE_BITSTRING
- || TYPE_CODE (arg_type) == TYPE_CODE_SET
- || (TYPE_CODE (arg_type) == TYPE_CODE_FLT
- && TYPE_LENGTH (arg_type) > 8)
- )
- && REG_STRUCT_HAS_ADDR (using_gcc, arg_type))
- {
- CORE_ADDR addr;
- int len; /* = TYPE_LENGTH (arg_type); */
- int aligned_len;
- arg_type = check_typedef (VALUE_ENCLOSING_TYPE (args[i]));
- len = TYPE_LENGTH (arg_type);
-
- if (STACK_ALIGN_P ())
- /* MVS 11/22/96: I think at least some of this
- stack_align code is really broken. Better to let
- PUSH_ARGUMENTS adjust the stack in a target-defined
- manner. */
- aligned_len = STACK_ALIGN (len);
- else
- aligned_len = len;
- if (INNER_THAN (1, 2))
- {
- /* stack grows downward */
- sp -= aligned_len;
- /* ... so the address of the thing we push is the
- stack pointer after we push it. */
- addr = sp;
- }
- else
- {
- /* The stack grows up, so the address of the thing
- we push is the stack pointer before we push it. */
- addr = sp;
- sp += aligned_len;
- }
- /* Push the structure. */
- 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),
- (LONGEST) addr); */
- args[i] = value_from_pointer (lookup_pointer_type (arg_type),
- addr);
- }
- }
- }
-
-
- /* Reserve space for the return structure to be written on the
- stack, if necessary. Make certain that the value is correctly
- aligned. */
-
- if (struct_return)
- {
- int len = TYPE_LENGTH (value_type);
- if (STACK_ALIGN_P ())
- /* NOTE: cagney/2003-03-22: Should rely on frame align, rather
- than stack align to force the alignment of the stack. */
- len = STACK_ALIGN (len);
- if (INNER_THAN (1, 2))
- {
- /* Stack grows downward. Align STRUCT_ADDR and SP after
- making space for the return value. */
- sp -= len;
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
- struct_addr = sp;
- }
- else
- {
- /* Stack grows upward. Align the frame, allocate space, and
- then again, re-align the frame??? */
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
- struct_addr = sp;
- sp += len;
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
- }
- }
-
- /* elz: on HPPA no need for this extra alignment, maybe it is needed
- on other architectures. This is because all the alignment is
- taken care of in the above code (ifdef REG_STRUCT_HAS_ADDR) and
- in hppa_push_arguments */
- /* NOTE: cagney/2003-03-24: The below code is very broken. Given an
- odd sized parameter the below will mis-align the stack. As was
- suggested back in '96, better to let PUSH_ARGUMENTS handle it. */
- if (DEPRECATED_EXTRA_STACK_ALIGNMENT_NEEDED)
- {
- /* MVS 11/22/96: I think at least some of this stack_align code
- is really broken. Better to let push_dummy_call() adjust the
- stack in a target-defined manner. */
- if (STACK_ALIGN_P () && INNER_THAN (1, 2))
- {
- /* If stack grows down, we must leave a hole at the top. */
- int len = 0;
-
- for (i = nargs - 1; i >= 0; i--)
- len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
- if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
- len += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
- sp -= STACK_ALIGN (len) - len;
- }
- }
-
- /* Create the dummy stack frame. Pass in the call dummy address as,
- presumably, the ABI code knows where, in the call dummy, the
- return address should be pointed. */
- if (gdbarch_push_dummy_call_p (current_gdbarch))
- /* When there is no push_dummy_call method, should this code
- simply error out. That would the implementation of this method
- for all ABIs (which is probably a good thing). */
- sp = gdbarch_push_dummy_call (current_gdbarch, current_regcache,
- dummy_addr, nargs, args, sp, struct_return,
- struct_addr);
- else if (DEPRECATED_PUSH_ARGUMENTS_P ())
- /* Keep old targets working. */
- sp = DEPRECATED_PUSH_ARGUMENTS (nargs, args, sp, struct_return,
- struct_addr);
- else
- sp = legacy_push_arguments (nargs, args, sp, struct_return, struct_addr);
-
- if (DEPRECATED_PUSH_RETURN_ADDRESS_P ())
- /* for targets that use no CALL_DUMMY */
- /* There are a number of targets now which actually don't write
- any CALL_DUMMY instructions into the target, but instead just
- save the machine state, push the arguments, and jump directly
- to the callee function. Since this doesn't actually involve
- executing a JSR/BSR instruction, the return address must be set
- up by hand, either by pushing onto the stack or copying into a
- return-address register as appropriate. Formerly this has been
- done in PUSH_ARGUMENTS, but that's overloading its
- functionality a bit, so I'm making it explicit to do it here. */
- sp = DEPRECATED_PUSH_RETURN_ADDRESS (real_pc, sp);
-
- /* NOTE: cagney/2003-03-23: Diable this code when there is a
- push_dummy_call() method. Since that method will have already
- handled any alignment issues, the code below is entirely
- redundant. */
- if (!gdbarch_push_dummy_call_p (current_gdbarch)
- && STACK_ALIGN_P () && !INNER_THAN (1, 2))
- {
- /* If stack grows up, we must leave a hole at the bottom, note
- that sp already has been advanced for the arguments! */
- if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
- sp += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
- sp = STACK_ALIGN (sp);
- }
-
-/* XXX This seems wrong. For stacks that grow down we shouldn't do
- anything here! */
- /* MVS 11/22/96: I think at least some of this stack_align code is
- really broken. Better to let PUSH_ARGUMENTS adjust the stack in
- a target-defined manner. */
- if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
- if (INNER_THAN (1, 2))
- {
- /* stack grows downward */
- sp -= DEPRECATED_CALL_DUMMY_STACK_ADJUST;
- }
-
- /* Store the address at which the structure is supposed to be
- written. */
- /* NOTE: 2003-03-24: Since PUSH_ARGUMENTS can (and typically does)
- store the struct return address, this call is entirely redundant. */
- if (struct_return && DEPRECATED_STORE_STRUCT_RETURN_P ())
- DEPRECATED_STORE_STRUCT_RETURN (struct_addr, sp);
-
- /* Write the stack pointer. This is here because the statements above
- might fool with it. On SPARC, this write also stores the register
- window into the right place in the new stack frame, which otherwise
- wouldn't happen. (See store_inferior_registers in sparc-nat.c.) */
- /* NOTE: cagney/2003-03-23: Disable this code when there is a
- push_dummy_call() method. Since that method will have already
- stored the stack pointer (as part of creating the fake call
- frame), and none of the code following that code adjusts the
- stack-pointer value, the below call is entirely redundant. */
- if (DEPRECATED_DUMMY_WRITE_SP_P ())
- DEPRECATED_DUMMY_WRITE_SP (sp);
-
- if (SAVE_DUMMY_FRAME_TOS_P ())
- SAVE_DUMMY_FRAME_TOS (sp);
-
- {
- char *name;
- struct symbol *symbol;
-
- name = NULL;
- symbol = find_pc_function (funaddr);
- if (symbol)
- {
- name = SYMBOL_PRINT_NAME (symbol);
- }
- else
- {
- /* Try the minimal symbols. */
- struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
-
- if (msymbol)
- {
- name = SYMBOL_PRINT_NAME (msymbol);
- }
- }
- if (name == NULL)
- {
- char format[80];
- sprintf (format, "at %s", local_hex_format ());
- name = alloca (80);
- /* FIXME-32x64: assumes funaddr fits in a long. */
- sprintf (name, format, (unsigned long) funaddr);
- }
-
- /* Execute the stack dummy routine, calling FUNCTION.
- When it is done, discard the empty frame
- after storing the contents of all regs into retbuf. */
- rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
-
- if (rc == 1)
- {
- /* We stopped inside the FUNCTION because of a random signal.
- Further execution of the FUNCTION is not allowed. */
-
- if (unwind_on_signal_p)
- {
- /* The user wants the context restored. */
-
- /* We must get back to the frame we were before the dummy
- call. */
- frame_pop (get_current_frame ());
-
- /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
- a C++ name with arguments and stuff. */
- 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.",
- name);
- }
- else
- {
- /* The user wants to stay in the frame where we stopped (default).*/
-
- /* If we restored the inferior status (via the cleanup),
- we would print a spurious error message (Unable to
- restore previously selected frame), would write the
- registers from the inf_status (which is wrong), and
- would do other wrong things. */
- discard_cleanups (inf_status_cleanup);
- 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 ("\
-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.",
- name);
- }
- }
-
- if (rc == 2)
- {
- /* We hit a breakpoint inside the FUNCTION. */
-
- /* If we restored the inferior status (via the cleanup), we
- would print a spurious error message (Unable to restore
- previously selected frame), would write the registers from
- the inf_status (which is wrong), and would do other wrong
- things. */
- discard_cleanups (inf_status_cleanup);
- discard_inferior_status (inf_status);
-
- /* The following error message used to say "The expression
- which contained the function call has been discarded." It
- is a hard concept to explain in a few words. Ideally, GDB
- would be able to resume evaluation of the expression when
- the function finally is done executing. Perhaps 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 ("\
-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);
- }
-
- /* If we get here the called FUNCTION run to completion. */
-
- /* Restore the inferior status, via its cleanup. At this stage,
- leave the RETBUF alone. */
- do_cleanups (inf_status_cleanup);
-
- /* Figure out the value returned by the function. */
- /* elz: I defined this new macro for the hppa architecture only.
- this gives us a way to get the value returned by the function
- from the stack, at the same address we told the function to put
- it. We cannot assume on the pa that r28 still contains the
- address of the returned structure. Usually this will be
- overwritten by the callee. I don't know about other
- architectures, so I defined this macro */
-#ifdef VALUE_RETURNED_FROM_STACK
- if (struct_return)
- {
- do_cleanups (retbuf_cleanup);
- return VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
- }
-#endif
- /* NOTE: cagney/2002-09-10: Only when the stack has been correctly
- aligned (using frame_align()) do we can trust STRUCT_ADDR and
- fetch the return value direct from the stack. This lack of
- trust comes about because legacy targets have a nasty habit of
- silently, and local to PUSH_ARGUMENTS(), moving STRUCT_ADDR.
- For such targets, just hope that value_being_returned() can
- find the adjusted value. */
- if (struct_return && gdbarch_frame_align_p (current_gdbarch))
- {
- struct value *retval = value_at (value_type, struct_addr, NULL);
- do_cleanups (retbuf_cleanup);
- return retval;
- }
- else
- {
- struct value *retval = value_being_returned (value_type, retbuf,
- struct_return);
- do_cleanups (retbuf_cleanup);
- return retval;
- }
- }
-}
-
/* Create a value for an array by allocating space in the inferior, copying
the data into that space, and then setting up an array value.
&setlist),
&showlist);
overload_resolution = 1;
-
- add_show_from_set (
- add_set_cmd ("unwindonsignal", no_class, var_boolean,
- (char *) &unwind_on_signal_p,
-"Set unwinding of stack if a signal is received while in a call dummy.\n\
-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.", &setlist),
- &showlist);
-
- add_show_from_set
- (add_set_cmd ("coerce-float-to-double", class_obscure, var_boolean,
- (char *) &coerce_float_to_double,
- "Set coercion of floats to doubles when calling functions\n"
- "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",
- &setlist),
- &showlist);
- coerce_float_to_double = 1;
}
extern struct value *value_slice (struct value *, int, int);
-extern struct value *call_function_by_hand (struct value *, int,
- struct value **);
-
extern struct value *value_literal_complex (struct value *, struct value *,
struct type *);