diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/infrun.c | 58 | ||||
-rw-r--r-- | gdb/target-connection.c | 7 | ||||
-rw-r--r-- | gdb/target-connection.h | 8 |
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 */ |