diff options
author | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-17 22:20:53 +0000 |
---|---|---|
committer | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-17 22:20:53 +0000 |
commit | 1f487ee9b8e502c4153f10ce6aa99e1da33df9e9 (patch) | |
tree | a71178c55927aa727c4a1d5531cc6c03de85aaff /gdbstub.c | |
parent | 976f8eef23eb571b6707d7bdec488f6c6ae4231b (diff) | |
download | qemu-1f487ee9b8e502c4153f10ce6aa99e1da33df9e9.zip qemu-1f487ee9b8e502c4153f10ce6aa99e1da33df9e9.tar.gz qemu-1f487ee9b8e502c4153f10ce6aa99e1da33df9e9.tar.bz2 |
Support signal reception in user-mode. Handle when the peer terminates or aborts the connection.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4483 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'gdbstub.c')
-rw-r--r-- | gdbstub.c | 25 |
1 files changed, 19 insertions, 6 deletions
@@ -65,6 +65,7 @@ typedef struct GDBState { int line_csum; uint8_t last_packet[4100]; int last_packet_len; + int signal; #ifdef CONFIG_USER_ONLY int fd; int running_state; @@ -93,9 +94,13 @@ static int get_char(GDBState *s) for(;;) { ret = recv(s->fd, &ch, 1, 0); if (ret < 0) { + if (errno == ECONNRESET) + s->fd = -1; if (errno != EINTR && errno != EAGAIN) return -1; } else if (ret == 0) { + close(s->fd); + s->fd = -1; return -1; } else { break; @@ -991,6 +996,10 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) } gdb_continue(s); return RS_IDLE; + case 'C': + s->signal = strtoul(p, (char **)&p, 16); + gdb_continue(s); + return RS_IDLE; case 'k': /* Kill the target */ fprintf(stderr, "\nQEMU: Terminated via GDBstub\n"); @@ -1364,10 +1373,9 @@ gdb_handlesig (CPUState *env, int sig) char buf[256]; int n; - if (gdbserver_fd < 0) - return sig; - s = &gdbserver_state; + if (gdbserver_fd < 0 || s->fd < 0) + return sig; /* disable single step if it was enabled */ cpu_single_step(env, 0); @@ -1378,6 +1386,10 @@ gdb_handlesig (CPUState *env, int sig) snprintf(buf, sizeof(buf), "S%02x", sig); put_packet(s, buf); } + /* put_packet() might have detected that the peer terminated the + connection. */ + if (s->fd < 0) + return sig; sig = 0; s->state = RS_IDLE; @@ -1398,6 +1410,8 @@ gdb_handlesig (CPUState *env, int sig) return sig; } } + sig = s->signal; + s->signal = 0; return sig; } @@ -1407,10 +1421,9 @@ void gdb_exit(CPUState *env, int code) GDBState *s; char buf[4]; - if (gdbserver_fd < 0) - return; - s = &gdbserver_state; + if (gdbserver_fd < 0 || s->fd < 0) + return; snprintf(buf, sizeof(buf), "W%02x", code); put_packet(s, buf); |