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 166 OBJS+= libqemu.a
167 167  
168 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 170 translate.o op.o
171 171  
172 172 ifeq ($(TARGET_ARCH), i386)
... ... @@ -219,7 +219,7 @@ ifeq ($(ARCH),alpha)
219 219 endif
220 220  
221 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 223 ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
224 224 fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
225 225 ifeq ($(TARGET_ARCH), ppc)
... ...
cpu-all.h
... ... @@ -611,8 +611,6 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
611 611  
612 612 #endif /* SINGLE_CPU_DEFINES */
613 613  
614   -#define DEFAULT_GDBSTUB_PORT 1234
615   -
616 614 void cpu_abort(CPUState *env, const char *fmt, ...);
617 615 extern CPUState *cpu_single_env;
618 616 extern int code_copy_enabled;
... ... @@ -722,9 +720,4 @@ static inline void cpu_physical_memory_set_dirty(target_ulong addr)
722 720  
723 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 723 #endif /* CPU_ALL_H */
... ...
gdbstub.c
... ... @@ -26,70 +26,36 @@
26 26 #include <netinet/in.h>
27 27 #include <netinet/tcp.h>
28 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 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 54 uint8_t ch;
89 55 int ret;
90 56  
91 57 for(;;) {
92   - ret = read(gdbstub_fd, &ch, 1);
  58 + ret = read(s->fd, &ch, 1);
93 59 if (ret < 0) {
94 60 if (errno != EINTR && errno != EAGAIN)
95 61 return -1;
... ... @@ -102,12 +68,12 @@ static int get_char(void)
102 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 73 int ret;
108 74  
109 75 while (len > 0) {
110   - ret = write(gdbstub_fd, buf, len);
  76 + ret = write(s->fd, buf, len);
111 77 if (ret < 0) {
112 78 if (errno != EINTR && errno != EAGAIN)
113 79 return;
... ... @@ -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 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 133 char buf1[3];
219 134 int len, csum, ch, i;
... ... @@ -224,9 +139,9 @@ static int put_packet(char *buf)
224 139  
225 140 for(;;) {
226 141 buf1[0] = '$';
227   - put_buffer(buf1, 1);
  142 + put_buffer(s, buf1, 1);
228 143 len = strlen(buf);
229   - put_buffer(buf, len);
  144 + put_buffer(s, buf, len);
230 145 csum = 0;
231 146 for(i = 0; i < len; i++) {
232 147 csum += buf[i];
... ... @@ -235,9 +150,9 @@ static int put_packet(char *buf)
235 150 buf1[1] = tohex((csum >> 4) & 0xf);
236 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 156 if (ch < 0)
242 157 return -1;
243 158 if (ch == '+')
... ... @@ -387,149 +302,293 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
387 302 #endif
388 303  
389 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 308 const char *p;
394   - int ret, ch, reg_size, type;
  309 + int ch, reg_size, type;
395 310 char buf[4096];
396 311 uint8_t mem_buf[2000];
397 312 uint32_t *registers;
398 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 328 #if defined(TARGET_I386)
420   - env->eip = addr;
  329 + env->eip = addr;
421 330 #elif defined (TARGET_PPC)
422   - env->nip = addr;
  331 + env->nip = addr;
423 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 339 #if defined(TARGET_I386)
438   - env->eip = addr;
  340 + env->eip = addr;
439 341 #elif defined (TARGET_PPC)
440   - env->nip = addr;
  342 + env->nip = addr;
441 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 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 464 } else {
506   - breakpoint_error:
507   - put_packet("ENN");
  465 + s->line_buf[s->line_buf_index++] = ch;
508 466 }
509 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 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 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 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 593 return 0;
535 594 }
... ...