Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008 Free Software Foundation, Inc.
+ 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
static void float_info (char *, int);
-static void detach_command (char *, int);
-
static void disconnect_command (char *, int);
static void unset_environment_command (char *, int);
in format described in environ.h. */
struct gdb_environ *inferior_environ;
-
-/* When set, no calls to target_resumed observer will be made. */
-int suppress_resume_observer = 0;
-/* When set, normal_stop will not call the normal_stop observer. */
-int suppress_stop_observer = 0;
\f
/* Accessor routines. */
target_require_runnable ();
if (from_tty
- && !query ("The program being debugged has been started already.\n\
-Start it from the beginning? "))
+ && !query (_("The program being debugged has been started already.\n\
+Start it from the beginning? ")))
error (_("Program not restarted."));
target_kill ();
}
run_command_1 (char *args, int from_tty, int tbreak_at_main)
{
char *exec_file;
+ struct cleanup *old_chain;
+ ptid_t ptid;
dont_repeat ();
target_create_inferior (exec_file, get_inferior_args (),
environ_vector (inferior_environ), from_tty);
+ /* We're starting off a new process. When we get out of here, in
+ non-stop mode, finish the state of all threads of that process,
+ but leave other threads alone, as they may be stopped in internal
+ events --- the frontend shouldn't see them as stopped. In
+ all-stop, always finish the state of all threads, as we may be
+ resuming more than just the new process. */
+ if (non_stop)
+ ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
+ else
+ ptid = minus_one_ptid;
+ old_chain = make_cleanup (finish_thread_state_cleanup, &ptid);
+
/* Pass zero for FROM_TTY, because at this point the "run" command
has done its thing; now we are setting up the running program. */
post_create_inferior (¤t_target, 0);
/* Start the target running. */
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
-}
+ /* Since there was no error, there's no need to finish the thread
+ states here. */
+ discard_cleanups (old_chain);
+}
static void
run_command (char *args, int from_tty)
return 0;
}
+void
+ensure_valid_thread (void)
+{
+ if (ptid_equal (inferior_ptid, null_ptid)
+ || is_exited (inferior_ptid))
+ error (_("\
+Cannot execute this command without a live selected thread."));
+}
+
void
continue_1 (int all_threads)
{
}
else
{
+ ensure_valid_thread ();
ensure_not_running ();
clear_proceed_status ();
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
int thread = -1;
ERROR_NO_INFERIOR;
+ ensure_valid_thread ();
ensure_not_running ();
if (count_string)
make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
}
- /* In synchronous case, all is well, just use the regular for loop. */
+ /* In synchronous case, all is well; each step_once call will step once. */
if (!target_can_async_p ())
{
for (; count > 0; count--)
{
- struct thread_info *tp = inferior_thread ();
- clear_proceed_status ();
-
- frame = get_current_frame ();
- tp->step_frame_id = get_frame_id (frame);
+ struct thread_info *tp;
+ step_once (skip_subroutines, single_inst, count, thread);
- if (!single_inst)
- {
- find_pc_line_pc_range (stop_pc,
- &tp->step_range_start, &tp->step_range_end);
- if (tp->step_range_end == 0)
- {
- char *name;
- if (find_pc_partial_function (stop_pc, &name,
- &tp->step_range_start,
- &tp->step_range_end) == 0)
- error (_("Cannot find bounds of current function"));
-
- target_terminal_ours ();
- printf_filtered (_("\
-Single stepping until exit from function %s, \n\
-which has no line number information.\n"), name);
- }
- }
+ if (target_has_execution
+ && !ptid_equal (inferior_ptid, null_ptid))
+ tp = inferior_thread ();
else
+ tp = NULL;
+
+ if (!tp || !tp->stop_step || !tp->step_multi)
{
- /* Say we are stepping, but stop after one insn whatever it does. */
- tp->step_range_start = tp->step_range_end = 1;
- if (!skip_subroutines)
- /* It is stepi.
- Don't step over function calls, not even to functions lacking
- line numbers. */
- tp->step_over_calls = STEP_OVER_NONE;
+ /* If we stopped for some reason that is not stepping
+ there are no further steps to make. */
+ if (tp)
+ tp->step_multi = 0;
+ break;
}
-
- if (skip_subroutines)
- tp->step_over_calls = STEP_OVER_ALL;
-
- tp->step_multi = (count > 1);
- proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
-
- if (!target_has_execution
- || !inferior_thread ()->stop_step)
- break;
}
do_cleanups (cleanups);
- return;
}
- /* In case of asynchronous target things get complicated, do only
- one step for now, before returning control to the event loop. Let
- the continuation figure out how many other steps we need to do,
- and handle them one at the time, through step_once(). */
else
{
+ /* In the case of an asynchronous target things get complicated;
+ do only one step for now, before returning control to the
+ event loop. Let the continuation figure out how many other
+ steps we need to do, and handle them one at the time, through
+ step_once. */
step_once (skip_subroutines, single_inst, count, thread);
+
/* We are running, and the continuation is installed. It will
disable the longjmp breakpoint as appropriate. */
discard_cleanups (cleanups);
{
/* There are more steps to make, and we did stop due to
ending a stepping range. Do another step. */
- step_once (a->skip_subroutines, a->single_inst, a->count - 1, a->thread);
+ step_once (a->skip_subroutines, a->single_inst,
+ a->count - 1, a->thread);
return;
}
tp->step_multi = 0;
delete_longjmp_breakpoint (a->thread);
}
-/* Do just one step operation. If count >1 we will have to set up a
- continuation to be done after the target stops (after this one
- step). This is useful to implement the 'step n' kind of commands, in
- case of asynchronous targets. We had to split step_1 into two parts,
- one to be done before proceed() and one afterwards. This function is
- called in case of step n with n>1, after the first step operation has
- been completed.*/
-static void
+/* Do just one step operation. This is useful to implement the 'step
+ n' kind of commands. In case of asynchronous targets, we will have
+ to set up a continuation to be done after the target stops (after
+ this one step). For synch targets, the caller handles further
+ stepping. */
+
+static void
step_once (int skip_subroutines, int single_inst, int count, int thread)
{
struct frame_info *frame;
- struct step_1_continuation_args *args;
if (count > 0)
{
clear_proceed_status ();
frame = get_current_frame ();
- if (!frame) /* Avoid coredump here. Why tho? */
- error (_("No current frame"));
tp->step_frame_id = get_frame_id (frame);
if (!single_inst)
{
- find_pc_line_pc_range (stop_pc,
+ CORE_ADDR pc;
+
+ pc = get_frame_pc (frame);
+ find_pc_line_pc_range (pc,
&tp->step_range_start, &tp->step_range_end);
/* If we have no line info, switch to stepi mode. */
else if (tp->step_range_end == 0)
{
char *name;
- if (find_pc_partial_function (stop_pc, &name,
+ if (find_pc_partial_function (pc, &name,
&tp->step_range_start,
&tp->step_range_end) == 0)
error (_("Cannot find bounds of current function"));
tp->step_multi = (count > 1);
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
- args = xmalloc (sizeof (*args));
- args->skip_subroutines = skip_subroutines;
- args->single_inst = single_inst;
- args->count = count;
- args->thread = thread;
- add_intermediate_continuation (tp, step_1_continuation, args, xfree);
+ /* For async targets, register a continuation to do any
+ additional steps. For sync targets, the caller will handle
+ further stepping. */
+ if (target_can_async_p ())
+ {
+ struct step_1_continuation_args *args;
+
+ args = xmalloc (sizeof (*args));
+ args->skip_subroutines = skip_subroutines;
+ args->single_inst = single_inst;
+ args->count = count;
+ args->thread = thread;
+
+ add_intermediate_continuation (tp, step_1_continuation, args, xfree);
+ }
}
}
int async_exec = 0;
ERROR_NO_INFERIOR;
+ ensure_valid_thread ();
ensure_not_running ();
/* Find out whether we must run in the background. */
sfn = find_pc_function (sal.pc);
if (fn != NULL && sfn != fn)
{
- if (!query ("Line %d is not in `%s'. Jump anyway? ", sal.line,
+ if (!query (_("Line %d is not in `%s'. Jump anyway? "), sal.line,
SYMBOL_PRINT_NAME (fn)))
{
error (_("Not confirmed."));
if (section_is_overlay (SYMBOL_OBJ_SECTION (sfn)) &&
!section_is_mapped (SYMBOL_OBJ_SECTION (sfn)))
{
- if (!query ("WARNING!!! Destination is in unmapped overlay! Jump anyway? "))
+ if (!query (_("WARNING!!! Destination is in unmapped overlay! Jump anyway? ")))
{
error (_("Not confirmed."));
/* NOTREACHED */
dont_repeat (); /* Too dangerous. */
ERROR_NO_INFERIOR;
+ ensure_valid_thread ();
ensure_not_running ();
/* Find out whether we must run in the background. */
}
clear_proceed_status ();
- /* "signal 0" should not get stuck if we are stopped at a breakpoint.
- FIXME: Neither should "signal foo" but when I tried passing
- (CORE_ADDR)-1 unconditionally I got a testsuite failure which I haven't
- tried to track down yet. */
- proceed (oursig == TARGET_SIGNAL_0 ? (CORE_ADDR) -1 : stop_pc, oursig, 0);
+ proceed ((CORE_ADDR) -1, oursig, 0);
}
/* Proceed until we reach a different source line with pc greater than
than the current line (if in symbolic section) or pc (if
not). */
- pc = read_pc ();
+ pc = get_frame_pc (frame);
func = find_pc_function (pc);
if (!func)
finish_command_continuation (void *arg)
{
struct finish_command_continuation_args *a = arg;
-
+ struct thread_info *tp = NULL;
bpstat bs = NULL;
if (!ptid_equal (inferior_ptid, null_ptid)
&& target_has_execution
&& is_stopped (inferior_ptid))
- bs = inferior_thread ()->stop_bpstat;
+ {
+ tp = inferior_thread ();
+ bs = tp->stop_bpstat;
+ }
if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL
&& a->function != NULL)
}
/* We suppress normal call of normal_stop observer and do it here so
- that that *stopped notification includes the return value. */
- /* NOTE: This is broken in non-stop mode. There is no guarantee the
- next stop will be in the same thread that we started doing a
- finish on. This suppressing (or some other replacement means)
- should be a thread property. */
- observer_notify_normal_stop (bs);
- suppress_stop_observer = 0;
+ that the *stopped notification includes the return value. */
+ if (bs != NULL && tp->proceed_to_finish)
+ observer_notify_normal_stop (bs, 1 /* print frame */);
delete_breakpoint (a->breakpoint);
}
static void
finish_command_continuation_free_arg (void *arg)
{
- /* NOTE: See finish_command_continuation. This would go away, if
- this suppressing is made a thread property. */
- suppress_stop_observer = 0;
xfree (arg);
}
struct thread_info *tp = inferior_thread ();
struct breakpoint *breakpoint;
struct cleanup *old_chain;
+ CORE_ADDR pc;
CORE_ADDR func_addr;
int back_up;
- if (find_pc_partial_function (get_frame_pc (get_current_frame ()),
- NULL, &func_addr, NULL) == 0)
+ pc = get_frame_pc (get_current_frame ());
+
+ if (find_pc_partial_function (pc, NULL, &func_addr, NULL) == 0)
internal_error (__FILE__, __LINE__,
_("Finish: couldn't find function."));
no way that a function up the stack can have a return address
that's equal to its entry point. */
- if (sal.pc != read_pc ())
+ if (sal.pc != pc)
{
/* Set breakpoint and continue. */
breakpoint =
old_chain = make_cleanup_delete_breakpoint (breakpoint);
tp->proceed_to_finish = 1; /* We want stop_registers, please... */
- make_cleanup_restore_integer (&suppress_stop_observer);
- suppress_stop_observer = 1;
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
cargs = xmalloc (sizeof (*cargs));
stat = bpstat_num (&bs, &num);
target_files_info ();
- printf_filtered (_("Program stopped at %s.\n"),
- hex_string ((unsigned long) stop_pc));
+ printf_filtered (_("Program stopped at %s.\n"), paddress (stop_pc));
if (tp->stop_step)
printf_filtered (_("It stopped after being stepped.\n"));
else if (stat != 0)
}
}
- /* A register number? (how portable is this one?). */
- {
- char *endptr;
- int regnum = strtol (start, &endptr, 0);
- if (endptr == end
- && regnum >= 0
- && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
- {
- gdbarch_print_registers_info (gdbarch, gdb_stdout,
- frame, regnum, fpregs);
- continue;
- }
- }
-
/* A register group? */
{
struct reggroup *group;
;
else if (target_has_execution)
{
- if (query ("A program is being debugged already. Kill it? "))
+ if (query (_("A program is being debugged already. Kill it? ")))
target_kill ();
else
error (_("Not killed."));
discard_cleanups (back_to);
}
+/* We had just found out that the target was already attached to an
+ inferior. PTID points at a thread of this new inferior, that is
+ the most likely to be stopped right now, but not necessarily so.
+ The new inferior is assumed to be already added to the inferior
+ list at this point. If LEAVE_RUNNING, then leave the threads of
+ this inferior running, except those we've explicitly seen reported
+ as stopped. */
+
+void
+notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
+{
+ struct cleanup* old_chain;
+ int async_exec;
+
+ 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 != TARGET_SIGNAL_0. We don't try to
+ resume threads with such a stop signal. */
+ async_exec = non_stop;
+
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ make_cleanup_restore_current_thread ();
+
+ switch_to_thread (ptid);
+
+ /* When we "notice" a new inferior we need to do all the things we
+ would normally do if we had just attached to it. */
+
+ if (is_executing (inferior_ptid))
+ {
+ struct inferior *inferior = current_inferior ();
+
+ /* We're going to install breakpoints, and poke at memory,
+ ensure that the inferior is stopped for a moment while we do
+ that. */
+ target_stop (inferior_ptid);
+
+ inferior->stop_soon = STOP_QUIETLY_REMOTE;
+
+ /* Wait for stop before proceeding. */
+ if (target_can_async_p ())
+ {
+ struct attach_command_continuation_args *a;
+
+ a = xmalloc (sizeof (*a));
+ a->args = xstrdup ("");
+ a->from_tty = from_tty;
+ a->async_exec = async_exec;
+ add_inferior_continuation (attach_command_continuation, a,
+ attach_command_continuation_free_args);
+
+ do_cleanups (old_chain);
+ return;
+ }
+ else
+ wait_for_inferior (0);
+ }
+
+ async_exec = leave_running;
+ attach_command_post_wait ("" /* args */, from_tty, async_exec);
+
+ do_cleanups (old_chain);
+}
+
/*
* detach_command --
* takes a program previously attached to and detaches it.
* started via the normal ptrace (PTRACE_TRACEME).
*/
-static void
+void
detach_command (char *args, int from_tty)
{
dont_repeat (); /* Not for the faint of heart. */
+
+ if (ptid_equal (inferior_ptid, null_ptid))
+ error (_("The program is not being run."));
+
target_detach (args, from_tty);
/* If the solist is global across inferiors, don't clear it when we