aboutsummaryrefslogtreecommitdiffstats
path: root/gdbstub.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2009-06-27 09:53:51 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-07-16 08:28:13 -0500
commitdd32aa10476d04853b71657d5345e812915d87ed (patch)
treedb1ebcc2f687b0726ebd322c9f35e203d27163fa /gdbstub.c
parent8389e7f4e1412cee0d8f8c21a1386259338a6299 (diff)
gdbstub: Add vCont support
This patch adds support for the vCont remote gdb command. It is used by gdb 6.8 or better to switch the debugging focus for single-stepping multi-threaded targets, ie. multi-threaded application in user mode emulation or VCPUs in system emulation. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'gdbstub.c')
-rw-r--r--gdbstub.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/gdbstub.c b/gdbstub.c
index 9bd437585..74713fd20 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1631,6 +1631,64 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
s->signal = 0;
gdb_continue(s);
return RS_IDLE;
+ case 'v':
+ if (strncmp(p, "Cont", 4) == 0) {
+ int res_signal, res_thread;
+
+ p += 4;
+ if (*p == '?') {
+ put_packet(s, "vCont;c;C;s;S");
+ break;
+ }
+ res = 0;
+ res_signal = 0;
+ res_thread = 0;
+ while (*p) {
+ int action, signal;
+
+ if (*p++ != ';') {
+ res = 0;
+ break;
+ }
+ action = *p++;
+ signal = 0;
+ if (action == 'C' || action == 'S') {
+ signal = strtoul(p, (char **)&p, 16);
+ } else if (action != 'c' && action != 's') {
+ res = 0;
+ break;
+ }
+ thread = 0;
+ if (*p == ':') {
+ thread = strtoull(p+1, (char **)&p, 16);
+ }
+ action = tolower(action);
+ if (res == 0 || (res == 'c' && action == 's')) {
+ res = action;
+ res_signal = signal;
+ res_thread = thread;
+ }
+ }
+ if (res) {
+ if (res_thread != -1 && res_thread != 0) {
+ env = find_cpu(res_thread);
+ if (env == NULL) {
+ put_packet(s, "E22");
+ break;
+ }
+ s->c_cpu = env;
+ }
+ if (res == 's') {
+ cpu_single_step(s->c_cpu, sstep_flags);
+ }
+ s->signal = res_signal;
+ gdb_continue(s);
+ return RS_IDLE;
+ }
+ break;
+ } else {
+ goto unknown_command;
+ }
case 'k':
/* Kill the target */
fprintf(stderr, "\nQEMU: Terminated via GDBstub\n");