/* Memory-access and commands for "inferior" process, for GDB.
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GDB.
#include "reggroups.h"
#include "block.h"
#include <ctype.h>
+#include "gdb_assert.h"
/* Functions exported for general use, in inferior.h: */
struct frame_id step_frame_id;
-/* Our notion of the current stack pointer. */
-
-CORE_ADDR step_sp;
-
enum step_over_calls_kind step_over_calls;
/* If stepping, nonzero means step count is > 1
\f
/* Compute command-line string given argument vector. This does the
same shell processing as fork_inferior. */
-/* ARGSUSED */
char *
construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv)
{
return 0;
}
-/* ARGSUSED */
void
tty_command (char *file, int from_tty)
{
inferior_io_terminal = savestring (file, strlen (file));
}
-static void
-run_command (char *args, int from_tty)
-{
- char *exec_file;
-
- dont_repeat ();
+/* Kill the inferior if already running. This function is designed
+ to be called when we are about to start the execution of the program
+ from the beginning. Ask the user to confirm that he wants to restart
+ the program being debugged when FROM_TTY is non-null. */
+void
+kill_if_already_running (int from_tty)
+{
if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
{
if (from_tty
#endif
init_wait_for_inferior ();
}
+}
+
+static void
+run_command (char *args, int from_tty)
+{
+ char *exec_file;
+
+ dont_repeat ();
+ kill_if_already_running (from_tty);
clear_breakpoint_hit_counts ();
/* Purge old solib objfiles. */
if (!args)
{
- if (event_loop_p && target_can_async_p ())
+ if (target_can_async_p ())
async_disable_stdin ();
}
else
/* If we get a request for running in the bg but the target
doesn't support it, error out. */
- if (event_loop_p && async_exec && !target_can_async_p ())
+ if (async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
/* If we don't get a request of running in the bg, then we need
to simulate synchronous (fg) execution. */
- if (event_loop_p && !async_exec && target_can_async_p ())
+ if (!async_exec && target_can_async_p ())
{
/* Simulate synchronous execution */
async_disable_stdin ();
/* We call get_inferior_args() because we might need to compute
the value now. */
target_create_inferior (exec_file, get_inferior_args (),
- environ_vector (inferior_environ));
+ environ_vector (inferior_environ), from_tty);
}
}
\f
+/* Start the execution of the program up until the beginning of the main
+ program. */
+
+static void
+start_command (char *args, int from_tty)
+{
+ /* Some languages such as Ada need to search inside the program
+ minimal symbols for the location where to put the temporary
+ breakpoint before starting. */
+ if (!have_minimal_symbols ())
+ error ("No symbol table loaded. Use the \"file\" command.");
+
+ /* If the inferior is already running, we want to ask the user if we
+ should restart it or not before we insert the temporary breakpoint.
+ This makes sure that this command doesn't have any side effect if
+ the user changes its mind. */
+ kill_if_already_running (from_tty);
+
+ /* Insert the temporary breakpoint, and run... */
+ tbreak_command (main_name (), 0);
+ run_command (args, from_tty);
+}
+
void
continue_command (char *proc_count_exp, int from_tty)
{
/* If we must run in the background, but the target can't do it,
error out. */
- if (event_loop_p && async_exec && !target_can_async_p ())
+ if (async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
/* If we are not asked to run in the bg, then prepare to run in the
foreground, synchronously. */
- if (event_loop_p && !async_exec && target_can_async_p ())
+ if (!async_exec && target_can_async_p ())
{
/* Simulate synchronous execution */
async_disable_stdin ();
\f
/* Step until outside of current statement. */
-/* ARGSUSED */
static void
step_command (char *count_string, int from_tty)
{
/* Likewise, but skip over subroutine calls as if single instructions. */
-/* ARGSUSED */
static void
next_command (char *count_string, int from_tty)
{
/* Likewise, but step only one instruction. */
-/* ARGSUSED */
void
stepi_command (char *count_string, int from_tty)
{
step_1 (0, 1, count_string);
}
-/* ARGSUSED */
void
nexti_command (char *count_string, int from_tty)
{
/* If we get a request for running in the bg but the target
doesn't support it, error out. */
- if (event_loop_p && async_exec && !target_can_async_p ())
+ if (async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
/* If we don't get a request of running in the bg, then we need
to simulate synchronous (fg) execution. */
- if (event_loop_p && !async_exec && target_can_async_p ())
+ if (!async_exec && target_can_async_p ())
{
/* Simulate synchronous execution */
async_disable_stdin ();
if (!single_inst || skip_subroutines) /* leave si command alone */
{
enable_longjmp_breakpoint ();
- if (!event_loop_p || !target_can_async_p ())
+ if (!target_can_async_p ())
cleanups = make_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
else
make_exec_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
}
/* In synchronous case, all is well, just use the regular for loop. */
- if (!event_loop_p || !target_can_async_p ())
+ if (!target_can_async_p ())
{
for (; count > 0; count--)
{
if (!frame) /* Avoid coredump here. Why tho? */
error ("No current frame");
step_frame_id = get_frame_id (frame);
- step_sp = read_sp ();
if (!single_inst)
{
if (!stop_step)
break;
-
- /* FIXME: On nexti, this may have already been done (when we hit the
- step resume break, I think). Probably this should be moved to
- wait_for_inferior (near the top). */
-#if defined (SHIFT_INST_REGS)
- SHIFT_INST_REGS ();
-#endif
}
if (!single_inst || skip_subroutines)
and handle them one at the time, through step_once(). */
else
{
- if (event_loop_p && target_can_async_p ())
+ if (target_can_async_p ())
step_once (skip_subroutines, single_inst, count);
}
}
count = arg->next->next->data.integer;
if (stop_step)
- {
- /* FIXME: On nexti, this may have already been done (when we hit the
- step resume break, I think). Probably this should be moved to
- wait_for_inferior (near the top). */
-#if defined (SHIFT_INST_REGS)
- SHIFT_INST_REGS ();
-#endif
- step_once (skip_subroutines, single_inst, count - 1);
- }
+ step_once (skip_subroutines, single_inst, count - 1);
else
if (!single_inst || skip_subroutines)
do_exec_cleanups (ALL_CLEANUPS);
if (!frame) /* Avoid coredump here. Why tho? */
error ("No current frame");
step_frame_id = get_frame_id (frame);
- step_sp = read_sp ();
if (!single_inst)
{
/* If we must run in the background, but the target can't do it,
error out. */
- if (event_loop_p && async_exec && !target_can_async_p ())
+ if (async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
/* If we are not asked to run in the bg, then prepare to run in the
foreground, synchronously. */
- if (event_loop_p && !async_exec && target_can_async_p ())
+ if (!async_exec && target_can_async_p ())
{
/* Simulate synchronous execution */
async_disable_stdin ();
we set. This may involve changes to wait_for_inferior and the
proceed status code. */
-/* ARGSUSED */
static void
until_next_command (int from_tty)
{
step_over_calls = STEP_OVER_ALL;
step_frame_id = get_frame_id (frame);
- step_sp = read_sp ();
step_multi = 0; /* Only one call to proceed */
/* If we must run in the background, but the target can't do it,
error out. */
- if (event_loop_p && async_exec && !target_can_async_p ())
+ if (async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
/* If we are not asked to run in the bg, then prepare to run in the
foreground, synchronously. */
- if (event_loop_p && !async_exec && target_can_async_p ())
+ if (!async_exec && target_can_async_p ())
{
/* Simulate synchronous execution */
async_disable_stdin ();
/* If we must run in the background, but the target can't do it,
error out. */
- if (event_loop_p && async_exec && !target_can_async_p ())
+ if (async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
/* If we are not asked to run in the bg, then prepare to run in the
foreground, synchronously. */
- if (event_loop_p && !async_exec && target_can_async_p ())
+ if (!async_exec && target_can_async_p ())
{
/* Simulate synchronous execution. */
async_disable_stdin ();
until_break_command (arg, from_tty, 1);
}
\f
+/* Print the result of a function at the end of a 'finish' command. */
-/* Print the result of a function at the end of a 'finish' command. */
static void
-print_return_value (int structure_return, struct type *value_type)
+print_return_value (int struct_return, struct type *value_type)
{
+ struct gdbarch *gdbarch = current_gdbarch;
+ struct cleanup *old_chain;
+ struct ui_stream *stb;
struct value *value;
- static struct ui_stream *stb = NULL;
- if (!structure_return)
+ gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID);
+
+ /* FIXME: 2003-09-27: When returning from a nested inferior function
+ call, it's possible (with no help from the architecture vector)
+ to locate and return/print a "struct return" value. This is just
+ a more complicated case of what is already being done in in the
+ inferior function call code. In fact, when inferior function
+ calls are made async, this will likely be made the norm. */
+
+ switch (gdbarch_return_value (gdbarch, value_type, NULL, NULL, NULL))
{
- value = value_being_returned (value_type, stop_registers, structure_return);
+ case RETURN_VALUE_REGISTER_CONVENTION:
+ case RETURN_VALUE_ABI_RETURNS_ADDRESS:
+ value = allocate_value (value_type);
+ CHECK_TYPEDEF (value_type);
+ gdbarch_return_value (current_gdbarch, value_type, stop_registers,
+ VALUE_CONTENTS_RAW (value), NULL);
+ break;
+ case RETURN_VALUE_STRUCT_CONVENTION:
+ value = NULL;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
+ }
+
+ if (value)
+ {
+ /* Print it. */
stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
ui_out_text (uiout, "Value returned is ");
- ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
+ ui_out_field_fmt (uiout, "gdb-result-var", "$%d",
+ record_latest_value (value));
ui_out_text (uiout, " = ");
value_print (value, stb->stream, 0, Val_no_prettyprint);
ui_out_field_stream (uiout, "return-value", stb);
ui_out_text (uiout, "\n");
+ do_cleanups (old_chain);
}
else
{
- /* We cannot determine the contents of the structure because
- it is on the stack, and we don't know where, since we did not
- initiate the call, as opposed to the call_function_by_hand case */
-#ifdef VALUE_RETURNED_FROM_STACK
- value = 0;
ui_out_text (uiout, "Value returned has type: ");
ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type));
ui_out_text (uiout, ".");
ui_out_text (uiout, " Cannot determine contents\n");
-#else
- value = value_being_returned (value_type, stop_registers, structure_return);
- stb = ui_out_stream_new (uiout);
- ui_out_text (uiout, "Value returned is ");
- ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
- ui_out_text (uiout, " = ");
- value_print (value, stb->stream, 0, Val_no_prettyprint);
- ui_out_field_stream (uiout, "return-value", stb);
- ui_out_text (uiout, "\n");
-#endif
}
}
/* Stuff that needs to be done by the finish command after the target
- has stopped. In asynchronous mode, we wait for the target to stop in
- the call to poll or select in the event loop, so it is impossible to
- do all the stuff as part of the finish_command function itself. The
- only chance we have to complete this command is in
- fetch_inferior_event, which is called by the event loop as soon as it
- detects that the target has stopped. This function is called via the
- cmd_continuation pointer. */
-void
+ has stopped. In asynchronous mode, we wait for the target to stop
+ in the call to poll or select in the event loop, so it is
+ impossible to do all the stuff as part of the finish_command
+ function itself. The only chance we have to complete this command
+ is in fetch_inferior_event, which is called by the event loop as
+ soon as it detects that the target has stopped. This function is
+ called via the cmd_continuation pointer. */
+
+static void
finish_command_continuation (struct continuation_arg *arg)
{
struct symbol *function;
struct cleanup *cleanups;
breakpoint = (struct breakpoint *) arg->data.pointer;
- function = (struct symbol *) arg->next->data.pointer;
- cleanups = (struct cleanup *) arg->next->next->data.pointer;
+ function = (struct symbol *) arg->next->data.pointer;
+ cleanups = (struct cleanup *) arg->next->next->data.pointer;
if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
- && function != 0)
+ && function != NULL)
{
struct type *value_type;
- CORE_ADDR funcaddr;
int struct_return;
+ int gcc_compiled;
value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
if (!value_type)
return;
}
- funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));
-
- struct_return = using_struct_return (check_typedef (value_type),
- BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)));
+ CHECK_TYPEDEF (value_type);
+ gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function));
+ struct_return = using_struct_return (value_type, gcc_compiled);
print_return_value (struct_return, value_type);
}
+
do_exec_cleanups (cleanups);
}
-/* "finish": Set a temporary breakpoint at the place
- the selected frame will return to, then continue. */
+/* "finish": Set a temporary breakpoint at the place the selected
+ frame will return to, then continue. */
static void
finish_command (char *arg, int from_tty)
int async_exec = 0;
- /* Find out whether we must run in the background. */
+ /* Find out whether we must run in the background. */
if (arg != NULL)
async_exec = strip_bg_char (&arg);
/* If we must run in the background, but the target can't do it,
- error out. */
- if (event_loop_p && async_exec && !target_can_async_p ())
+ error out. */
+ if (async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
/* If we are not asked to run in the bg, then prepare to run in the
- foreground, synchronously. */
- if (event_loop_p && !async_exec && target_can_async_p ())
+ foreground, synchronously. */
+ if (!async_exec && target_can_async_p ())
{
- /* Simulate synchronous execution */
+ /* Simulate synchronous execution. */
async_disable_stdin ();
}
breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish);
- if (!event_loop_p || !target_can_async_p ())
+ if (!target_can_async_p ())
old_chain = make_cleanup_delete_breakpoint (breakpoint);
else
old_chain = make_exec_cleanup_delete_breakpoint (breakpoint);
function = find_pc_function (get_frame_pc (deprecated_selected_frame));
- /* Print info on the selected frame, including level number
- but not source. */
+ /* Print info on the selected frame, including level number but not
+ source. */
if (from_tty)
{
printf_filtered ("Run till exit from ");
- print_stack_frame (deprecated_selected_frame,
- frame_relative_level (deprecated_selected_frame), 0);
+ print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
}
/* If running asynchronously and the target support asynchronous
execution, set things up for the rest of the finish command to be
completed later on, when gdb has detected that the target has
- stopped, in fetch_inferior_event. */
- if (event_loop_p && target_can_async_p ())
+ stopped, in fetch_inferior_event. */
+ if (target_can_async_p ())
{
arg1 =
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
add_continuation (finish_command_continuation, arg1);
}
- proceed_to_finish = 1; /* We want stop_registers, please... */
+ proceed_to_finish = 1; /* We want stop_registers, please... */
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
/* Do this only if not running asynchronously or if the target
- cannot do async execution. Otherwise, complete this command when
- the target actually stops, in fetch_inferior_event. */
- if (!event_loop_p || !target_can_async_p ())
+ cannot do async execution. Otherwise, complete this command when
+ the target actually stops, in fetch_inferior_event. */
+ if (!target_can_async_p ())
{
-
- /* Did we stop at our breakpoint? */
+ /* Did we stop at our breakpoint? */
if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
- && function != 0)
+ && function != NULL)
{
struct type *value_type;
- CORE_ADDR funcaddr;
int struct_return;
+ int gcc_compiled;
value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
if (!value_type)
internal_error (__FILE__, __LINE__,
"finish_command: function has no target type");
- /* FIXME: Shouldn't we do the cleanups before returning? */
+ /* FIXME: Shouldn't we do the cleanups before returning? */
if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
return;
- funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));
-
- struct_return =
- using_struct_return (check_typedef (value_type),
- BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)));
+ CHECK_TYPEDEF (value_type);
+ gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function));
+ struct_return = using_struct_return (value_type, gcc_compiled);
print_return_value (struct_return, value_type);
}
+
do_cleanups (old_chain);
}
}
\f
-/* ARGSUSED */
+
static void
program_info (char *args, int from_tty)
{
target_files_info ();
printf_filtered ("Program stopped at %s.\n",
- local_hex_string ((unsigned long) stop_pc));
+ hex_string ((unsigned long) stop_pc));
if (stop_step)
printf_filtered ("It stopped after being stepped.\n");
else if (num != 0)
static const char path_var_name[] = "PATH";
-/* ARGSUSED */
static void
path_info (char *args, int from_tty)
{
{
int i;
const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
- char raw_buffer[MAX_REGISTER_SIZE];
- char virtual_buffer[MAX_REGISTER_SIZE];
-
- if (DEPRECATED_DO_REGISTERS_INFO_P ())
- {
- DEPRECATED_DO_REGISTERS_INFO (regnum, print_all);
- return;
- }
+ char buffer[MAX_REGISTER_SIZE];
for (i = 0; i < numregs; i++)
{
print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), file);
/* Get the data in raw format. */
- if (! frame_register_read (frame, i, raw_buffer))
+ if (! frame_register_read (frame, i, buffer))
{
fprintf_filtered (file, "*value not available*\n");
continue;
}
- /* FIXME: cagney/2002-08-03: This code shouldn't be necessary.
- The function frame_register_read() should have returned the
- pre-cooked register so no conversion is necessary. */
- /* Convert raw data to virtual format if necessary. */
- if (DEPRECATED_REGISTER_CONVERTIBLE (i))
- {
- DEPRECATED_REGISTER_CONVERT_TO_VIRTUAL (i, register_type (current_gdbarch, i),
- raw_buffer, virtual_buffer);
- }
- else
- {
- memcpy (virtual_buffer, raw_buffer,
- REGISTER_VIRTUAL_SIZE (i));
- }
-
/* If virtual format is floating, print it that way, and in raw
hex. */
if (TYPE_CODE (register_type (current_gdbarch, i)) == TYPE_CODE_FLT)
{
int j;
- val_print (register_type (current_gdbarch, i), virtual_buffer, 0, 0,
+ val_print (register_type (current_gdbarch, i), buffer, 0, 0,
file, 0, 1, 0, Val_pretty_default);
fprintf_filtered (file, "\t(raw 0x");
- for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+ for (j = 0; j < register_size (current_gdbarch, i); j++)
{
int idx;
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
idx = j;
else
- idx = REGISTER_RAW_SIZE (i) - 1 - j;
- fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[idx]);
+ idx = register_size (current_gdbarch, i) - 1 - j;
+ fprintf_filtered (file, "%02x", (unsigned char) buffer[idx]);
}
fprintf_filtered (file, ")");
}
else
{
/* Print the register in hex. */
- val_print (register_type (current_gdbarch, i), virtual_buffer, 0, 0,
+ val_print (register_type (current_gdbarch, i), buffer, 0, 0,
file, 'x', 1, 0, Val_pretty_default);
/* If not a vector register, print it also according to its
natural format. */
if (TYPE_VECTOR (register_type (current_gdbarch, i)) == 0)
{
fprintf_filtered (file, "\t");
- val_print (register_type (current_gdbarch, i), virtual_buffer, 0, 0,
+ val_print (register_type (current_gdbarch, i), buffer, 0, 0,
file, 0, 1, 0, Val_pretty_default);
}
}
based on what modes we are starting it with. */
target_terminal_init ();
- /* Install inferior's terminal modes. */
- target_terminal_inferior ();
-
/* Set up execution context to know that we should return from
wait_for_inferior as soon as the target reports a stop. */
init_wait_for_inferior ();
symbol_file_add_main (full_exec_path, from_tty);
}
}
+ else
+ {
+ reopen_exec_file ();
+ reread_symbols ();
+ }
#ifdef SOLIB_ADD
/* Add shared library symbols from the newly attached process, if any. */
*/
target_post_attach (PIDGET (inferior_ptid));
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
normal_stop ();
- if (attach_hook)
- attach_hook ();
+ if (deprecated_attach_hook)
+ deprecated_attach_hook ();
}
/*
#if defined(SOLIB_RESTART)
SOLIB_RESTART ();
#endif
- if (detach_hook)
- detach_hook ();
+ if (deprecated_detach_hook)
+ deprecated_detach_hook ();
}
/* Disconnect from the current target without resuming it (leaving it
#if defined(SOLIB_RESTART)
SOLIB_RESTART ();
#endif
- if (detach_hook)
- detach_hook ();
+ if (deprecated_detach_hook)
+ deprecated_detach_hook ();
}
/* Stop the execution of the target while running in async mode, in
void
interrupt_target_command (char *args, int from_tty)
{
- if (event_loop_p && target_can_async_p ())
+ if (target_can_async_p ())
{
dont_repeat (); /* Not for the faint of heart */
target_stop ();
}
}
-/* ARGSUSED */
static void
print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
struct frame_info *frame, const char *args)
print_float_info (current_gdbarch, gdb_stdout, deprecated_selected_frame, args);
}
\f
-/* ARGSUSED */
static void
unset_command (char *args, int from_tty)
{
&setlist);
set_cmd_completer (c, filename_completer);
set_cmd_sfunc (c, notice_args_set);
- c = add_show_from_set (c, &showlist);
+ c = deprecated_add_show_from_set (c, &showlist);
set_cmd_sfunc (c, notice_args_read);
c = add_cmd
add_com ("R", class_run, run_no_args_command,
"Start debugged program with no arguments.");
+ c = add_com ("start", class_run, start_command,
+ "\
+Run the debugged program until the beginning of the main procedure.\n\
+You may specify arguments to give to your program, just as with the\n\
+\"run\" command.");
+ set_cmd_completer (c, filename_completer);
+
add_com ("interrupt", class_run, interrupt_target_command,
"Interrupt the execution of the debugged program.");