2003-04-21 Andrew Cagney <cagney@redhat.com>
* infcall.c: New file. * infcall.h: New file. * valarith.c: Include "infcall.h". * scm-lang.c, objc-lang.cm, hppa-tdep.c, gcore.c: Ditto. * eval.c, ada-valprint.c, ada-lang.c: Ditto. * Makefile.in (valarith.o, scm-lang.o): Update dependencies. (objc-lang.o, hppa-tdep.o, gcore.o): Update dependencies. (eval.o, ada-valprint.o, ada-lang.o): Update dependencies. (SFILES): Add "infcall.c" (COMMON_OBS): Add "infcall.o". (infcall.o): Specify dependencies. * value.h (call_function_by_hand): Delete declaration. * inferior.h (run_stack_dummy): Delete declaration. * infcmd.c (breakpoint_auto_delete_contents): Move to "infcall.c". (run_stack_dummy): Move to "infcall.c", merged into call_function_by_hand. * valops.c (call_function_by_hand): Moved to "infcall.c". (find_function_addr, value_arg_coerce): Ditto. (unwindonsignal_p, coerce_float_to_double): Ditto. (_initialize_valops): Move "set/show coerce-float-to-double", and "set/show unwindonsignal" commands to "infcall.c". * v850-tdep.c, target.h: Update comments. * sparc-tdep.c (sparc_fix_call_dummy): Update comments. * sh-tdep.c (sh_init_extra_frame_info): Update comments. (sh64_init_extra_frame_info): Update comments. * mn10300-tdep.c: Update comments. * mcore-tdep.c (mcore_init_extra_frame_info): Update comments. * config/sparc/tm-sparc.h: Update comments. * breakpoint.h: Update comments. * avr-tdep.c (avr_init_extra_frame_info): Update comments. * arm-tdep.c: Update comment.
This commit is contained in:
parent
6c6532f753
commit
04714b914f
27 changed files with 1119 additions and 985 deletions
|
@ -1,3 +1,37 @@
|
||||||
|
2003-04-21 Andrew Cagney <cagney@redhat.com>
|
||||||
|
|
||||||
|
* infcall.c: New file.
|
||||||
|
* infcall.h: New file.
|
||||||
|
* valarith.c: Include "infcall.h".
|
||||||
|
* scm-lang.c, objc-lang.cm, hppa-tdep.c, gcore.c: Ditto.
|
||||||
|
* eval.c, ada-valprint.c, ada-lang.c: Ditto.
|
||||||
|
* Makefile.in (valarith.o, scm-lang.o): Update dependencies.
|
||||||
|
(objc-lang.o, hppa-tdep.o, gcore.o): Update dependencies.
|
||||||
|
(eval.o, ada-valprint.o, ada-lang.o): Update dependencies.
|
||||||
|
(SFILES): Add "infcall.c"
|
||||||
|
(COMMON_OBS): Add "infcall.o".
|
||||||
|
(infcall.o): Specify dependencies.
|
||||||
|
* value.h (call_function_by_hand): Delete declaration.
|
||||||
|
* inferior.h (run_stack_dummy): Delete declaration.
|
||||||
|
* infcmd.c (breakpoint_auto_delete_contents): Move to "infcall.c".
|
||||||
|
(run_stack_dummy): Move to "infcall.c", merged into
|
||||||
|
call_function_by_hand.
|
||||||
|
* valops.c (call_function_by_hand): Moved to "infcall.c".
|
||||||
|
(find_function_addr, value_arg_coerce): Ditto.
|
||||||
|
(unwindonsignal_p, coerce_float_to_double): Ditto.
|
||||||
|
(_initialize_valops): Move "set/show coerce-float-to-double", and
|
||||||
|
"set/show unwindonsignal" commands to "infcall.c".
|
||||||
|
* v850-tdep.c, target.h: Update comments.
|
||||||
|
* sparc-tdep.c (sparc_fix_call_dummy): Update comments.
|
||||||
|
* sh-tdep.c (sh_init_extra_frame_info): Update comments.
|
||||||
|
(sh64_init_extra_frame_info): Update comments.
|
||||||
|
* mn10300-tdep.c: Update comments.
|
||||||
|
* mcore-tdep.c (mcore_init_extra_frame_info): Update comments.
|
||||||
|
* config/sparc/tm-sparc.h: Update comments.
|
||||||
|
* breakpoint.h: Update comments.
|
||||||
|
* avr-tdep.c (avr_init_extra_frame_info): Update comments.
|
||||||
|
* arm-tdep.c: Update comment.
|
||||||
|
|
||||||
2003-04-19 Mark Kettenis <kettenis@gnu.org>
|
2003-04-19 Mark Kettenis <kettenis@gnu.org>
|
||||||
|
|
||||||
* i386-tdep.c (i386_num_register_names): New variable.
|
* i386-tdep.c (i386_num_register_names): New variable.
|
||||||
|
|
|
@ -521,7 +521,9 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
|
||||||
frame-unwind.c \
|
frame-unwind.c \
|
||||||
gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
|
gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
|
||||||
hpacc-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 \
|
interps.c \
|
||||||
jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
|
jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
|
||||||
kod.c kod-cisco.c \
|
kod.c kod-cisco.c \
|
||||||
|
@ -669,6 +671,7 @@ i386_linux_tdep_h = i386-linux-tdep.h
|
||||||
i386_tdep_h = i386-tdep.h
|
i386_tdep_h = i386-tdep.h
|
||||||
i387_tdep_h = i387-tdep.h
|
i387_tdep_h = i387-tdep.h
|
||||||
inf_loop_h = inf-loop.h
|
inf_loop_h = inf-loop.h
|
||||||
|
infcall_h = infcall.h
|
||||||
inferior_h = inferior.h $(breakpoint_h) $(target_h) $(frame_h)
|
inferior_h = inferior.h $(breakpoint_h) $(target_h) $(frame_h)
|
||||||
inflow_h = inflow.h $(terminal_h)
|
inflow_h = inflow.h $(terminal_h)
|
||||||
interps_h = interps.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 \
|
COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
|
||||||
charset.o disasm.o dummy-frame.o \
|
charset.o disasm.o dummy-frame.o \
|
||||||
source.o values.o eval.o valops.o valarith.o valprint.o printcmd.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 \
|
expprint.o environ.o stack.o thread.o \
|
||||||
interps.o \
|
interps.o \
|
||||||
macrotab.o macrocmd.o macroexp.o macroscope.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) \
|
ada-lang.o: ada-lang.c $(gdb_string_h) $(demangle_h) $(defs_h) $(symtab_h) \
|
||||||
$(gdbtypes_h) $(gdbcmd_h) $(expression_h) $(parser_defs_h) \
|
$(gdbtypes_h) $(gdbcmd_h) $(expression_h) $(parser_defs_h) \
|
||||||
$(language_h) $(c_lang_h) $(inferior_h) $(symfile_h) $(objfiles_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) \
|
ada-tasks.o: ada-tasks.c $(defs_h) $(command_h) $(value_h) $(language_h) \
|
||||||
$(inferior_h) $(symtab_h) $(target_h) $(gdbcore_h) $(gregset_h) \
|
$(inferior_h) $(symtab_h) $(target_h) $(gdbcore_h) $(gregset_h) \
|
||||||
$(ada_lang_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)
|
$(c_lang_h) $(typeprint_h) $(ada_lang_h) $(gdb_string_h)
|
||||||
ada-valprint.o: ada-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
|
ada-valprint.o: ada-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(expression_h) $(value_h) $(demangle_h) $(valprint_h) $(language_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) \
|
aix-thread.o: aix-thread.c $(defs_h) $(gdb_assert_h) $(gdbthread_h) \
|
||||||
$(target_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) $(language_h) \
|
$(target_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) $(language_h) \
|
||||||
$(ppc_tdep_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)
|
environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
|
||||||
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_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) \
|
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
|
||||||
$(gdb_string_h)
|
$(gdb_string_h)
|
||||||
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_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) \
|
frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \
|
||||||
$(arch_utils_h) $(regcache_h)
|
$(arch_utils_h) $(regcache_h)
|
||||||
gcore.o: gcore.c $(defs_h) $(cli_decode_h) $(inferior_h) $(gdbcore_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.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)
|
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) \
|
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)
|
$(gdbtypes_h) $(gdbcore_h) $(cp_abi_h)
|
||||||
hppa-tdep.o: hppa-tdep.c $(defs_h) $(frame_h) $(bfd_h) $(inferior_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) \
|
$(value_h) $(regcache_h) $(completer_h) $(language_h) $(osabi_h) \
|
||||||
$(gdb_assert_h) $(infttrace_h) $(symtab_h) $(a_out_encap_h) \
|
$(gdb_assert_h) $(infttrace_h) $(symtab_h) $(infcall_h) \
|
||||||
$(gdb_stat_h) $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) \
|
$(a_out_encap_h) $(gdb_stat_h) $(gdb_wait_h) $(gdbcore_h) \
|
||||||
$(symfile_h) $(objfiles_h)
|
$(gdbcmd_h) $(target_h) $(symfile_h) $(objfiles_h)
|
||||||
hppa-hpux-tdep.o: hppa-hpux-tdep.c $(defs_h) $(arch_utils_h) $(gdbcore_h) \
|
hppa-hpux-tdep.o: hppa-hpux-tdep.c $(defs_h) $(arch_utils_h) $(gdbcore_h) \
|
||||||
$(osabi_h) $(gdb_string_h)
|
$(osabi_h) $(gdb_string_h)
|
||||||
hppab-nat.o: hppab-nat.c $(defs_h) $(inferior_h) $(target_h) $(regcache_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)
|
$(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) \
|
inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \
|
||||||
$(event_top_h) $(inf_loop_h) $(remote_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) \
|
infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(frame_h) $(inferior_h) $(environ_h) $(value_h) $(gdbcmd_h) \
|
$(frame_h) $(inferior_h) $(environ_h) $(value_h) $(gdbcmd_h) \
|
||||||
$(symfile_h) $(gdbcore_h) $(target_h) $(language_h) $(symfile_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)
|
$(osabi_h)
|
||||||
objc-lang.o: objc-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_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) \
|
$(parser_defs_h) $(language_h) $(c_lang_h) $(objc_lang_h) \
|
||||||
$(complaints_h) $(value_h) $(symfile_h) $(objfiles_h) \
|
$(complaints_h) $(value_h) $(symfile_h) $(objfiles_h) $(gdb_string_h) \
|
||||||
$(gdb_string_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(frame_h) \
|
$(target_h) $(gdbcore_h) $(gdbcmd_h) $(frame_h) $(gdb_regex_h) \
|
||||||
$(gdb_regex_h) $(regcache_h) $(block_h)
|
$(regcache_h) $(block_h) $(infcall_h)
|
||||||
objfiles.o: objfiles.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_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) \
|
$(objfiles_h) $(gdb_stabs_h) $(target_h) $(bcache_h) $(gdb_stat_h) \
|
||||||
$(gdb_obstack_h) $(gdb_string_h) $(breakpoint_h) $(mmalloc_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_tags_h)
|
||||||
scm-lang.o: scm-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_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) \
|
$(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) \
|
scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(expression_h) $(parser_defs_h) $(language_h) $(value_h) \
|
$(expression_h) $(parser_defs_h) $(language_h) $(value_h) \
|
||||||
$(scm_lang_h) $(valprint_h) $(gdbcore_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)
|
$(gdbcore_h) $(value_h) $(command_h) $(regcache_h)
|
||||||
valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
|
valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(expression_h) $(target_h) $(language_h) $(gdb_string_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) \
|
valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \
|
||||||
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
|
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
|
||||||
$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(gdb_string_h) \
|
$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(gdb_string_h) \
|
||||||
|
|
|
@ -39,6 +39,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
#include "ada-lang.h"
|
#include "ada-lang.h"
|
||||||
#include "ui-out.h"
|
#include "ui-out.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
struct cleanup *unresolved_names;
|
struct cleanup *unresolved_names;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
#include "annotate.h"
|
#include "annotate.h"
|
||||||
#include "ada-lang.h"
|
#include "ada-lang.h"
|
||||||
#include "c-lang.h"
|
#include "c-lang.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
/* Encapsulates arguments to ada_val_print. */
|
/* Encapsulates arguments to ada_val_print. */
|
||||||
struct ada_val_print_args
|
struct ada_val_print_args
|
||||||
|
|
|
@ -1257,8 +1257,8 @@ static LONGEST arm_call_dummy_words[] =
|
||||||
|
|
||||||
FIXME rearnsha 2002-02018: Tweeking current_gdbarch is not an
|
FIXME rearnsha 2002-02018: Tweeking current_gdbarch is not an
|
||||||
optimal solution, but the call to arm_fix_call_dummy is immediately
|
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
|
followed by a call to call_function_by_hand, which is the only
|
||||||
where call_dummy_breakpoint_offset is actually used. */
|
function where call_dummy_breakpoint_offset is actually used. */
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -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),
|
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
|
||||||
get_frame_base (fi)))
|
get_frame_base (fi)))
|
||||||
{
|
{
|
||||||
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
|
/* We need to setup fi->frame here because call_function_by_hand
|
||||||
by assuming it's always FP. */
|
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),
|
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi),
|
||||||
AVR_PC_REGNUM));
|
AVR_PC_REGNUM));
|
||||||
}
|
}
|
||||||
|
|
|
@ -623,7 +623,7 @@ extern void set_longjmp_resume_breakpoint (CORE_ADDR, struct frame_id);
|
||||||
enabled watchpoints. When disabled, the watchpoints are marked
|
enabled watchpoints. When disabled, the watchpoints are marked
|
||||||
call_disabled. When reenabled, they are marked enabled.
|
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
|
The inferior must be stopped, and all breakpoints removed, when
|
||||||
these functions are used.
|
these functions are used.
|
||||||
|
|
|
@ -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
|
* call_function then writes CALL_DUMMY, pushes the args onto the
|
||||||
* stack, and adjusts the stack pointer.
|
* stack, and adjusts the stack pointer.
|
||||||
*
|
|
||||||
* run_stack_dummy then starts execution (in the middle of
|
call_function_by_hand then starts execution (in the middle of
|
||||||
* CALL_DUMMY, as directed by call_function). */
|
CALL_DUMMY, as directed by call_function). */
|
||||||
|
|
||||||
#ifndef CALL_DUMMY
|
#ifndef CALL_DUMMY
|
||||||
/* This sequence of words is the instructions
|
/* This sequence of words is the instructions
|
||||||
|
|
|
@ -1216,8 +1216,8 @@ cris_init_extra_frame_info (int fromleaf, struct frame_info *fi)
|
||||||
get_frame_base (fi),
|
get_frame_base (fi),
|
||||||
get_frame_base (fi)))
|
get_frame_base (fi)))
|
||||||
{
|
{
|
||||||
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
|
/* We need to setup fi->frame here because call_function_by_hand
|
||||||
by assuming it's always FP. */
|
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));
|
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 =
|
get_frame_extra_info (fi)->return_pc =
|
||||||
deprecated_read_register_dummy (get_frame_pc (fi),
|
deprecated_read_register_dummy (get_frame_pc (fi),
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "language.h" /* For CAST_IS_CONVERSION */
|
#include "language.h" /* For CAST_IS_CONVERSION */
|
||||||
#include "f-lang.h" /* for array bound stuff */
|
#include "f-lang.h" /* for array bound stuff */
|
||||||
#include "cp-abi.h"
|
#include "cp-abi.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
/* Defined in symtab.c */
|
/* Defined in symtab.c */
|
||||||
extern int hp_som_som_object_present;
|
extern int hp_som_som_object_present;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "elf-bfd.h"
|
#include "elf-bfd.h"
|
||||||
#include "symfile.h"
|
#include "symfile.h"
|
||||||
#include "objfiles.h"
|
#include "objfiles.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
static char *default_gcore_target (void);
|
static char *default_gcore_target (void);
|
||||||
static enum bfd_architecture default_gcore_arch (void);
|
static enum bfd_architecture default_gcore_arch (void);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "infttrace.h"
|
#include "infttrace.h"
|
||||||
/* For argument passing to the inferior */
|
/* For argument passing to the inferior */
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
#ifdef USG
|
#ifdef USG
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
981
gdb/infcall.c
Normal file
981
gdb/infcall.c
Normal file
|
@ -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);
|
||||||
|
}
|
39
gdb/infcall.h
Normal file
39
gdb/infcall.h
Normal file
|
@ -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
|
108
gdb/infcmd.c
108
gdb/infcmd.c
|
@ -115,8 +115,6 @@ void _initialize_infcmd (void);
|
||||||
|
|
||||||
#define GO_USAGE "Usage: go <location>\n"
|
#define GO_USAGE "Usage: go <location>\n"
|
||||||
|
|
||||||
static void breakpoint_auto_delete_contents (void *);
|
|
||||||
|
|
||||||
#define ERROR_NO_INFERIOR \
|
#define ERROR_NO_INFERIOR \
|
||||||
if (!target_has_execution) error ("The program is not being run.");
|
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);
|
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
|
/* 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.
|
our current one or exit the function. We skip calls in both cases.
|
||||||
|
|
||||||
|
|
|
@ -164,8 +164,6 @@ extern void terminal_save_ours (void);
|
||||||
|
|
||||||
extern void terminal_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 (void);
|
||||||
|
|
||||||
extern CORE_ADDR read_pc_pid (ptid_t);
|
extern CORE_ADDR read_pc_pid (ptid_t);
|
||||||
|
|
|
@ -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),
|
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
|
||||||
get_frame_base (fi)))
|
get_frame_base (fi)))
|
||||||
{
|
{
|
||||||
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
|
/* We need to setup fi->frame here because call_function_by_hand
|
||||||
by assuming it's always FP. */
|
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));
|
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi), SP_REGNUM));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -892,9 +892,10 @@ mn10300_frame_saved_pc (struct frame_info *fi)
|
||||||
always be correct. mn10300_analyze_prologue will fix fi->frame if
|
always be correct. mn10300_analyze_prologue will fix fi->frame if
|
||||||
it's not valid.
|
it's not valid.
|
||||||
|
|
||||||
We can be called with the PC in the call dummy under two circumstances.
|
We can be called with the PC in the call dummy under two
|
||||||
First, during normal backtracing, second, while figuring out the frame
|
circumstances. First, during normal backtracing, second, while
|
||||||
pointer just prior to calling the target function (see run_stack_dummy). */
|
figuring out the frame pointer just prior to calling the target
|
||||||
|
function (see call_function_by_hand). */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mn10300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
|
mn10300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "gdb_regex.h"
|
#include "gdb_regex.h"
|
||||||
#include "regcache.h"
|
#include "regcache.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "source.h"
|
#include "source.h"
|
||||||
#include "gdb_string.h"
|
#include "gdb_string.h"
|
||||||
#include "gdbcore.h"
|
#include "gdbcore.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
extern void _initialize_scheme_language (void);
|
extern void _initialize_scheme_language (void);
|
||||||
static struct value *evaluate_subexp_scm (struct type *, struct expression *,
|
static struct value *evaluate_subexp_scm (struct type *, struct expression *,
|
||||||
|
|
|
@ -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),
|
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
|
||||||
get_frame_base (fi)))
|
get_frame_base (fi)))
|
||||||
{
|
{
|
||||||
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
|
/* We need to setup fi->frame here because call_function_by_hand
|
||||||
by assuming it's always FP. */
|
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),
|
deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi),
|
||||||
SP_REGNUM));
|
SP_REGNUM));
|
||||||
get_frame_extra_info (fi)->return_pc = deprecated_read_register_dummy (get_frame_pc (fi),
|
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),
|
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
|
||||||
get_frame_base (fi)))
|
get_frame_base (fi)))
|
||||||
{
|
{
|
||||||
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
|
/* We need to setup fi->frame here because call_function_by_hand
|
||||||
by assuming it's always FP. */
|
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));
|
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 =
|
get_frame_extra_info (fi)->return_pc =
|
||||||
deprecated_read_register_dummy (get_frame_pc (fi),
|
deprecated_read_register_dummy (get_frame_pc (fi),
|
||||||
|
|
|
@ -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
|
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
|
to the proper address in the call dummy, so that `finish' after a stop
|
||||||
in a call dummy works.
|
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,
|
Tweeking current_gdbarch is not an optimal solution, but the call
|
||||||
which is the only function where dummy_breakpoint_offset is actually
|
to sparc_fix_call_dummy is immediately followed by a call to
|
||||||
used, if it is non-zero. */
|
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
|
if (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
|
||||||
|| TYPE_CODE (value_type) == TYPE_CODE_UNION)
|
|| TYPE_CODE (value_type) == TYPE_CODE_UNION)
|
||||||
{
|
{
|
||||||
|
|
|
@ -836,15 +836,15 @@ extern void target_load (char *arg, int from_tty);
|
||||||
#define target_async(CALLBACK,CONTEXT) \
|
#define target_async(CALLBACK,CONTEXT) \
|
||||||
(current_target.to_async((CALLBACK), (CONTEXT)))
|
(current_target.to_async((CALLBACK), (CONTEXT)))
|
||||||
|
|
||||||
/* This is to be used ONLY within run_stack_dummy(). It
|
/* This is to be used ONLY within call_function_by_hand(). It provides
|
||||||
provides a workaround, to have inferior function calls done in
|
a workaround, to have inferior function calls done in sychronous
|
||||||
sychronous mode, even though the target is asynchronous. After
|
mode, even though the target is asynchronous. After
|
||||||
target_async_mask(0) is called, calls to target_can_async_p() will
|
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
|
return FALSE , so that target_resume() will not try to start the
|
||||||
target asynchronously. After the inferior stops, we IMMEDIATELY
|
target asynchronously. After the inferior stops, we IMMEDIATELY
|
||||||
restore the previous nature of the target, by calling
|
restore the previous nature of the target, by calling
|
||||||
target_async_mask(1). After that, target_can_async_p() will return
|
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
|
FIXME ezannoni 1999-12-13: we won't need this once we move
|
||||||
the turning async on and off to the single execution commands,
|
the turning async on and off to the single execution commands,
|
||||||
|
|
|
@ -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
|
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 ()).
|
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.
|
We can be called with the PC in the call dummy under two
|
||||||
First, during normal backtracing, second, while figuring out the frame
|
circumstances. First, during normal backtracing, second, while
|
||||||
pointer just prior to calling the target function (see run_stack_dummy). */
|
figuring out the frame pointer just prior to calling the target
|
||||||
|
function (see call_function_by_hand). */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
v850_init_extra_frame_info (int fromleaf, struct frame_info *fi)
|
v850_init_extra_frame_info (int fromleaf, struct frame_info *fi)
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "gdb_string.h"
|
#include "gdb_string.h"
|
||||||
#include "doublest.h"
|
#include "doublest.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
/* Define whether or not the C operator '/' truncates towards zero for
|
/* Define whether or not the C operator '/' truncates towards zero for
|
||||||
differently signed operands (truncation direction is undefined in C). */
|
differently signed operands (truncation direction is undefined in C). */
|
||||||
|
|
829
gdb/valops.c
829
gdb/valops.c
|
@ -34,6 +34,7 @@
|
||||||
#include "regcache.h"
|
#include "regcache.h"
|
||||||
#include "cp-abi.h"
|
#include "cp-abi.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
#include "infcall.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "gdb_string.h"
|
#include "gdb_string.h"
|
||||||
|
@ -49,10 +50,6 @@ extern int overload_debug;
|
||||||
static int typecmp (int staticp, int varargs, int nargs,
|
static int typecmp (int staticp, int varargs, int nargs,
|
||||||
struct field t1[], struct value *t2[]);
|
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 CORE_ADDR value_push (CORE_ADDR, struct value *);
|
||||||
|
|
||||||
static struct value *search_struct_field (char *, struct value *, int,
|
static struct value *search_struct_field (char *, struct value *, int,
|
||||||
|
@ -84,37 +81,6 @@ static int auto_abandon = 0;
|
||||||
|
|
||||||
int overload_resolution = 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. */
|
/* Find the address of function name NAME in the inferior. */
|
||||||
|
|
||||||
struct value *
|
struct value *
|
||||||
|
@ -1089,774 +1055,6 @@ legacy_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
|
||||||
return 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
|
/* 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.
|
the data into that space, and then setting up an array value.
|
||||||
|
|
||||||
|
@ -3485,29 +2683,4 @@ _initialize_valops (void)
|
||||||
&setlist),
|
&setlist),
|
||||||
&showlist);
|
&showlist);
|
||||||
overload_resolution = 1;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,9 +549,6 @@ extern struct value *varying_to_slice (struct value *);
|
||||||
|
|
||||||
extern struct value *value_slice (struct value *, int, int);
|
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 *,
|
extern struct value *value_literal_complex (struct value *, struct value *,
|
||||||
struct type *);
|
struct type *);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue