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
This commit is contained in:
aliguori 2009-03-28 18:05:53 +00:00
parent 819f56b7fb
commit 36556b20c5
2 changed files with 38 additions and 21 deletions

View File

@ -265,6 +265,7 @@ typedef struct GDBRegisterState {
} GDBRegisterState; } GDBRegisterState;
enum RSState { enum RSState {
RS_INACTIVE,
RS_IDLE, RS_IDLE,
RS_GETLINE, RS_GETLINE,
RS_CHKSUM1, RS_CHKSUM1,
@ -1924,7 +1925,7 @@ static void gdb_vm_state_change(void *opaque, int running, int reason)
int ret; int ret;
if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) || if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) ||
s->state == RS_SYSCALL) s->state == RS_INACTIVE || s->state == RS_SYSCALL)
return; return;
/* disable single step if it was enable */ /* disable single step if it was enable */
@ -2342,36 +2343,50 @@ int gdbserver_start(const char *port)
char gdbstub_port_name[128]; char gdbstub_port_name[128];
int port_num; int port_num;
char *p; char *p;
CharDriverState *chr; CharDriverState *chr = NULL;
CharDriverState *mon_chr;
if (!port || !*port) if (!port || !*port)
return -1; return -1;
if (strcmp(port, "none") != 0) {
port_num = strtol(port, &p, 10);
if (*p == 0) {
/* A numeric value is interpreted as a port number. */
snprintf(gdbstub_port_name, sizeof(gdbstub_port_name),
"tcp::%d,nowait,nodelay,server", port_num);
port = gdbstub_port_name;
}
port_num = strtol(port, &p, 10); chr = qemu_chr_open("gdb", port, NULL);
if (*p == 0) { if (!chr)
/* A numeric value is interpreted as a port number. */ return -1;
snprintf(gdbstub_port_name, sizeof(gdbstub_port_name),
"tcp::%d,nowait,nodelay,server", port_num); qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
port = gdbstub_port_name; gdb_chr_event, NULL);
} }
chr = qemu_chr_open("gdb", port, NULL); s = gdbserver_state;
if (!chr) if (!s) {
return -1; s = qemu_mallocz(sizeof(GDBState));
gdbserver_state = s;
s = qemu_mallocz(sizeof(GDBState)); qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
/* Initialize a monitor terminal for gdb */
mon_chr = qemu_mallocz(sizeof(*mon_chr));
mon_chr->chr_write = gdb_monitor_write;
monitor_init(mon_chr, 0);
} else {
if (s->chr)
qemu_chr_close(s->chr);
mon_chr = s->mon_chr;
memset(s, 0, sizeof(GDBState));
}
s->c_cpu = first_cpu; s->c_cpu = first_cpu;
s->g_cpu = first_cpu; s->g_cpu = first_cpu;
s->chr = chr; s->chr = chr;
gdbserver_state = s; s->state = chr ? RS_IDLE : RS_INACTIVE;
qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, s->mon_chr = mon_chr;
gdb_chr_event, NULL);
qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
/* Initialize a monitor terminal for gdb */
s->mon_chr = qemu_mallocz(sizeof(*s->mon_chr));
s->mon_chr->chr_write = gdb_monitor_write;
monitor_init(s->mon_chr, 0);
return 0; return 0;
} }

View File

@ -577,6 +577,8 @@ static void do_gdbserver(Monitor *mon, const char *port)
if (gdbserver_start(port) < 0) { if (gdbserver_start(port) < 0) {
monitor_printf(mon, "Could not open gdbserver socket on port '%s'\n", monitor_printf(mon, "Could not open gdbserver socket on port '%s'\n",
port); port);
} else if (strcmp(port, "none") == 0) {
monitor_printf(mon, "Disabled gdbserver\n");
} else { } else {
monitor_printf(mon, "Waiting gdb connection on port '%s'\n", port); monitor_printf(mon, "Waiting gdb connection on port '%s'\n", port);
} }