aboutsummaryrefslogtreecommitdiff
path: root/gdb/infcmd.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2015-11-30 16:05:13 +0000
committerPedro Alves <palves@redhat.com>2015-11-30 18:36:37 +0000
commit6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e (patch)
treec037bfbc8a183642709bbcd8b6f6a36d6fe5dbd3 /gdb/infcmd.c
parentf015c27b5294eaf87d0aa814d94972e65c7cc90e (diff)
downloadgdb-6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e.zip
gdb-6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e.tar.gz
gdb-6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e.tar.bz2
Remote all-stop-on-top-of-non-stop
This is the first pass at implementing support for all-stop mode running against the remote target using the non-stop variant of the protocol. The trickiest part here is the initial connection setup/synching. We need to fetch all inferiors' target descriptions etc. before stopping threads, because stop_all_threads needs to read the threads' registers (to record each thread's stop_pc). But OTOH, the initial inferior setup (target_post_attach, post_create_inferior, etc.), only works correctly if the inferior is stopped... So I've split that initial setup part from attach_command_post_wait to a separate function, and added a "still needs setup" flag to the inferior structure. This is similar to gdbserver/linux-low.c's handling of discovering the process's target description). Then if on connection all threads of the remote inferior are running, when we go about stopping them, as soon as they stop we call setup_inferior, from within stop_all_threads. Also, in all-stop, we need to process all the initial stop replies to learn about all the pending signal the threads may already be stopped for, and pick the one to report as current. This is exposed by gdb.threads/reconnect-signal.exp. gdb/ 2015-11-30 Pedro Alves <palves@redhat.com> * gdbthread.h (switch_to_thread_no_regs): Declare. * infcmd.c (setup_inferior): New function, factored out from ... (attach_command_post_wait): ... this. Rename to ... (attach_post_wait): ... this. Replace parameter async_exec with attach_post_wait_mode parameter. Adjust. (enum attach_post_wait_mode): New enum. (struct attach_command_continuation_args): Replace 'async_exec' field with 'mode' field. (attach_command_continuation): Adjust. (attach_command): Add comment. Mark the inferior as needing setup. Adjust to use enum attach_post_wait_mode. (notice_new_inferior): Use switch_to_thread_no_regs. Adjust to use enum attach_post_wait_mode. * inferior.h (setup_inferior): Declare. (struct inferior) <needs_setup>: New field. * infrun.c (set_last_target_status): Make extern. (stop_all_threads): Make extern. Setup inferior, if necessary. * infrun.h (set_last_target_status, stop_all_threads): Declare. * remote-notif.c (remote_async_get_pending_events_handler) (handle_notification): Replace non_stop checks with target_is_non_stop_p() checks. * remote.c (remote_notice_new_inferior): Remove non_stop check. (remote_update_thread_list): Replace non_stop check with target_is_non_stop_p() check. (print_one_stopped_thread): New function. (process_initial_stop_replies): New 'from_tty' parameter. "Notice" all new live inferiors after storing initial stops as pending status in each corresponding thread. If all-stop, stop all threads, try picking a signalled thread as current, and print the status of that one thread. Record the last target status. (remote_start_remote): Replace non_stop checks with target_is_non_stop_p() checks. Don't query for the remote current thread of use qOffsets here. Pass from_tty to process_initial_stop_replies. (extended_remote_attach): Replace non_stop checks with target_is_non_stop_p() checks. (extended_remote_post_attach): Send qOffsets here. (remote_vcont_resume, remote_resume, remote_stop) (remote_interrupt, remote_parse_stop_reply, remote_wait): Replace non_stop checks with target_is_non_stop_p() checks. (remote_async): If target is non-stop, mark/clear the pending events token. * thread.c (switch_to_thread_no_regs): New function.
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r--gdb/infcmd.c77
1 files changed, 57 insertions, 20 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 54aa1ef..9aae860 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2609,18 +2609,15 @@ proceed_after_attach (int pid)
do_cleanups (old_chain);
}
-/* attach_command --
- takes a program started up outside of gdb and ``attaches'' to it.
- This stops it cold in its tracks and allows us to start debugging it.
- and wait for the trace-trap that results from attaching. */
+/* See inferior.h. */
-static void
-attach_command_post_wait (char *args, int from_tty, int async_exec)
+void
+setup_inferior (int from_tty)
{
struct inferior *inferior;
inferior = current_inferior ();
- inferior->control.stop_soon = NO_STOP_QUIETLY;
+ inferior->needs_setup = 0;
/* If no exec file is yet known, try to determine it from the
process itself. */
@@ -2636,8 +2633,37 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
target_post_attach (ptid_get_pid (inferior_ptid));
post_create_inferior (&current_target, from_tty);
+}
+
+/* What to do after the first program stops after attaching. */
+enum attach_post_wait_mode
+{
+ /* Do nothing. Leaves threads as they are. */
+ ATTACH_POST_WAIT_NOTHING,
+
+ /* Re-resume threads that are marked running. */
+ ATTACH_POST_WAIT_RESUME,
+
+ /* Stop all threads. */
+ ATTACH_POST_WAIT_STOP,
+};
+
+/* Called after we've attached to a process and we've seen it stop for
+ the first time. If ASYNC_EXEC is true, re-resume threads that
+ should be running. Else if ATTACH, */
+
+static void
+attach_post_wait (char *args, int from_tty, enum attach_post_wait_mode mode)
+{
+ struct inferior *inferior;
- if (async_exec)
+ inferior = current_inferior ();
+ inferior->control.stop_soon = NO_STOP_QUIETLY;
+
+ if (inferior->needs_setup)
+ setup_inferior (from_tty);
+
+ if (mode == ATTACH_POST_WAIT_RESUME)
{
/* The user requested an `attach&', so be sure to leave threads
that didn't get a signal running. */
@@ -2657,7 +2683,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
}
}
}
- else
+ else if (mode == ATTACH_POST_WAIT_STOP)
{
/* The user requested a plain `attach', so be sure to leave
the inferior stopped. */
@@ -2685,7 +2711,7 @@ struct attach_command_continuation_args
{
char *args;
int from_tty;
- int async_exec;
+ enum attach_post_wait_mode mode;
};
static void
@@ -2697,7 +2723,7 @@ attach_command_continuation (void *args, int err)
if (err)
return;
- attach_command_post_wait (a->args, a->from_tty, a->async_exec);
+ attach_post_wait (a->args, a->from_tty, a->mode);
}
static void
@@ -2710,12 +2736,18 @@ attach_command_continuation_free_args (void *args)
xfree (a);
}
+/* "attach" command entry point. Takes a program started up outside
+ of gdb and ``attaches'' to it. This stops it cold in its tracks
+ and allows us to start debugging it. */
+
void
attach_command (char *args, int from_tty)
{
int async_exec;
struct cleanup *args_chain;
struct target_ops *attach_target;
+ struct inferior *inferior = current_inferior ();
+ enum attach_post_wait_mode mode;
dont_repeat (); /* Not for the faint of heart */
@@ -2775,6 +2807,8 @@ attach_command (char *args, int from_tty)
init_wait_for_inferior ();
clear_proceed_status (0);
+ inferior->needs_setup = 1;
+
if (target_is_non_stop_p ())
{
/* If we find that the current thread isn't stopped, explicitly
@@ -2790,12 +2824,13 @@ attach_command (char *args, int from_tty)
target_stop (pid_to_ptid (ptid_get_pid (inferior_ptid)));
}
+ mode = async_exec ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_STOP;
+
/* Some system don't generate traps when attaching to inferior.
E.g. Mach 3 or GNU hurd. */
if (!target_attach_no_wait)
{
struct attach_command_continuation_args *a;
- struct inferior *inferior = current_inferior ();
/* Careful here. See comments in inferior.h. Basically some
OSes don't ignore SIGSTOPs on continue requests anymore. We
@@ -2808,7 +2843,7 @@ attach_command (char *args, int from_tty)
a = XNEW (struct attach_command_continuation_args);
a->args = xstrdup (args);
a->from_tty = from_tty;
- a->async_exec = async_exec;
+ a->mode = mode;
add_inferior_continuation (attach_command_continuation, a,
attach_command_continuation_free_args);
/* Done with ARGS. */
@@ -2822,7 +2857,7 @@ attach_command (char *args, int from_tty)
/* Done with ARGS. */
do_cleanups (args_chain);
- attach_command_post_wait (args, from_tty, async_exec);
+ attach_post_wait (args, from_tty, mode);
}
/* We had just found out that the target was already attached to an
@@ -2837,7 +2872,7 @@ void
notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
{
struct cleanup* old_chain;
- int async_exec;
+ enum attach_post_wait_mode mode;
old_chain = make_cleanup (null_cleanup, NULL);
@@ -2845,12 +2880,14 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
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. */
- async_exec = non_stop;
+ mode = non_stop ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
if (!ptid_equal (inferior_ptid, null_ptid))
make_cleanup_restore_current_thread ();
- switch_to_thread (ptid);
+ /* Avoid reading registers -- we haven't fetched the target
+ description yet. */
+ switch_to_thread_no_regs (find_thread_ptid (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. */
@@ -2871,7 +2908,7 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
a = XNEW (struct attach_command_continuation_args);
a->args = xstrdup ("");
a->from_tty = from_tty;
- a->async_exec = async_exec;
+ a->mode = mode;
add_inferior_continuation (attach_command_continuation, a,
attach_command_continuation_free_args);
@@ -2879,8 +2916,8 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
return;
}
- async_exec = leave_running;
- attach_command_post_wait ("" /* args */, from_tty, async_exec);
+ mode = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
+ attach_post_wait ("" /* args */, from_tty, mode);
do_cleanups (old_chain);
}