Commit 8a34a0fb03191770a77026da164f3ad589c61407

Authored by aliguori
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
... ...