packing update
[qemu] / gdbstub.c
index b8198ee..addff2e 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -30,6 +30,7 @@
 
 #include "qemu.h"
 #else
+#include "monitor.h"
 #include "qemu-char.h"
 #include "sysemu.h"
 #include "gdbstub.h"
@@ -87,7 +88,11 @@ static int gdb_signal_table[] = {
     -1, /* SIGLOST */
     TARGET_SIGUSR1,
     TARGET_SIGUSR2,
+#ifdef TARGET_SIGPWR
     TARGET_SIGPWR,
+#else
+    -1,
+#endif
     -1, /* SIGPOLL */
     -1,
     -1,
@@ -100,6 +105,7 @@ static int gdb_signal_table[] = {
     -1,
     -1,
     -1,
+#ifdef __SIGRTMIN
     __SIGRTMIN + 1,
     __SIGRTMIN + 2,
     __SIGRTMIN + 3,
@@ -206,6 +212,7 @@ static int gdb_signal_table[] = {
     -1,
     -1,
     -1
+#endif
 };
 #else
 /* In system mode we only need SIGINT and SIGTRAP; other signals
@@ -279,6 +286,7 @@ typedef struct GDBState {
     int running_state;
 #else
     CharDriverState *chr;
+    CharDriverState *mon_chr;
 #endif
 } GDBState;
 
@@ -614,7 +622,17 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int i)
 
 #elif defined (TARGET_PPC)
 
+/* Old gdb always expects FP registers.  Newer (xml-aware) gdb only
+   expects whatever the target description contains.  Due to a
+   historical mishap the FP registers appear in between core integer
+   regs and PC, MSR, CR, and so forth.  We hack round this by giving the
+   FP regs zero size when talking to a newer gdb.  */
 #define NUM_CORE_REGS 71
+#if defined (TARGET_PPC64)
+#define GDB_CORE_XML "power64-core.xml"
+#else
+#define GDB_CORE_XML "power-core.xml"
+#endif
 
 static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 {
@@ -623,6 +641,8 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
         GET_REGL(env->gpr[n]);
     } else if (n < 64) {
         /* fprs */
+        if (gdb_has_xml)
+            return 0;
         stfq_p(mem_buf, env->fpr[n-32]);
         return 8;
     } else {
@@ -640,7 +660,12 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
         case 67: GET_REGL(env->lr);
         case 68: GET_REGL(env->ctr);
         case 69: GET_REGL(env->xer);
-        case 70: GET_REG32(0); /* fpscr */
+        case 70:
+            {
+                if (gdb_has_xml)
+                    return 0;
+                GET_REG32(0); /* fpscr */
+            }
         }
     }
     return 0;
@@ -654,6 +679,8 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         return sizeof(target_ulong);
     } else if (n < 64) {
         /* fprs */
+        if (gdb_has_xml)
+            return 0;
         env->fpr[n-32] = ldfq_p(mem_buf);
         return 8;
     } else {
@@ -683,6 +710,8 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
             return sizeof(target_ulong);
         case 70:
             /* fpscr */
+            if (gdb_has_xml)
+                return 0;
             return 4;
         }
     }
@@ -694,7 +723,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
 #define NUM_CORE_REGS 86
 #else
-#define NUM_CORE_REGS 73
+#define NUM_CORE_REGS 72
 #endif
 
 #ifdef TARGET_ABI32
@@ -728,7 +757,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     case 69: GET_REGA(env->npc);
     case 70: GET_REGA(env->fsr);
     case 71: GET_REGA(0); /* csr */
-    case 72: GET_REGA(0);
+    default: GET_REGA(0);
     }
 #else
     if (n < 64) {
@@ -1779,7 +1808,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
                 }
             break;
         }
-#ifdef CONFIG_LINUX_USER
+#ifdef CONFIG_USER_ONLY
         else if (strncmp(p, "Offsets", 7) == 0) {
             TaskState *ts = s->c_cpu->opaque;
 
@@ -1792,7 +1821,22 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             put_packet(s, buf);
             break;
         }
-#endif
+#else /* !CONFIG_USER_ONLY */
+        else if (strncmp(p, "Rcmd,", 5) == 0) {
+            int len = strlen(p + 5);
+
+            if ((len % 2) != 0) {
+                put_packet(s, "E01");
+                break;
+            }
+            hextomem(mem_buf, p + 5, len);
+            len = len / 2;
+            mem_buf[len++] = 0;
+            qemu_chr_read(s->mon_chr, mem_buf, len);
+            put_packet(s, "OK");
+            break;
+        }
+#endif /* !CONFIG_USER_ONLY */
         if (strncmp(p, "Supported", 9) == 0) {
             snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH);
 #ifdef GDB_CORE_XML
@@ -1861,7 +1905,7 @@ void gdb_set_stop_cpu(CPUState *env)
 }
 
 #ifndef CONFIG_USER_ONLY
-static void gdb_vm_stopped(void *opaque, int reason)
+static void gdb_vm_state_change(void *opaque, int running, int reason)
 {
     GDBState *s = gdbserver_state;
     CPUState *env = s->c_cpu;
@@ -1869,7 +1913,8 @@ static void gdb_vm_stopped(void *opaque, int reason)
     const char *type;
     int ret;
 
-    if (s->state == RS_SYSCALL)
+    if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) ||
+        s->state == RS_SYSCALL)
         return;
 
     /* disable single step if it was enable */
@@ -1898,10 +1943,8 @@ static void gdb_vm_stopped(void *opaque, int reason)
         }
        tb_flush(env);
         ret = GDB_SIGNAL_TRAP;
-    } else if (reason == EXCP_INTERRUPT) {
-        ret = GDB_SIGNAL_INT;
     } else {
-        ret = 0;
+        ret = GDB_SIGNAL_INT;
     }
     snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, env->cpu_index+1);
     put_packet(s, buf);
@@ -1969,7 +2012,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
 #ifdef CONFIG_USER_ONLY
     gdb_handlesig(s->c_cpu, 0);
 #else
-    cpu_interrupt(s->c_cpu, CPU_INTERRUPT_EXIT);
+    cpu_exit(s->c_cpu);
 #endif
 }
 
@@ -2163,11 +2206,6 @@ static void gdb_accept(void)
     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
 
     s = qemu_mallocz(sizeof(GDBState));
-    if (!s) {
-        errno = ENOMEM;
-        perror("accept");
-        return;
-    }
 
     memset (s, 0, sizeof (GDBState));
     s->c_cpu = first_cpu;
@@ -2261,6 +2299,35 @@ static void gdb_chr_event(void *opaque, int event)
     }
 }
 
+static void gdb_monitor_output(GDBState *s, const char *msg, int len)
+{
+    char buf[MAX_PACKET_LENGTH];
+
+    buf[0] = 'O';
+    if (len > (MAX_PACKET_LENGTH/2) - 1)
+        len = (MAX_PACKET_LENGTH/2) - 1;
+    memtohex(buf + 1, (uint8_t *)msg, len);
+    put_packet(s, buf);
+}
+
+static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    const char *p = (const char *)buf;
+    int max_sz;
+
+    max_sz = (sizeof(gdbserver_state->last_packet) - 2) / 2;
+    for (;;) {
+        if (len <= max_sz) {
+            gdb_monitor_output(gdbserver_state, p, len);
+            break;
+        }
+        gdb_monitor_output(gdbserver_state, p, max_sz);
+        p += max_sz;
+        len -= max_sz;
+    }
+    return len;
+}
+
 int gdbserver_start(const char *port)
 {
     GDBState *s;
@@ -2280,21 +2347,24 @@ int gdbserver_start(const char *port)
         port = gdbstub_port_name;
     }
 
-    chr = qemu_chr_open("gdb", port);
+    chr = qemu_chr_open("gdb", port, NULL);
     if (!chr)
         return -1;
 
     s = qemu_mallocz(sizeof(GDBState));
-    if (!s) {
-        return -1;
-    }
     s->c_cpu = first_cpu;
     s->g_cpu = first_cpu;
     s->chr = chr;
     gdbserver_state = s;
     qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
                           gdb_chr_event, NULL);
-    qemu_add_vm_stop_handler(gdb_vm_stopped, NULL);
+    qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
+
+    /* Initialize a monitor terminal for gdb */
+    s->mon_chr = qemu_mallocz(sizeof(*s->mon_chr));
+    s->mon_chr->chr_write = gdb_monitor_write;
+    monitor_init(s->mon_chr, 0);
+
     return 0;
 }
 #endif