From d4cd23fa7442c4b9d684352744d4938b535e7db4 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Mon, 21 Apr 2003 16:48:41 +0000 Subject: 2003-04-21 Andrew Cagney * 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. --- gdb/ChangeLog | 34 ++ gdb/Makefile.in | 37 +- gdb/ada-lang.c | 1 + gdb/ada-valprint.c | 1 + gdb/arm-tdep.c | 4 +- gdb/avr-tdep.c | 4 +- gdb/breakpoint.h | 2 +- gdb/config/sparc/tm-sparc.h | 6 +- gdb/cris-tdep.c | 4 +- gdb/eval.c | 1 + gdb/gcore.c | 1 + gdb/hppa-tdep.c | 1 + gdb/infcall.c | 981 ++++++++++++++++++++++++++++++++++++++++++++ gdb/infcall.h | 39 ++ gdb/infcmd.c | 108 ----- gdb/inferior.h | 2 - gdb/mcore-tdep.c | 4 +- gdb/mn10300-tdep.c | 7 +- gdb/objc-lang.c | 1 + gdb/scm-lang.c | 1 + gdb/sh-tdep.c | 8 +- gdb/sparc-tdep.c | 9 +- gdb/target.h | 8 +- gdb/v850-tdep.c | 7 +- gdb/valarith.c | 1 + gdb/valops.c | 829 +------------------------------------ gdb/value.h | 3 - 27 files changed, 1119 insertions(+), 985 deletions(-) create mode 100644 gdb/infcall.c create mode 100644 gdb/infcall.h (limited to 'gdb') diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ad86a9055ca..fa435b5c7fb 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,37 @@ +2003-04-21 Andrew Cagney + + * 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 * i386-tdep.c (i386_num_register_names): New variable. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index a78ef16099a..a5d0f5f223b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -521,7 +521,9 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ 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 \ @@ -669,6 +671,7 @@ i386_linux_tdep_h = i386-linux-tdep.h 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 @@ -834,7 +837,9 @@ TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR) 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 \ @@ -1488,7 +1493,8 @@ abug-rom.o: abug-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ 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) @@ -1498,7 +1504,7 @@ ada-typeprint.o: ada-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_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) @@ -1681,7 +1687,7 @@ elfread.o: elfread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(elf_bfd_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) \ @@ -1723,7 +1729,7 @@ frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_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) \ @@ -1758,9 +1764,9 @@ hpacc-abi.o: hpacc-abi.c $(defs_h) $(value_h) $(gdb_regex_h) $(gdb_string_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) @@ -1830,6 +1836,9 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_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) \ @@ -1995,9 +2004,9 @@ ns32knbsd-tdep.o: ns32knbsd-tdep.c $(defs_h) $(ns32k_tdep_h) $(gdb_string_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) \ @@ -2150,7 +2159,7 @@ scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_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) @@ -2308,7 +2317,7 @@ v850ice.o: v850ice.c $(defs_h) $(gdb_string_h) $(frame_h) $(symtab_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) \ diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index bc0809d3e2a..b047442d6f3 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -39,6 +39,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ada-lang.h" #include "ui-out.h" #include "block.h" +#include "infcall.h" struct cleanup *unresolved_names; diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c index 8633f2c7893..5b90c0683cd 100644 --- a/gdb/ada-valprint.c +++ b/gdb/ada-valprint.c @@ -30,6 +30,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #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 diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 0a029e84702..f104952a551 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -1257,8 +1257,8 @@ static LONGEST arm_call_dummy_words[] = 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 diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index b787c8141cf..16a21297e0a 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -753,8 +753,8 @@ avr_init_extra_frame_info (int fromleaf, struct frame_info *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), AVR_PC_REGNUM)); } diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index e8c8750eef4..b2c53fc6328 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -623,7 +623,7 @@ extern void set_longjmp_resume_breakpoint (CORE_ADDR, struct frame_id); 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. diff --git a/gdb/config/sparc/tm-sparc.h b/gdb/config/sparc/tm-sparc.h index 414b69ec9ce..7641ee1c5f4 100644 --- a/gdb/config/sparc/tm-sparc.h +++ b/gdb/config/sparc/tm-sparc.h @@ -545,9 +545,9 @@ extern CORE_ADDR init_frame_pc_noop (int fromleaf, struct frame_info *prev); * * 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 diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index f03cd14e269..ef5e072020d 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -1216,8 +1216,8 @@ cris_init_extra_frame_info (int fromleaf, struct frame_info *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), diff --git a/gdb/eval.c b/gdb/eval.c index d5d08927893..af93ce9cda6 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -32,6 +32,7 @@ #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; diff --git a/gdb/gcore.c b/gdb/gcore.c index 5ad17e83f83..6a0edbf51e1 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -26,6 +26,7 @@ #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); diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 27cfedfd648..affc5d3aa8c 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -36,6 +36,7 @@ #include "infttrace.h" /* For argument passing to the inferior */ #include "symtab.h" +#include "infcall.h" #ifdef USG #include diff --git a/gdb/infcall.c b/gdb/infcall.c new file mode 100644 index 00000000000..fee13974446 --- /dev/null +++ b/gdb/infcall.c @@ -0,0 +1,981 @@ +/* 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); +} diff --git a/gdb/infcall.h b/gdb/infcall.h new file mode 100644 index 00000000000..03774111b8c --- /dev/null +++ b/gdb/infcall.h @@ -0,0 +1,39 @@ +/* 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 diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 01ab3d7b0de..5867655b98e 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -115,8 +115,6 @@ void _initialize_infcmd (void); #define GO_USAGE "Usage: go \n" -static void breakpoint_auto_delete_contents (void *); - #define ERROR_NO_INFERIOR \ if (!target_has_execution) error ("The program is not being run."); @@ -950,112 +948,6 @@ signal_command (char *signum_exp, int from_tty) 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; -} - /* 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. diff --git a/gdb/inferior.h b/gdb/inferior.h index 62034492915..0950973907c 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -164,8 +164,6 @@ extern void terminal_save_ours (void); 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); diff --git a/gdb/mcore-tdep.c b/gdb/mcore-tdep.c index ab03f3ad765..5d18ce83881 100644 --- a/gdb/mcore-tdep.c +++ b/gdb/mcore-tdep.c @@ -1058,8 +1058,8 @@ mcore_init_extra_frame_info (int fromleaf, struct frame_info *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)); } else diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index 22f3b67e7f1..d411b741564 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -892,9 +892,10 @@ mn10300_frame_saved_pc (struct frame_info *fi) 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) diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index bc937ca7ea0..c8524cc25b6 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -42,6 +42,7 @@ #include "gdb_regex.h" #include "regcache.h" #include "block.h" +#include "infcall.h" #include diff --git a/gdb/scm-lang.c b/gdb/scm-lang.c index 99a1fd5ba96..1af501d5829 100644 --- a/gdb/scm-lang.c +++ b/gdb/scm-lang.c @@ -33,6 +33,7 @@ #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 *, diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c index 0390e95f84f..4bd3af18687 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -1763,8 +1763,8 @@ sh_init_extra_frame_info (int fromleaf, struct frame_info *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), @@ -1795,8 +1795,8 @@ sh64_init_extra_frame_info (int fromleaf, struct frame_info *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), diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index e1a0089f3c0..18311f6c161 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -2379,10 +2379,11 @@ sparc_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, 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) { diff --git a/gdb/target.h b/gdb/target.h index b3f43fce577..e757b6701d9 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -836,15 +836,15 @@ extern void target_load (char *arg, int from_tty); #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, diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c index de810565e04..1b14cf6584f 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -1155,9 +1155,10 @@ v850_frame_init_saved_regs (struct frame_info *fi) 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) diff --git a/gdb/valarith.c b/gdb/valarith.c index ed0fe05f35e..854a1517ae6 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -31,6 +31,7 @@ #include "gdb_string.h" #include "doublest.h" #include +#include "infcall.h" /* Define whether or not the C operator '/' truncates towards zero for differently signed operands (truncation direction is undefined in C). */ diff --git a/gdb/valops.c b/gdb/valops.c index a2a2e978bd3..d8261c822f0 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -34,6 +34,7 @@ #include "regcache.h" #include "cp-abi.h" #include "block.h" +#include "infcall.h" #include #include "gdb_string.h" @@ -49,10 +50,6 @@ extern int overload_debug; 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, @@ -84,37 +81,6 @@ static int auto_abandon = 0; 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; - - /* Find the address of function name NAME in the inferior. */ struct value * @@ -1089,774 +1055,6 @@ legacy_push_arguments (int nargs, struct value **args, CORE_ADDR sp, 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. @@ -3485,29 +2683,4 @@ _initialize_valops (void) &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; } diff --git a/gdb/value.h b/gdb/value.h index ad488a788fa..54854e5f563 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -549,9 +549,6 @@ extern struct value *varying_to_slice (struct value *); 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 *); -- cgit v1.2.1