Commit 858693c63813f91ee3a0140bf3dfe5a069070eea

Authored by bellard
1 parent 9b14bb04

moved gdbstub to qemu - new asynchronous gdbstub


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@686 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -166,7 +166,7 @@ SRCS:= $(OBJS:.o=.c) @@ -166,7 +166,7 @@ SRCS:= $(OBJS:.o=.c)
166 OBJS+= libqemu.a 166 OBJS+= libqemu.a
167 167
168 # cpu emulator library 168 # cpu emulator library
169 -LIBOBJS=exec.o translate-all.o cpu-exec.o gdbstub.o \ 169 +LIBOBJS=exec.o translate-all.o cpu-exec.o\
170 translate.o op.o 170 translate.o op.o
171 171
172 ifeq ($(TARGET_ARCH), i386) 172 ifeq ($(TARGET_ARCH), i386)
@@ -219,7 +219,7 @@ ifeq ($(ARCH),alpha) @@ -219,7 +219,7 @@ ifeq ($(ARCH),alpha)
219 endif 219 endif
220 220
221 # must use static linking to avoid leaving stuff in virtual address space 221 # must use static linking to avoid leaving stuff in virtual address space
222 -VL_OBJS=vl.o osdep.o block.o monitor.o \ 222 +VL_OBJS=vl.o osdep.o block.o monitor.o gdbstub.o \
223 ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \ 223 ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
224 fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o 224 fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
225 ifeq ($(TARGET_ARCH), ppc) 225 ifeq ($(TARGET_ARCH), ppc)
cpu-all.h
@@ -611,8 +611,6 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size); @@ -611,8 +611,6 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
611 611
612 #endif /* SINGLE_CPU_DEFINES */ 612 #endif /* SINGLE_CPU_DEFINES */
613 613
614 -#define DEFAULT_GDBSTUB_PORT 1234  
615 -  
616 void cpu_abort(CPUState *env, const char *fmt, ...); 614 void cpu_abort(CPUState *env, const char *fmt, ...);
617 extern CPUState *cpu_single_env; 615 extern CPUState *cpu_single_env;
618 extern int code_copy_enabled; 616 extern int code_copy_enabled;
@@ -722,9 +720,4 @@ static inline void cpu_physical_memory_set_dirty(target_ulong addr) @@ -722,9 +720,4 @@ static inline void cpu_physical_memory_set_dirty(target_ulong addr)
722 720
723 void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end); 721 void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end);
724 722
725 -/* gdb stub API */  
726 -extern int gdbstub_fd;  
727 -CPUState *cpu_gdbstub_get_env(void *opaque);  
728 -int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port);  
729 -  
730 #endif /* CPU_ALL_H */ 723 #endif /* CPU_ALL_H */
gdbstub.c
@@ -26,70 +26,36 @@ @@ -26,70 +26,36 @@
26 #include <netinet/in.h> 26 #include <netinet/in.h>
27 #include <netinet/tcp.h> 27 #include <netinet/tcp.h>
28 #include <signal.h> 28 #include <signal.h>
  29 +#include <fcntl.h>
29 30
30 -#include "cpu.h"  
31 -#include "exec-all.h" 31 +#include "vl.h"
32 32
33 //#define DEBUG_GDB 33 //#define DEBUG_GDB
34 34
35 -int gdbstub_fd = -1; 35 +enum RSState {
  36 + RS_IDLE,
  37 + RS_GETLINE,
  38 + RS_CHKSUM1,
  39 + RS_CHKSUM2,
  40 +};
36 41
37 -/* return 0 if OK */  
38 -static int gdbstub_open(int port)  
39 -{  
40 - struct sockaddr_in sockaddr;  
41 - socklen_t len;  
42 - int fd, val, ret; 42 +static int gdbserver_fd;
43 43
44 - fd = socket(PF_INET, SOCK_STREAM, 0);  
45 - if (fd < 0) {  
46 - perror("socket");  
47 - return -1;  
48 - } 44 +typedef struct GDBState {
  45 + enum RSState state;
  46 + int fd;
  47 + char line_buf[4096];
  48 + int line_buf_index;
  49 + int line_csum;
  50 +} GDBState;
49 51
50 - /* allow fast reuse */  
51 - val = 1;  
52 - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));  
53 -  
54 - sockaddr.sin_family = AF_INET;  
55 - sockaddr.sin_port = htons(port);  
56 - sockaddr.sin_addr.s_addr = 0;  
57 - ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));  
58 - if (ret < 0) {  
59 - perror("bind");  
60 - return -1;  
61 - }  
62 - ret = listen(fd, 0);  
63 - if (ret < 0) {  
64 - perror("listen");  
65 - return -1;  
66 - }  
67 -  
68 - /* now wait for one connection */  
69 - for(;;) {  
70 - len = sizeof(sockaddr);  
71 - gdbstub_fd = accept(fd, (struct sockaddr *)&sockaddr, &len);  
72 - if (gdbstub_fd < 0 && errno != EINTR) {  
73 - perror("accept");  
74 - return -1;  
75 - } else if (gdbstub_fd >= 0) {  
76 - break;  
77 - }  
78 - }  
79 -  
80 - /* set short latency */  
81 - val = 1;  
82 - setsockopt(gdbstub_fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));  
83 - return 0;  
84 -}  
85 -  
86 -static int get_char(void) 52 +static int get_char(GDBState *s)
87 { 53 {
88 uint8_t ch; 54 uint8_t ch;
89 int ret; 55 int ret;
90 56
91 for(;;) { 57 for(;;) {
92 - ret = read(gdbstub_fd, &ch, 1); 58 + ret = read(s->fd, &ch, 1);
93 if (ret < 0) { 59 if (ret < 0) {
94 if (errno != EINTR && errno != EAGAIN) 60 if (errno != EINTR && errno != EAGAIN)
95 return -1; 61 return -1;
@@ -102,12 +68,12 @@ static int get_char(void) @@ -102,12 +68,12 @@ static int get_char(void)
102 return ch; 68 return ch;
103 } 69 }
104 70
105 -static void put_buffer(const uint8_t *buf, int len) 71 +static void put_buffer(GDBState *s, const uint8_t *buf, int len)
106 { 72 {
107 int ret; 73 int ret;
108 74
109 while (len > 0) { 75 while (len > 0) {
110 - ret = write(gdbstub_fd, buf, len); 76 + ret = write(s->fd, buf, len);
111 if (ret < 0) { 77 if (ret < 0) {
112 if (errno != EINTR && errno != EAGAIN) 78 if (errno != EINTR && errno != EAGAIN)
113 return; 79 return;
@@ -161,59 +127,8 @@ static void hextomem(uint8_t *mem, const char *buf, int len) @@ -161,59 +127,8 @@ static void hextomem(uint8_t *mem, const char *buf, int len)
161 } 127 }
162 } 128 }
163 129
164 -/* return -1 if error or EOF */  
165 -static int get_packet(char *buf, int buf_size)  
166 -{  
167 - int ch, len, csum, csum1;  
168 - char reply[1];  
169 -  
170 - for(;;) {  
171 - for(;;) {  
172 - ch = get_char();  
173 - if (ch < 0)  
174 - return -1;  
175 - if (ch == '$')  
176 - break;  
177 - }  
178 - len = 0;  
179 - csum = 0;  
180 - for(;;) {  
181 - ch = get_char();  
182 - if (ch < 0)  
183 - return -1;  
184 - if (ch == '#')  
185 - break;  
186 - if (len > buf_size - 1)  
187 - return -1;  
188 - buf[len++] = ch;  
189 - csum += ch;  
190 - }  
191 - buf[len] = '\0';  
192 - ch = get_char();  
193 - if (ch < 0)  
194 - return -1;  
195 - csum1 = fromhex(ch) << 4;  
196 - ch = get_char();  
197 - if (ch < 0)  
198 - return -1;  
199 - csum1 |= fromhex(ch);  
200 - if ((csum & 0xff) != csum1) {  
201 - reply[0] = '-';  
202 - put_buffer(reply, 1);  
203 - } else {  
204 - reply[0] = '+';  
205 - put_buffer(reply, 1);  
206 - break;  
207 - }  
208 - }  
209 -#ifdef DEBUG_GDB  
210 - printf("command='%s'\n", buf);  
211 -#endif  
212 - return len;  
213 -}  
214 -  
215 /* return -1 if error, 0 if OK */ 130 /* return -1 if error, 0 if OK */
216 -static int put_packet(char *buf) 131 +static int put_packet(GDBState *s, char *buf)
217 { 132 {
218 char buf1[3]; 133 char buf1[3];
219 int len, csum, ch, i; 134 int len, csum, ch, i;
@@ -224,9 +139,9 @@ static int put_packet(char *buf) @@ -224,9 +139,9 @@ static int put_packet(char *buf)
224 139
225 for(;;) { 140 for(;;) {
226 buf1[0] = '$'; 141 buf1[0] = '$';
227 - put_buffer(buf1, 1); 142 + put_buffer(s, buf1, 1);
228 len = strlen(buf); 143 len = strlen(buf);
229 - put_buffer(buf, len); 144 + put_buffer(s, buf, len);
230 csum = 0; 145 csum = 0;
231 for(i = 0; i < len; i++) { 146 for(i = 0; i < len; i++) {
232 csum += buf[i]; 147 csum += buf[i];
@@ -235,9 +150,9 @@ static int put_packet(char *buf) @@ -235,9 +150,9 @@ static int put_packet(char *buf)
235 buf1[1] = tohex((csum >> 4) & 0xf); 150 buf1[1] = tohex((csum >> 4) & 0xf);
236 buf1[2] = tohex((csum) & 0xf); 151 buf1[2] = tohex((csum) & 0xf);
237 152
238 - put_buffer(buf1, 3); 153 + put_buffer(s, buf1, 3);
239 154
240 - ch = get_char(); 155 + ch = get_char(s);
241 if (ch < 0) 156 if (ch < 0)
242 return -1; 157 return -1;
243 if (ch == '+') 158 if (ch == '+')
@@ -387,149 +302,293 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) @@ -387,149 +302,293 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
387 #endif 302 #endif
388 303
389 /* port = 0 means default port */ 304 /* port = 0 means default port */
390 -int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) 305 +static int gdb_handle_packet(GDBState *s, const char *line_buf)
391 { 306 {
392 - CPUState *env; 307 + CPUState *env = cpu_single_env;
393 const char *p; 308 const char *p;
394 - int ret, ch, reg_size, type; 309 + int ch, reg_size, type;
395 char buf[4096]; 310 char buf[4096];
396 uint8_t mem_buf[2000]; 311 uint8_t mem_buf[2000];
397 uint32_t *registers; 312 uint32_t *registers;
398 uint32_t addr, len; 313 uint32_t addr, len;
399 314
400 - printf("Waiting gdb connection on port %d\n", port);  
401 - if (gdbstub_open(port) < 0)  
402 - return -1;  
403 - printf("Connected\n");  
404 - for(;;) {  
405 - ret = get_packet(buf, sizeof(buf));  
406 - if (ret < 0)  
407 - break;  
408 - p = buf;  
409 - ch = *p++;  
410 - switch(ch) {  
411 - case '?':  
412 - snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);  
413 - put_packet(buf);  
414 - break;  
415 - case 'c':  
416 - if (*p != '\0') {  
417 - addr = strtoul(p, (char **)&p, 16);  
418 - env = cpu_gdbstub_get_env(opaque); 315 +#ifdef DEBUG_GDB
  316 + printf("command='%s'\n", line_buf);
  317 +#endif
  318 + p = line_buf;
  319 + ch = *p++;
  320 + switch(ch) {
  321 + case '?':
  322 + snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);
  323 + put_packet(s, buf);
  324 + break;
  325 + case 'c':
  326 + if (*p != '\0') {
  327 + addr = strtoul(p, (char **)&p, 16);
419 #if defined(TARGET_I386) 328 #if defined(TARGET_I386)
420 - env->eip = addr; 329 + env->eip = addr;
421 #elif defined (TARGET_PPC) 330 #elif defined (TARGET_PPC)
422 - env->nip = addr; 331 + env->nip = addr;
423 #endif 332 #endif
424 - }  
425 - ret = main_loop(opaque);  
426 - if (ret == EXCP_DEBUG)  
427 - ret = SIGTRAP;  
428 - else  
429 - ret = 0;  
430 - snprintf(buf, sizeof(buf), "S%02x", ret);  
431 - put_packet(buf);  
432 - break;  
433 - case 's':  
434 - env = cpu_gdbstub_get_env(opaque);  
435 - if (*p != '\0') {  
436 - addr = strtoul(p, (char **)&p, 16); 333 + }
  334 + vm_start();
  335 + break;
  336 + case 's':
  337 + if (*p != '\0') {
  338 + addr = strtoul(p, (char **)&p, 16);
437 #if defined(TARGET_I386) 339 #if defined(TARGET_I386)
438 - env->eip = addr; 340 + env->eip = addr;
439 #elif defined (TARGET_PPC) 341 #elif defined (TARGET_PPC)
440 - env->nip = addr; 342 + env->nip = addr;
441 #endif 343 #endif
  344 + }
  345 + cpu_single_step(env, 1);
  346 + vm_start();
  347 + break;
  348 + case 'g':
  349 + reg_size = cpu_gdb_read_registers(env, mem_buf);
  350 + memtohex(buf, mem_buf, reg_size);
  351 + put_packet(s, buf);
  352 + break;
  353 + case 'G':
  354 + registers = (void *)mem_buf;
  355 + len = strlen(p) / 2;
  356 + hextomem((uint8_t *)registers, p, len);
  357 + cpu_gdb_write_registers(env, mem_buf, len);
  358 + put_packet(s, "OK");
  359 + break;
  360 + case 'm':
  361 + addr = strtoul(p, (char **)&p, 16);
  362 + if (*p == ',')
  363 + p++;
  364 + len = strtoul(p, NULL, 16);
  365 + if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0)
  366 + memset(mem_buf, 0, len);
  367 + memtohex(buf, mem_buf, len);
  368 + put_packet(s, buf);
  369 + break;
  370 + case 'M':
  371 + addr = strtoul(p, (char **)&p, 16);
  372 + if (*p == ',')
  373 + p++;
  374 + len = strtoul(p, (char **)&p, 16);
  375 + if (*p == ',')
  376 + p++;
  377 + hextomem(mem_buf, p, len);
  378 + if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0)
  379 + put_packet(s, "ENN");
  380 + else
  381 + put_packet(s, "OK");
  382 + break;
  383 + case 'Z':
  384 + type = strtoul(p, (char **)&p, 16);
  385 + if (*p == ',')
  386 + p++;
  387 + addr = strtoul(p, (char **)&p, 16);
  388 + if (*p == ',')
  389 + p++;
  390 + len = strtoul(p, (char **)&p, 16);
  391 + if (type == 0 || type == 1) {
  392 + if (cpu_breakpoint_insert(env, addr) < 0)
  393 + goto breakpoint_error;
  394 + put_packet(s, "OK");
  395 + } else {
  396 + breakpoint_error:
  397 + put_packet(s, "ENN");
  398 + }
  399 + break;
  400 + case 'z':
  401 + type = strtoul(p, (char **)&p, 16);
  402 + if (*p == ',')
  403 + p++;
  404 + addr = strtoul(p, (char **)&p, 16);
  405 + if (*p == ',')
  406 + p++;
  407 + len = strtoul(p, (char **)&p, 16);
  408 + if (type == 0 || type == 1) {
  409 + cpu_breakpoint_remove(env, addr);
  410 + put_packet(s, "OK");
  411 + } else {
  412 + goto breakpoint_error;
  413 + }
  414 + break;
  415 + default:
  416 + // unknown_command:
  417 + /* put empty packet */
  418 + buf[0] = '\0';
  419 + put_packet(s, buf);
  420 + break;
  421 + }
  422 + return RS_IDLE;
  423 +}
  424 +
  425 +static void gdb_vm_stopped(void *opaque, int reason)
  426 +{
  427 + GDBState *s = opaque;
  428 + char buf[256];
  429 + int ret;
  430 +
  431 + /* disable single step if it was enable */
  432 + cpu_single_step(cpu_single_env, 0);
  433 +
  434 + if (reason == EXCP_DEBUG)
  435 + ret = SIGTRAP;
  436 + else
  437 + ret = 0;
  438 + snprintf(buf, sizeof(buf), "S%02x", ret);
  439 + put_packet(s, buf);
  440 +}
  441 +
  442 +static void gdb_read_byte(GDBState *s, int ch)
  443 +{
  444 + int i, csum;
  445 + char reply[1];
  446 +
  447 + if (vm_running) {
  448 + /* when the CPU is running, we cannot do anything except stop
  449 + it when receiving a char */
  450 + vm_stop(EXCP_INTERRUPT);
  451 + } else {
  452 + switch(s->state) {
  453 + case RS_IDLE:
  454 + if (ch == '$') {
  455 + s->line_buf_index = 0;
  456 + s->state = RS_GETLINE;
442 } 457 }
443 - cpu_single_step(env, 1);  
444 - ret = main_loop(opaque);  
445 - cpu_single_step(env, 0);  
446 - if (ret == EXCP_DEBUG)  
447 - ret = SIGTRAP;  
448 - else  
449 - ret = 0;  
450 - snprintf(buf, sizeof(buf), "S%02x", ret);  
451 - put_packet(buf);  
452 - break;  
453 - case 'g':  
454 - env = cpu_gdbstub_get_env(opaque);  
455 - reg_size = cpu_gdb_read_registers(env, mem_buf);  
456 - memtohex(buf, mem_buf, reg_size);  
457 - put_packet(buf);  
458 break; 458 break;
459 - case 'G':  
460 - env = cpu_gdbstub_get_env(opaque);  
461 - registers = (void *)mem_buf;  
462 - len = strlen(p) / 2;  
463 - hextomem((uint8_t *)registers, p, len);  
464 - cpu_gdb_write_registers(env, mem_buf, len);  
465 - put_packet("OK");  
466 - break;  
467 - case 'm':  
468 - env = cpu_gdbstub_get_env(opaque);  
469 - addr = strtoul(p, (char **)&p, 16);  
470 - if (*p == ',')  
471 - p++;  
472 - len = strtoul(p, NULL, 16);  
473 - if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0)  
474 - memset(mem_buf, 0, len);  
475 - memtohex(buf, mem_buf, len);  
476 - put_packet(buf);  
477 - break;  
478 - case 'M':  
479 - env = cpu_gdbstub_get_env(opaque);  
480 - addr = strtoul(p, (char **)&p, 16);  
481 - if (*p == ',')  
482 - p++;  
483 - len = strtoul(p, (char **)&p, 16);  
484 - if (*p == ',')  
485 - p++;  
486 - hextomem(mem_buf, p, len);  
487 - if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0)  
488 - put_packet("ENN");  
489 - else  
490 - put_packet("OK");  
491 - break;  
492 - case 'Z':  
493 - type = strtoul(p, (char **)&p, 16);  
494 - if (*p == ',')  
495 - p++;  
496 - addr = strtoul(p, (char **)&p, 16);  
497 - if (*p == ',')  
498 - p++;  
499 - len = strtoul(p, (char **)&p, 16);  
500 - if (type == 0 || type == 1) {  
501 - env = cpu_gdbstub_get_env(opaque);  
502 - if (cpu_breakpoint_insert(env, addr) < 0)  
503 - goto breakpoint_error;  
504 - put_packet("OK"); 459 + case RS_GETLINE:
  460 + if (ch == '#') {
  461 + s->state = RS_CHKSUM1;
  462 + } else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
  463 + s->state = RS_IDLE;
505 } else { 464 } else {
506 - breakpoint_error:  
507 - put_packet("ENN"); 465 + s->line_buf[s->line_buf_index++] = ch;
508 } 466 }
509 break; 467 break;
510 - case 'z':  
511 - type = strtoul(p, (char **)&p, 16);  
512 - if (*p == ',')  
513 - p++;  
514 - addr = strtoul(p, (char **)&p, 16);  
515 - if (*p == ',')  
516 - p++;  
517 - len = strtoul(p, (char **)&p, 16);  
518 - if (type == 0 || type == 1) {  
519 - env = cpu_gdbstub_get_env(opaque);  
520 - cpu_breakpoint_remove(env, addr);  
521 - put_packet("OK"); 468 + case RS_CHKSUM1:
  469 + s->line_buf[s->line_buf_index] = '\0';
  470 + s->line_csum = fromhex(ch) << 4;
  471 + s->state = RS_CHKSUM2;
  472 + break;
  473 + case RS_CHKSUM2:
  474 + s->line_csum |= fromhex(ch);
  475 + csum = 0;
  476 + for(i = 0; i < s->line_buf_index; i++) {
  477 + csum += s->line_buf[i];
  478 + }
  479 + if (s->line_csum != (csum & 0xff)) {
  480 + reply[0] = '-';
  481 + put_buffer(s, reply, 1);
  482 + s->state = RS_IDLE;
522 } else { 483 } else {
523 - goto breakpoint_error; 484 + reply[0] = '+';
  485 + put_buffer(s, reply, 1);
  486 + s->state = gdb_handle_packet(s, s->line_buf);
524 } 487 }
525 break; 488 break;
526 - default:  
527 - // unknown_command:  
528 - /* put empty packet */  
529 - buf[0] = '\0';  
530 - put_packet(buf); 489 + }
  490 + }
  491 +}
  492 +
  493 +static int gdb_can_read(void *opaque)
  494 +{
  495 + return 256;
  496 +}
  497 +
  498 +static void gdb_read(void *opaque, const uint8_t *buf, int size)
  499 +{
  500 + GDBState *s = opaque;
  501 + int i;
  502 + if (size == 0) {
  503 + /* end of connection */
  504 + qemu_del_vm_stop_handler(gdb_vm_stopped, s);
  505 + qemu_del_fd_read_handler(s->fd);
  506 + qemu_free(s);
  507 + vm_start();
  508 + } else {
  509 + for(i = 0; i < size; i++)
  510 + gdb_read_byte(s, buf[i]);
  511 + }
  512 +}
  513 +
  514 +static void gdb_accept(void *opaque, const uint8_t *buf, int size)
  515 +{
  516 + GDBState *s;
  517 + struct sockaddr_in sockaddr;
  518 + socklen_t len;
  519 + int val, fd;
  520 +
  521 + for(;;) {
  522 + len = sizeof(sockaddr);
  523 + fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len);
  524 + if (fd < 0 && errno != EINTR) {
  525 + perror("accept");
  526 + return;
  527 + } else if (fd >= 0) {
531 break; 528 break;
532 } 529 }
533 } 530 }
  531 +
  532 + /* set short latency */
  533 + val = 1;
  534 + setsockopt(fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
  535 +
  536 + s = qemu_mallocz(sizeof(GDBState));
  537 + if (!s) {
  538 + close(fd);
  539 + return;
  540 + }
  541 + s->fd = fd;
  542 +
  543 + fcntl(fd, F_SETFL, O_NONBLOCK);
  544 +
  545 + /* stop the VM */
  546 + vm_stop(EXCP_INTERRUPT);
  547 +
  548 + /* start handling I/O */
  549 + qemu_add_fd_read_handler(s->fd, gdb_can_read, gdb_read, s);
  550 + /* when the VM is stopped, the following callback is called */
  551 + qemu_add_vm_stop_handler(gdb_vm_stopped, s);
  552 +}
  553 +
  554 +static int gdbserver_open(int port)
  555 +{
  556 + struct sockaddr_in sockaddr;
  557 + int fd, val, ret;
  558 +
  559 + fd = socket(PF_INET, SOCK_STREAM, 0);
  560 + if (fd < 0) {
  561 + perror("socket");
  562 + return -1;
  563 + }
  564 +
  565 + /* allow fast reuse */
  566 + val = 1;
  567 + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
  568 +
  569 + sockaddr.sin_family = AF_INET;
  570 + sockaddr.sin_port = htons(port);
  571 + sockaddr.sin_addr.s_addr = 0;
  572 + ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
  573 + if (ret < 0) {
  574 + perror("bind");
  575 + return -1;
  576 + }
  577 + ret = listen(fd, 0);
  578 + if (ret < 0) {
  579 + perror("listen");
  580 + return -1;
  581 + }
  582 + fcntl(fd, F_SETFL, O_NONBLOCK);
  583 + return fd;
  584 +}
  585 +
  586 +int gdbserver_start(int port)
  587 +{
  588 + gdbserver_fd = gdbserver_open(port);
  589 + if (gdbserver_fd < 0)
  590 + return -1;
  591 + /* accept connections */
  592 + qemu_add_fd_read_handler(gdbserver_fd, NULL, gdb_accept, NULL);
534 return 0; 593 return 0;
535 } 594 }