From: Jason Wessel Subject: [PATCH] gdbstub: replace singlestep q packets with qRcmd packets At the gdbserial protocol level, using the qRcmd packets allows gdb to use the "monitor" command to access the controls for single stepping behavior. Now you can use a gdb "monitor" command instead of a gdb "maintenance" command. The ability to turn off single stepping entirely was removed because it is not a useful feature. The qemu docs were updated to reflect this change. Signed-off-by: Jason Wessel --- gdbstub.c | 92 +++++++++++++++++++++++++++++++++++++++------------------- qemu-doc.texi | 31 ++++++------------- 2 files changed, 74 insertions(+), 49 deletions(-) --- a/gdbstub.c +++ b/gdbstub.c @@ -205,9 +205,9 @@ static void hextomem(uint8_t *mem, const } /* return -1 if error, 0 if OK */ -static int put_packet(GDBState *s, char *buf) +static int put_packet_hex(GDBState *s, const char *buf, int len, int isHex) { - int len, csum, i; + int csum, i; uint8_t *p; #ifdef DEBUG_GDB @@ -217,13 +217,19 @@ static int put_packet(GDBState *s, char for(;;) { p = s->last_packet; *(p++) = '$'; - len = strlen(buf); - memcpy(p, buf, len); - p += len; + if (isHex) { + p[0] = 'O'; + memtohex(p + 1, buf, len); + len = strlen(p); + } else { + memcpy(p, buf, len); + } + csum = 0; for(i = 0; i < len; i++) { - csum += buf[i]; + csum += p[i]; } + p += len; *(p++) = '#'; *(p++) = tohex((csum >> 4) & 0xf); *(p++) = tohex((csum) & 0xf); @@ -244,6 +250,24 @@ static int put_packet(GDBState *s, char return 0; } +/* return -1 if error, 0 if OK */ +static int put_packet(GDBState *s, const char *buf) { + return put_packet_hex(s, buf, strlen(buf), 0); +} + +static void monitor_output(GDBState *s, const char *msg) +{ + put_packet_hex(s, msg, strlen(msg), 1); +} + +static void monitor_help(GDBState *s) +{ + monitor_output(s, "gdbstub specific monitor commands:\n"); + monitor_output(s, "show -- Show gdbstub Single Stepping variables\n"); + monitor_output(s, "set sirqs <0|1> -- Single Stepping with qemu irq handlers enabled\n"); + monitor_output(s, "set stimers <0|1> -- Single Stepping with qemu timers enabled\n"); +} + #if defined(TARGET_I386) #ifdef TARGET_X86_64 @@ -948,6 +972,37 @@ static void cpu_gdb_write_registers(CPUS #endif +static void gdb_rcmd(GDBState *s, const char *p, char *buf, char *mem_buf) +{ + int len = strlen(p); + + if ((len % 2) != 0) { + put_packet(s, "E01"); + return; + } + hextomem(mem_buf, p, len); + mem_buf[(len >> 1)] = 0; + + if (!strcmp(mem_buf, "show sirqs")) { + sprintf(buf, "sirqs == %i\n", (sstep_flags & SSTEP_NOIRQ) == 0); + monitor_output(s, buf); + } else if (!strcmp(mem_buf, "show stimers")) { + sprintf(buf, "stimers == %i\n", (sstep_flags & SSTEP_NOTIMER) == 0); + monitor_output(s, buf); + } else if (!strcmp(mem_buf, "set sirqs 1")) { + sstep_flags &= ~SSTEP_NOIRQ; + } else if (!strcmp(mem_buf, "set sirqs 0")) { + sstep_flags |= SSTEP_NOIRQ; + } else if (!strcmp(mem_buf, "set stimers 1")) { + sstep_flags &= ~SSTEP_NOTIMER; + } else if (!strcmp(mem_buf, "set stimers 0")) { + sstep_flags |= SSTEP_NOTIMER; + } else if (!strcmp(mem_buf, "help") || !strcmp(mem_buf, "?")) { + monitor_help(s); + } + put_packet(s, "OK"); +} + static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) { const char *p; @@ -1139,29 +1194,8 @@ static int gdb_handle_packet(GDBState *s } break; case 'q': - case 'Q': - /* parse any 'q' packets here */ - if (!strcmp(p,"qemu.sstepbits")) { - /* Query Breakpoint bit definitions */ - sprintf(buf,"ENABLE=%x,NOIRQ=%x,NOTIMER=%x", - SSTEP_ENABLE, - SSTEP_NOIRQ, - SSTEP_NOTIMER); - put_packet(s, buf); - break; - } else if (strncmp(p,"qemu.sstep",10) == 0) { - /* Display or change the sstep_flags */ - p += 10; - if (*p != '=') { - /* Display current setting */ - sprintf(buf,"0x%x", sstep_flags); - put_packet(s, buf); - break; - } - p++; - type = strtoul(p, (char **)&p, 16); - sstep_flags = type; - put_packet(s, "OK"); + if (!strncmp(p, "Rcmd,", 5)) { + gdb_rcmd(s, p + 5, buf, mem_buf); break; } #ifdef CONFIG_LINUX_USER --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -1951,32 +1951,23 @@ Use @code{set architecture i8086} to dum Advanced debugging options: -The default single stepping behavior is step with the IRQs and timer service routines off. It is set this way because when gdb executes a single step it expects to advance beyond the current instruction. With the IRQs and and timer service routines on, a single step might jump into the one of the interrupt or exception vectors instead of executing the current instruction. This means you may hit the same breakpoint a number of times before executing the instruction gdb wants to have executed. Because there are rare circumstances where you want to single step into an interrupt vector the behavior can be controlled from GDB. There are three commands you can query and set the single step behavior: +The default single stepping behavior is to step with the IRQs and timer service routines off. It is set this way because when gdb executes a single step it expects to advance beyond the current instruction. With the IRQs and and timer service routines on, a single step might jump into the one of the interrupt or exception vectors instead of executing the current instruction. This means you may hit the same breakpoint a number of times before executing the instruction gdb wants execute. Because there are rare circumstances where you want to single step into an interrupt vector the behavior can be controlled from GDB. There are several commands you use to query and set the single step behavior while inside gdb: @table @code -@item maintenance packet qqemu.sstepbits +@item monitor show -This will display the MASK bits used to control the single stepping IE: +This will display the values of the single stepping controls IE: @example -(gdb) maintenance packet qqemu.sstepbits -sending: "qqemu.sstepbits" -received: "ENABLE=1,NOIRQ=2,NOTIMER=4" +(gdb) monitor show sirqs +sirqs == 0 +(gdb) monitor show stimers +stimers == 0 @end example -@item maintenance packet qqemu.sstep +@item monitor set sirqs <0|1> -This will display the current value of the mask used when single stepping IE: -@example -(gdb) maintenance packet qqemu.sstep -sending: "qqemu.sstep" -received: "0x7" -@end example -@item maintenance packet Qqemu.sstep=HEX_VALUE +Turn off or on the the irq processing when single stepping, which is defaulted to off. +@item monitor set stimers <0|1> -This will change the single step mask, so if wanted to enable IRQs on the single step, but not timers, you would use: -@example -(gdb) maintenance packet Qqemu.sstep=0x5 -sending: "qemu.sstep=0x5" -received: "OK" -@end example +Turn off or on the the timer processing when single stepping, which is defaulted to off. @end table @node pcsys_os_specific