aboutsummaryrefslogtreecommitdiff
path: root/gdbstub.c
diff options
context:
space:
mode:
authoredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-17 22:20:53 +0000
committeredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-17 22:20:53 +0000
commit1f487ee9b8e502c4153f10ce6aa99e1da33df9e9 (patch)
treea71178c55927aa727c4a1d5531cc6c03de85aaff /gdbstub.c
parent976f8eef23eb571b6707d7bdec488f6c6ae4231b (diff)
downloadqemu-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.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/gdbstub.c b/gdbstub.c
index 1df598d..5342474 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -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);