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 | 30 | |
31 | 31 | #include "qemu.h" |
32 | 32 | #else |
33 | +#include "monitor.h" | |
33 | 34 | #include "qemu-char.h" |
34 | 35 | #include "sysemu.h" |
35 | 36 | #include "gdbstub.h" |
... | ... | @@ -285,6 +286,7 @@ typedef struct GDBState { |
285 | 286 | int running_state; |
286 | 287 | #else |
287 | 288 | CharDriverState *chr; |
289 | + CharDriverState *mon_chr; | |
288 | 290 | #endif |
289 | 291 | } GDBState; |
290 | 292 | |
... | ... | @@ -1819,7 +1821,22 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) |
1819 | 1821 | put_packet(s, buf); |
1820 | 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 | 1840 | if (strncmp(p, "Supported", 9) == 0) { |
1824 | 1841 | snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH); |
1825 | 1842 | #ifdef GDB_CORE_XML |
... | ... | @@ -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 | 2331 | int gdbserver_start(const char *port) |
2286 | 2332 | { |
2287 | 2333 | GDBState *s; |
... | ... | @@ -2313,6 +2359,12 @@ int gdbserver_start(const char *port) |
2313 | 2359 | qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, |
2314 | 2360 | gdb_chr_event, NULL); |
2315 | 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 | 2368 | return 0; |
2317 | 2369 | } |
2318 | 2370 | #endif | ... | ... |