aboutsummaryrefslogtreecommitdiff
path: root/gdbstub
diff options
context:
space:
mode:
authorMatheus Branco Borella <dark.ryu.550@gmail.com>2023-08-29 17:15:24 +0100
committerAlex Bennée <alex.bennee@linaro.org>2023-08-30 14:57:50 +0100
commit761e3c10881b5f521b19b713cf8d16c72c47affb (patch)
treef6ea91ed5e74bf8fe868826ef8217d39890bf8f7 /gdbstub
parenta8fea70f656416b2ed7d388fbcc7cc6cda126a82 (diff)
downloadqemu-761e3c10881b5f521b19b713cf8d16c72c47affb.zip
qemu-761e3c10881b5f521b19b713cf8d16c72c47affb.tar.gz
qemu-761e3c10881b5f521b19b713cf8d16c72c47affb.tar.bz2
gdbstub: fixes cases where wrong threads were reported to GDB on SIGINT
This fix is implemented by having the vCont handler set the value of `gdbserver_state.c_cpu` if any threads are to be resumed. The specific CPU picked is arbitrarily from the ones to be resumed, but it should be okay, as all GDB cares about is that it is a resumed thread. Signed-off-by: Matheus Branco Borella <dark.ryu.550@gmail.com> Message-Id: <20230804182633.47300-2-dark.ryu.550@gmail.com> [AJB: style and whitespace fixes] Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1725 Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20230829161528.2707696-9-alex.bennee@linaro.org>
Diffstat (limited to 'gdbstub')
-rw-r--r--gdbstub/gdbstub.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 5f28d5c..e7d48fa 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -597,6 +597,15 @@ static int gdb_handle_vcont(const char *p)
* or incorrect parameters passed.
*/
res = 0;
+
+ /*
+ * target_count and last_target keep track of how many CPUs we are going to
+ * step or resume, and a pointer to the state structure of one of them,
+ * respectivelly
+ */
+ int target_count = 0;
+ CPUState *last_target = NULL;
+
while (*p) {
if (*p++ != ';') {
return -ENOTSUP;
@@ -637,6 +646,9 @@ static int gdb_handle_vcont(const char *p)
while (cpu) {
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
+
+ target_count++;
+ last_target = cpu;
}
cpu = gdb_next_attached_cpu(cpu);
@@ -654,6 +666,9 @@ static int gdb_handle_vcont(const char *p)
while (cpu) {
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
+
+ target_count++;
+ last_target = cpu;
}
cpu = gdb_next_cpu_in_process(cpu);
@@ -671,11 +686,25 @@ static int gdb_handle_vcont(const char *p)
/* only use if no previous match occourred */
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
+
+ target_count++;
+ last_target = cpu;
}
break;
}
}
+ /*
+ * if we're about to resume a specific set of CPUs/threads, make it so that
+ * in case execution gets interrupted, we can send GDB a stop reply with a
+ * correct value. it doesn't really matter which CPU we tell GDB the signal
+ * happened in (VM pauses stop all of them anyway), so long as it is one of
+ * the ones we resumed/single stepped here.
+ */
+ if (target_count > 0) {
+ gdbserver_state.c_cpu = last_target;
+ }
+
gdbserver_state.signal = signal;
gdb_continue_partial(newstates);
return res;