#include "cli/cli-utils.h"
#include "infcall.h"
#include "thread-fsm.h"
+#include "top.h"
+#include "interps.h"
/* Local functions: */
set_inferior_io_terminal (const char *terminal_name)
{
xfree (current_inferior ()->terminal);
- current_inferior ()->terminal = terminal_name ? xstrdup (terminal_name) : 0;
+
+ if (terminal_name != NULL && *terminal_name != '\0')
+ current_inferior ()->terminal = xstrdup (terminal_name);
+ else
+ current_inferior ()->terminal = NULL;
}
const char *
{
/* Be sure we own the terminal in case write operations are performed. */
- target_terminal_ours ();
+ target_terminal_ours_for_output ();
/* If the target hasn't taken care of this already, do it now.
Targets which need to access registers during to_open,
simulate synchronous (fg) execution. Note no cleanup is
necessary for this. stdin is re-enabled whenever an error
reaches the top level. */
- async_disable_stdin ();
+ all_uis_on_sync_execution_starting ();
}
}
iterate_over_threads (proceed_thread_callback, NULL);
- if (sync_execution)
+ if (current_ui->prompt_state == PROMPT_BLOCKED)
{
/* If all threads in the target were already running,
proceed_thread_callback ends up never calling proceed,
args = strip_bg_char (args, &async_exec);
args_chain = make_cleanup (xfree, args);
- prepare_execution_command (¤t_target, async_exec);
-
if (args != NULL)
{
if (startswith (args, "-a"))
/* Done with ARGS. */
do_cleanups (args_chain);
+ ERROR_NO_INFERIOR;
+ ensure_not_tfind_mode ();
+
+ if (!non_stop || !all_threads)
+ {
+ ensure_valid_thread ();
+ ensure_not_running ();
+ }
+
+ prepare_execution_command (¤t_target, async_exec);
+
if (from_tty)
printf_filtered (_("Continuing.\n"));
/* If true, this is a stepi/nexti, otherwise a step/step. */
int single_inst;
-
- /* The thread that the command was run on. */
- int thread;
};
-static void step_command_fsm_clean_up (struct thread_fsm *self);
-static int step_command_fsm_should_stop (struct thread_fsm *self);
+static void step_command_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread);
+static int step_command_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *thread);
static enum async_reply_reason
step_command_fsm_async_reply_reason (struct thread_fsm *self);
/* Allocate a new step_command_fsm. */
static struct step_command_fsm *
-new_step_command_fsm (void)
+new_step_command_fsm (struct interp *cmd_interp)
{
struct step_command_fsm *sm;
sm = XCNEW (struct step_command_fsm);
- thread_fsm_ctor (&sm->thread_fsm, &step_command_fsm_ops);
+ thread_fsm_ctor (&sm->thread_fsm, &step_command_fsm_ops, cmd_interp);
return sm;
}
sm->skip_subroutines = skip_subroutines;
sm->single_inst = single_inst;
sm->count = count;
- sm->thread = thread->global_num;
/* Leave the si command alone. */
if (!sm->single_inst || sm->skip_subroutines)
/* Setup the execution command state machine to handle all the COUNT
steps. */
thr = inferior_thread ();
- step_sm = new_step_command_fsm ();
+ step_sm = new_step_command_fsm (command_interp ());
thr->thread_fsm = &step_sm->thread_fsm;
step_command_fsm_prepare (step_sm, skip_subroutines,
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
else
{
+ int proceeded;
+
/* Stepped into an inline frame. Pretend that we've
stopped. */
- thread_fsm_clean_up (thr->thread_fsm);
- normal_stop ();
- inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+ thread_fsm_clean_up (thr->thread_fsm, thr);
+ proceeded = normal_stop ();
+ if (!proceeded)
+ inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+ all_uis_check_sync_execution_done ();
}
}
will need to keep going. */
static int
-step_command_fsm_should_stop (struct thread_fsm *self)
+step_command_fsm_should_stop (struct thread_fsm *self, struct thread_info *tp)
{
struct step_command_fsm *sm = (struct step_command_fsm *) self;
- struct thread_info *tp = find_thread_global_id (sm->thread);
if (tp->control.stop_step)
{
/* Implementation of the 'clean_up' FSM method for stepping commands. */
static void
-step_command_fsm_clean_up (struct thread_fsm *self)
+step_command_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread)
{
struct step_command_fsm *sm = (struct step_command_fsm *) self;
if (!sm->single_inst || sm->skip_subroutines)
- delete_longjmp_breakpoint (sm->thread);
+ delete_longjmp_breakpoint (thread->global_num);
}
/* Implementation of the 'async_reply_reason' FSM method for stepping
&tp->control.step_range_end) == 0)
error (_("Cannot find bounds of current function"));
- target_terminal_ours ();
+ target_terminal_ours_for_output ();
printf_filtered (_("Single stepping until exit from function %s,"
"\nwhich has no line number information.\n"),
name);
int thread;
};
-static int until_next_fsm_should_stop (struct thread_fsm *self);
-static void until_next_fsm_clean_up (struct thread_fsm *self);
+static int until_next_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *thread);
+static void until_next_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread);
static enum async_reply_reason
until_next_fsm_async_reply_reason (struct thread_fsm *self);
/* Allocate a new until_next_fsm. */
static struct until_next_fsm *
-new_until_next_fsm (int thread)
+new_until_next_fsm (struct interp *cmd_interp, int thread)
{
struct until_next_fsm *sm;
sm = XCNEW (struct until_next_fsm);
- thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops);
+ thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops, cmd_interp);
sm->thread = thread;
no arg) command. */
static int
-until_next_fsm_should_stop (struct thread_fsm *self)
+until_next_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *tp)
{
- struct thread_info *tp = inferior_thread ();
-
if (tp->control.stop_step)
thread_fsm_set_finished (self);
arg) command. */
static void
-until_next_fsm_clean_up (struct thread_fsm *self)
+until_next_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread)
{
struct until_next_fsm *sm = (struct until_next_fsm *) self;
- delete_longjmp_breakpoint (sm->thread);
+ delete_longjmp_breakpoint (thread->global_num);
}
/* Implementation of the 'async_reply_reason' FSM method for the until
set_longjmp_breakpoint (tp, get_frame_id (frame));
old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
- sm = new_until_next_fsm (tp->global_num);
+ sm = new_until_next_fsm (command_interp (), tp->global_num);
tp->thread_fsm = &sm->thread_fsm;
discard_cleanups (old_chain);
}
else
{
- struct cleanup *oldchain;
- char *type_name;
-
- type_name = type_to_string (rv->type);
- oldchain = make_cleanup (xfree, type_name);
+ std::string type_name = type_to_string (rv->type);
ui_out_text (uiout, "Value returned has type: ");
- ui_out_field_string (uiout, "return-type", type_name);
+ ui_out_field_string (uiout, "return-type", type_name.c_str ());
ui_out_text (uiout, ".");
ui_out_text (uiout, " Cannot determine contents\n");
- do_cleanups (oldchain);
}
}
/* The base class. */
struct thread_fsm thread_fsm;
- /* The thread that was current when the command was executed. */
- int thread;
-
/* The momentary breakpoint set at the function's return address in
the caller. */
struct breakpoint *breakpoint;
struct return_value_info return_value;
};
-static int finish_command_fsm_should_stop (struct thread_fsm *self);
-static void finish_command_fsm_clean_up (struct thread_fsm *self);
+static int finish_command_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *thread);
+static void finish_command_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread);
static struct return_value_info *
finish_command_fsm_return_value (struct thread_fsm *self);
static enum async_reply_reason
finish_command_fsm_should_stop,
finish_command_fsm_return_value,
finish_command_fsm_async_reply_reason,
+ NULL, /* should_notify_stop */
};
/* Allocate a new finish_command_fsm. */
static struct finish_command_fsm *
-new_finish_command_fsm (int thread)
+new_finish_command_fsm (struct interp *cmd_interp)
{
struct finish_command_fsm *sm;
sm = XCNEW (struct finish_command_fsm);
- thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops);
-
- sm->thread = thread;
+ thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops, cmd_interp);
return sm;
}
marks the FSM finished. */
static int
-finish_command_fsm_should_stop (struct thread_fsm *self)
+finish_command_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *tp)
{
struct finish_command_fsm *f = (struct finish_command_fsm *) self;
struct return_value_info *rv = &f->return_value;
- struct thread_info *tp = find_thread_global_id (f->thread);
if (f->function != NULL
&& bpstat_find_breakpoint (tp->control.stop_bpstat,
commands. */
static void
-finish_command_fsm_clean_up (struct thread_fsm *self)
+finish_command_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread)
{
struct finish_command_fsm *f = (struct finish_command_fsm *) self;
delete_breakpoint (f->breakpoint);
f->breakpoint = NULL;
}
- delete_longjmp_breakpoint (f->thread);
+ delete_longjmp_breakpoint (thread->global_num);
}
/* Implementation of the 'return_value' FSM method for the finish
static enum async_reply_reason
finish_command_fsm_async_reply_reason (struct thread_fsm *self)
{
- struct finish_command_fsm *f = (struct finish_command_fsm *) self;
-
if (execution_direction == EXEC_REVERSE)
return EXEC_ASYNC_END_STEPPING_RANGE;
else
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
+/* Skip frames for "finish". */
+
+static struct frame_info *
+skip_finish_frames (struct frame_info *frame)
+{
+ struct frame_info *start;
+
+ do
+ {
+ start = frame;
+
+ frame = skip_tailcall_frames (frame);
+ if (frame == NULL)
+ break;
+
+ frame = skip_unwritable_frames (frame);
+ if (frame == NULL)
+ break;
+ }
+ while (start != frame);
+
+ return frame;
+}
+
/* "finish": Set a temporary breakpoint at the place the selected
frame will return to, then continue. */
tp = inferior_thread ();
- sm = new_finish_command_fsm (tp->global_num);
+ sm = new_finish_command_fsm (command_interp ());
tp->thread_fsm = &sm->thread_fsm;
return;
}
- /* Ignore TAILCALL_FRAME type frames, they were executed already before
- entering THISFRAME. */
- while (get_frame_type (frame) == TAILCALL_FRAME)
- frame = get_prev_frame (frame);
-
/* Find the function we will return from. */
sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
if (execution_direction == EXEC_REVERSE)
finish_backward (sm);
else
- finish_forward (sm, frame);
+ {
+ frame = skip_finish_frames (frame);
+
+ if (frame == NULL)
+ error (_("Cannot find the caller frame."));
+
+ finish_forward (sm, frame);
+ }
}
\f
if (TYPE_CODE (regtype) == TYPE_CODE_FLT
|| TYPE_CODE (regtype) == TYPE_CODE_DECFLOAT)
{
- int j;
struct value_print_options opts;
const gdb_byte *valaddr = value_contents_for_printing (val);
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype));
opts.deref_ref = 1;
val_print (regtype,
- value_contents_for_printing (val),
value_embedded_offset (val), 0,
file, 0, val, &opts, current_language);
get_formatted_print_options (&opts, 'x');
opts.deref_ref = 1;
val_print (regtype,
- value_contents_for_printing (val),
value_embedded_offset (val), 0,
file, 0, val, &opts, current_language);
/* If not a vector register, print it also according to its
opts.deref_ref = 1;
fprintf_filtered (file, "\t");
val_print (regtype,
- value_contents_for_printing (val),
value_embedded_offset (val), 0,
file, 0, val, &opts, current_language);
}
/* If no exec file is yet known, try to determine it from the
process itself. */
if (get_exec_file (0) == NULL)
- exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty);
+ exec_file_locate_attach (ptid_get_pid (inferior_ptid), 1, from_tty);
else
{
reopen_exec_file ();
/* The user requested a plain `attach', so be sure to leave
the inferior stopped. */
- async_enable_stdin ();
-
/* At least the current thread is already stopped. */
/* In all-stop, by definition, all threads have to be already
STOP_QUIETLY_NO_SIGSTOP is for. */
inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP;
- /* sync_execution mode. Wait for stop. */
+ /* Wait for stop. */
a = XNEW (struct attach_command_continuation_args);
a->args = xstrdup (args);
a->from_tty = from_tty;
old_chain = make_cleanup (null_cleanup, NULL);
- /* If in non-stop, leave threads as running as they were. If
- they're stopped for some reason other than us telling it to, the
- target reports a signal != GDB_SIGNAL_0. We don't try to
- resume threads with such a stop signal. */
- mode = non_stop ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
+ mode = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
if (!ptid_equal (inferior_ptid, null_ptid))
make_cleanup_restore_current_thread ();
return;
}
- mode = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
attach_post_wait ("" /* args */, from_tty, mode);
do_cleanups (old_chain);
target_detach (args, from_tty);
+ /* The current inferior process was just detached successfully. Get
+ rid of breakpoints that no longer make sense. Note we don't do
+ this within target_detach because that is also used when
+ following child forks, and in that case we will want to transfer
+ breakpoints to the child, not delete them. */
+ breakpoint_init_inferior (inf_exited);
+
/* If the solist is global across inferiors, don't clear it when we
detach from a single inferior. */
if (!gdbarch_has_global_solist (target_gdbarch ()))
ptid = minus_one_ptid;
else
ptid = inferior_ptid;
- target_interrupt (ptid);
+
+ if (non_stop)
+ target_stop (ptid);
+ else
+ target_interrupt (ptid);
/* Tag the thread as having been explicitly requested to stop, so
other parts of gdb know not to resume this thread automatically,
const char *cmd_name;
/* Add the filename of the terminal connected to inferior I/O. */
- add_setshow_filename_cmd ("inferior-tty", class_run,
- &inferior_io_terminal_scratch, _("\
+ add_setshow_optional_filename_cmd ("inferior-tty", class_run,
+ &inferior_io_terminal_scratch, _("\
Set terminal for future runs of program being debugged."), _("\
Show terminal for future runs of program being debugged."), _("\
-Usage: set inferior-tty /dev/pts/1"),
- set_inferior_tty_command,
- show_inferior_tty_command,
- &setlist, &showlist);
+Usage: set inferior-tty [TTY]\n\n\
+If TTY is omitted, the default behavior of using the same terminal as GDB\n\
+is restored."),
+ set_inferior_tty_command,
+ show_inferior_tty_command,
+ &setlist, &showlist);
add_com_alias ("tty", "set inferior-tty", class_alias, 0);
cmd_name = "args";