Commit 8a34a0fb03191770a77026da164f3ad589c61407
1 parent
cde76ee1
monitor: Pass-through for gdbstub (Jan Kiszka)
Create a monitor terminal and pass it through the gdbstub. This allows to use gdb's monitor command to access the QEMU monitor. Works for all commands except for non-detached migration and password retrieval (user will receive error messages instead). Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6718 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
53 additions
and
1 deletions
gdbstub.c
| @@ -30,6 +30,7 @@ | @@ -30,6 +30,7 @@ | ||
| 30 | 30 | ||
| 31 | #include "qemu.h" | 31 | #include "qemu.h" |
| 32 | #else | 32 | #else |
| 33 | +#include "monitor.h" | ||
| 33 | #include "qemu-char.h" | 34 | #include "qemu-char.h" |
| 34 | #include "sysemu.h" | 35 | #include "sysemu.h" |
| 35 | #include "gdbstub.h" | 36 | #include "gdbstub.h" |
| @@ -285,6 +286,7 @@ typedef struct GDBState { | @@ -285,6 +286,7 @@ typedef struct GDBState { | ||
| 285 | int running_state; | 286 | int running_state; |
| 286 | #else | 287 | #else |
| 287 | CharDriverState *chr; | 288 | CharDriverState *chr; |
| 289 | + CharDriverState *mon_chr; | ||
| 288 | #endif | 290 | #endif |
| 289 | } GDBState; | 291 | } GDBState; |
| 290 | 292 | ||
| @@ -1819,7 +1821,22 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | @@ -1819,7 +1821,22 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
| 1819 | put_packet(s, buf); | 1821 | put_packet(s, buf); |
| 1820 | break; | 1822 | break; |
| 1821 | } | 1823 | } |
| 1822 | -#endif | 1824 | +#else /* !CONFIG_LINUX_USER */ |
| 1825 | + else if (strncmp(p, "Rcmd,", 5) == 0) { | ||
| 1826 | + int len = strlen(p + 5); | ||
| 1827 | + | ||
| 1828 | + if ((len % 2) != 0) { | ||
| 1829 | + put_packet(s, "E01"); | ||
| 1830 | + break; | ||
| 1831 | + } | ||
| 1832 | + hextomem(mem_buf, p + 5, len); | ||
| 1833 | + len = len / 2; | ||
| 1834 | + mem_buf[len++] = 0; | ||
| 1835 | + qemu_chr_read(s->mon_chr, mem_buf, len); | ||
| 1836 | + put_packet(s, "OK"); | ||
| 1837 | + break; | ||
| 1838 | + } | ||
| 1839 | +#endif /* !CONFIG_LINUX_USER */ | ||
| 1823 | if (strncmp(p, "Supported", 9) == 0) { | 1840 | if (strncmp(p, "Supported", 9) == 0) { |
| 1824 | snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH); | 1841 | snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH); |
| 1825 | #ifdef GDB_CORE_XML | 1842 | #ifdef GDB_CORE_XML |
| @@ -2282,6 +2299,35 @@ static void gdb_chr_event(void *opaque, int event) | @@ -2282,6 +2299,35 @@ static void gdb_chr_event(void *opaque, int event) | ||
| 2282 | } | 2299 | } |
| 2283 | } | 2300 | } |
| 2284 | 2301 | ||
| 2302 | +static void gdb_monitor_output(GDBState *s, const char *msg, int len) | ||
| 2303 | +{ | ||
| 2304 | + char buf[MAX_PACKET_LENGTH]; | ||
| 2305 | + | ||
| 2306 | + buf[0] = 'O'; | ||
| 2307 | + if (len > (MAX_PACKET_LENGTH/2) - 1) | ||
| 2308 | + len = (MAX_PACKET_LENGTH/2) - 1; | ||
| 2309 | + memtohex(buf + 1, (uint8_t *)msg, len); | ||
| 2310 | + put_packet(s, buf); | ||
| 2311 | +} | ||
| 2312 | + | ||
| 2313 | +static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len) | ||
| 2314 | +{ | ||
| 2315 | + const char *p = (const char *)buf; | ||
| 2316 | + int max_sz; | ||
| 2317 | + | ||
| 2318 | + max_sz = (sizeof(gdbserver_state->last_packet) - 2) / 2; | ||
| 2319 | + for (;;) { | ||
| 2320 | + if (len <= max_sz) { | ||
| 2321 | + gdb_monitor_output(gdbserver_state, p, len); | ||
| 2322 | + break; | ||
| 2323 | + } | ||
| 2324 | + gdb_monitor_output(gdbserver_state, p, max_sz); | ||
| 2325 | + p += max_sz; | ||
| 2326 | + len -= max_sz; | ||
| 2327 | + } | ||
| 2328 | + return len; | ||
| 2329 | +} | ||
| 2330 | + | ||
| 2285 | int gdbserver_start(const char *port) | 2331 | int gdbserver_start(const char *port) |
| 2286 | { | 2332 | { |
| 2287 | GDBState *s; | 2333 | GDBState *s; |
| @@ -2313,6 +2359,12 @@ int gdbserver_start(const char *port) | @@ -2313,6 +2359,12 @@ int gdbserver_start(const char *port) | ||
| 2313 | qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, | 2359 | qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, |
| 2314 | gdb_chr_event, NULL); | 2360 | gdb_chr_event, NULL); |
| 2315 | qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL); | 2361 | qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL); |
| 2362 | + | ||
| 2363 | + /* Initialize a monitor terminal for gdb */ | ||
| 2364 | + s->mon_chr = qemu_mallocz(sizeof(*s->mon_chr)); | ||
| 2365 | + s->mon_chr->chr_write = gdb_monitor_write; | ||
| 2366 | + monitor_init(s->mon_chr, 0); | ||
| 2367 | + | ||
| 2316 | return 0; | 2368 | return 0; |
| 2317 | } | 2369 | } |
| 2318 | #endif | 2370 | #endif |