aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/infrun.c58
-rw-r--r--gdb/target-connection.c7
-rw-r--r--gdb/target-connection.h8
4 files changed, 77 insertions, 5 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d07a792..63c32a0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2020-01-10 Pedro Alves <palves@redhat.com>
+ * infrun.c: Include "target-connection.h".
+ (check_multi_target_resumption): New.
+ (proceed): Call it.
+ * target-connection.c (make_target_connection_string): Make
+ extern.
+ * target-connection.h (make_target_connection_string): Declare.
+
+2020-01-10 Pedro Alves <palves@redhat.com>
+
* Makefile.in (COMMON_SFILES): Add target-connection.c.
* inferior.c (uiout_field_connection): New function.
(print_inferior): Add new "connection-id" column.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 707c053..a0583a8 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -28,6 +28,7 @@
#include "gdbcore.h"
#include "gdbcmd.h"
#include "target.h"
+#include "target-connection.h"
#include "gdbthread.h"
#include "annotate.h"
#include "symfile.h"
@@ -2881,6 +2882,61 @@ commit_resume_all_targets ()
}
}
+/* Check that all the targets we're about to resume are in non-stop
+ mode. Ideally, we'd only care whether all targets support
+ target-async, but we're not there yet. E.g., stop_all_threads
+ doesn't know how to handle all-stop targets. Also, the remote
+ protocol in all-stop mode is synchronous, irrespective of
+ target-async, which means that things like a breakpoint re-set
+ triggered by one target would try to read memory from all targets
+ and fail. */
+
+static void
+check_multi_target_resumption (process_stratum_target *resume_target)
+{
+ if (!non_stop && resume_target == nullptr)
+ {
+ scoped_restore_current_thread restore_thread;
+
+ /* This is used to track whether we're resuming more than one
+ target. */
+ process_stratum_target *first_connection = nullptr;
+
+ /* The first inferior we see with a target that does not work in
+ always-non-stop mode. */
+ inferior *first_not_non_stop = nullptr;
+
+ for (inferior *inf : all_non_exited_inferiors (resume_target))
+ {
+ switch_to_inferior_no_thread (inf);
+
+ if (!target_has_execution)
+ continue;
+
+ process_stratum_target *proc_target
+ = current_inferior ()->process_target();
+
+ if (!target_is_non_stop_p ())
+ first_not_non_stop = inf;
+
+ if (first_connection == nullptr)
+ first_connection = proc_target;
+ else if (first_connection != proc_target
+ && first_not_non_stop != nullptr)
+ {
+ switch_to_inferior_no_thread (first_not_non_stop);
+
+ proc_target = current_inferior ()->process_target();
+
+ error (_("Connection %d (%s) does not support "
+ "multi-target resumption."),
+ proc_target->connection_number,
+ make_target_connection_string (proc_target).c_str ());
+ }
+ }
+ }
+}
+
/* Basic routine for continuing the program in various fashions.
ADDR is the address to resume at, or -1 for resume where stopped.
@@ -2931,6 +2987,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
process_stratum_target *resume_target
= user_visible_resume_target (resume_ptid);
+ check_multi_target_resumption (resume_target);
+
if (addr == (CORE_ADDR) -1)
{
if (pc == cur_thr->suspend.stop_pc
diff --git a/gdb/target-connection.c b/gdb/target-connection.c
index 35c786b..c8c63ab 100644
--- a/gdb/target-connection.c
+++ b/gdb/target-connection.c
@@ -53,12 +53,9 @@ connection_list_remove (process_stratum_target *t)
t->connection_number = 0;
}
-/* Make a target connection string for T. This is usually T's
- shortname, but it includes the result of
- process_stratum_target::connection_string() too if T supports
- it. */
+/* See target-connection.h. */
-static std::string
+std::string
make_target_connection_string (process_stratum_target *t)
{
if (t->connection_string () != NULL)
diff --git a/gdb/target-connection.h b/gdb/target-connection.h
index dad3357..f97e476 100644
--- a/gdb/target-connection.h
+++ b/gdb/target-connection.h
@@ -20,6 +20,8 @@
#ifndef TARGET_CONNECTION_H
#define TARGET_CONNECTION_H
+#include <string>
+
struct process_stratum_target;
/* Add a process target to the connection list, if not already
@@ -29,4 +31,10 @@ void connection_list_add (process_stratum_target *t);
/* Remove a process target from the connection list. */
void connection_list_remove (process_stratum_target *t);
+/* Make a target connection string for T. This is usually T's
+ shortname, but it includes the result of
+ process_stratum_target::connection_string() too if T supports
+ it. */
+std::string make_target_connection_string (process_stratum_target *t);
+
#endif /* TARGET_CONNECTION_H */