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 | ... | ... |