Commit 36556b20c5c9a02f5e238435cd41bf67740359ee
1 parent
819f56b7
gdbstub: Allow re-instantiation (Jan Kiszka)
[ Note: depends on char closing fixes ] Properly clean up the gdbstub when the user tries to re-open it (possibly under a different address). Moreover, allow to shut it down from the monitor via 'gdbserver none'. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6913 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
38 additions
and
21 deletions
gdbstub.c
@@ -265,6 +265,7 @@ typedef struct GDBRegisterState { | @@ -265,6 +265,7 @@ typedef struct GDBRegisterState { | ||
265 | } GDBRegisterState; | 265 | } GDBRegisterState; |
266 | 266 | ||
267 | enum RSState { | 267 | enum RSState { |
268 | + RS_INACTIVE, | ||
268 | RS_IDLE, | 269 | RS_IDLE, |
269 | RS_GETLINE, | 270 | RS_GETLINE, |
270 | RS_CHKSUM1, | 271 | RS_CHKSUM1, |
@@ -1924,7 +1925,7 @@ static void gdb_vm_state_change(void *opaque, int running, int reason) | @@ -1924,7 +1925,7 @@ static void gdb_vm_state_change(void *opaque, int running, int reason) | ||
1924 | int ret; | 1925 | int ret; |
1925 | 1926 | ||
1926 | if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) || | 1927 | if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) || |
1927 | - s->state == RS_SYSCALL) | 1928 | + s->state == RS_INACTIVE || s->state == RS_SYSCALL) |
1928 | return; | 1929 | return; |
1929 | 1930 | ||
1930 | /* disable single step if it was enable */ | 1931 | /* disable single step if it was enable */ |
@@ -2342,36 +2343,50 @@ int gdbserver_start(const char *port) | @@ -2342,36 +2343,50 @@ int gdbserver_start(const char *port) | ||
2342 | char gdbstub_port_name[128]; | 2343 | char gdbstub_port_name[128]; |
2343 | int port_num; | 2344 | int port_num; |
2344 | char *p; | 2345 | char *p; |
2345 | - CharDriverState *chr; | 2346 | + CharDriverState *chr = NULL; |
2347 | + CharDriverState *mon_chr; | ||
2346 | 2348 | ||
2347 | if (!port || !*port) | 2349 | if (!port || !*port) |
2348 | return -1; | 2350 | return -1; |
2351 | + if (strcmp(port, "none") != 0) { | ||
2352 | + port_num = strtol(port, &p, 10); | ||
2353 | + if (*p == 0) { | ||
2354 | + /* A numeric value is interpreted as a port number. */ | ||
2355 | + snprintf(gdbstub_port_name, sizeof(gdbstub_port_name), | ||
2356 | + "tcp::%d,nowait,nodelay,server", port_num); | ||
2357 | + port = gdbstub_port_name; | ||
2358 | + } | ||
2349 | 2359 | ||
2350 | - port_num = strtol(port, &p, 10); | ||
2351 | - if (*p == 0) { | ||
2352 | - /* A numeric value is interpreted as a port number. */ | ||
2353 | - snprintf(gdbstub_port_name, sizeof(gdbstub_port_name), | ||
2354 | - "tcp::%d,nowait,nodelay,server", port_num); | ||
2355 | - port = gdbstub_port_name; | 2360 | + chr = qemu_chr_open("gdb", port, NULL); |
2361 | + if (!chr) | ||
2362 | + return -1; | ||
2363 | + | ||
2364 | + qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, | ||
2365 | + gdb_chr_event, NULL); | ||
2356 | } | 2366 | } |
2357 | 2367 | ||
2358 | - chr = qemu_chr_open("gdb", port, NULL); | ||
2359 | - if (!chr) | ||
2360 | - return -1; | 2368 | + s = gdbserver_state; |
2369 | + if (!s) { | ||
2370 | + s = qemu_mallocz(sizeof(GDBState)); | ||
2371 | + gdbserver_state = s; | ||
2361 | 2372 | ||
2362 | - s = qemu_mallocz(sizeof(GDBState)); | 2373 | + qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL); |
2374 | + | ||
2375 | + /* Initialize a monitor terminal for gdb */ | ||
2376 | + mon_chr = qemu_mallocz(sizeof(*mon_chr)); | ||
2377 | + mon_chr->chr_write = gdb_monitor_write; | ||
2378 | + monitor_init(mon_chr, 0); | ||
2379 | + } else { | ||
2380 | + if (s->chr) | ||
2381 | + qemu_chr_close(s->chr); | ||
2382 | + mon_chr = s->mon_chr; | ||
2383 | + memset(s, 0, sizeof(GDBState)); | ||
2384 | + } | ||
2363 | s->c_cpu = first_cpu; | 2385 | s->c_cpu = first_cpu; |
2364 | s->g_cpu = first_cpu; | 2386 | s->g_cpu = first_cpu; |
2365 | s->chr = chr; | 2387 | s->chr = chr; |
2366 | - gdbserver_state = s; | ||
2367 | - qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, | ||
2368 | - gdb_chr_event, NULL); | ||
2369 | - qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL); | ||
2370 | - | ||
2371 | - /* Initialize a monitor terminal for gdb */ | ||
2372 | - s->mon_chr = qemu_mallocz(sizeof(*s->mon_chr)); | ||
2373 | - s->mon_chr->chr_write = gdb_monitor_write; | ||
2374 | - monitor_init(s->mon_chr, 0); | 2388 | + s->state = chr ? RS_IDLE : RS_INACTIVE; |
2389 | + s->mon_chr = mon_chr; | ||
2375 | 2390 | ||
2376 | return 0; | 2391 | return 0; |
2377 | } | 2392 | } |
monitor.c
@@ -577,6 +577,8 @@ static void do_gdbserver(Monitor *mon, const char *port) | @@ -577,6 +577,8 @@ static void do_gdbserver(Monitor *mon, const char *port) | ||
577 | if (gdbserver_start(port) < 0) { | 577 | if (gdbserver_start(port) < 0) { |
578 | monitor_printf(mon, "Could not open gdbserver socket on port '%s'\n", | 578 | monitor_printf(mon, "Could not open gdbserver socket on port '%s'\n", |
579 | port); | 579 | port); |
580 | + } else if (strcmp(port, "none") == 0) { | ||
581 | + monitor_printf(mon, "Disabled gdbserver\n"); | ||
580 | } else { | 582 | } else { |
581 | monitor_printf(mon, "Waiting gdb connection on port '%s'\n", port); | 583 | monitor_printf(mon, "Waiting gdb connection on port '%s'\n", port); |
582 | } | 584 | } |