]> git.proxmox.com Git - qemu.git/commitdiff
Add support for the 'k' (kill) and 'D' (detach) packets (Jason Wessel).
authoredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 17 May 2008 18:58:29 +0000 (18:58 +0000)
committeredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 17 May 2008 18:58:29 +0000 (18:58 +0000)
Implement the 'k' gdbserial packet which kills the qemu instance via
the debugger stub.

Implement the 'D' detach packet for the gdb stub such that you can
disconnect gdb with the "detach" command.  This required implementing
a cpu_breakpoint_remove_all() and a cpu_watchpoint_remove_all()
function to cleanup all the breakpoints and watchpoints prior to
leaving the gdb stub else simulation can stop with no debugger
attached.

On a '?' packet remove all the breakpoints and watchpoints.  This is
considered more of a safety net in case you force killed gdb or it
crashed and you are reconnecting.  The identical behavior exists for
kgdb in the linux kernel.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4478 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-all.h
exec.c
gdbstub.c

index 7e77f7656f62f14e11e59f2be05b6d247d714e47..d71166c352db9d8c1173fdad74682117434edde8 100644 (file)
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -760,8 +760,10 @@ void cpu_reset_interrupt(CPUState *env, int mask);
 
 int cpu_watchpoint_insert(CPUState *env, target_ulong addr);
 int cpu_watchpoint_remove(CPUState *env, target_ulong addr);
+void cpu_watchpoint_remove_all(CPUState *env);
 int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
 int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
+void cpu_breakpoint_remove_all(CPUState *env);
 
 #define SSTEP_ENABLE  0x1  /* Enable simulated HW single stepping */
 #define SSTEP_NOIRQ   0x2  /* Do not use IRQ while single stepping */
diff --git a/exec.c b/exec.c
index ce2d5d9842b721d4a05e9f6b68cb69602f86009c..dc13c9bffeacc16729c4bba451fe56eeabf43a54 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1139,6 +1139,16 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
     return -1;
 }
 
+/* Remove all watchpoints. */
+void cpu_watchpoint_remove_all(CPUState *env) {
+    int i;
+
+    for (i = 0; i < env->nb_watchpoints; i++) {
+        tlb_flush_page(env, env->watchpoint[i].vaddr);
+    }
+    env->nb_watchpoints = 0;
+}
+
 /* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
    breakpoint is reached */
 int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
@@ -1162,6 +1172,17 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
 #endif
 }
 
+/* remove all breakpoints */
+void cpu_breakpoint_remove_all(CPUState *env) {
+#if defined(TARGET_HAS_ICE)
+    int i;
+    for(i = 0; i < env->nb_breakpoints; i++) {
+        breakpoint_invalidate(env, env->breakpoints[i]);
+    }
+    env->nb_breakpoints = 0;
+#endif
+}
+
 /* remove a breakpoint */
 int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
 {
index 9a361e3251639e831e478a79522bfa85d2c09f16..1df598dc67e040cfce38a74f29026577cf2ef603 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -962,6 +962,12 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
         /* TODO: Make this return the correct value for user-mode.  */
         snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);
         put_packet(s, buf);
+        /* Remove all the breakpoints when this query is issued,
+         * because gdb is doing and initial connect and the state
+         * should be cleaned up.
+         */
+        cpu_breakpoint_remove_all(env);
+        cpu_watchpoint_remove_all(env);
         break;
     case 'c':
         if (*p != '\0') {
@@ -985,6 +991,17 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
         }
         gdb_continue(s);
        return RS_IDLE;
+    case 'k':
+        /* Kill the target */
+        fprintf(stderr, "\nQEMU: Terminated via GDBstub\n");
+        exit(0);
+    case 'D':
+        /* Detach packet */
+        cpu_breakpoint_remove_all(env);
+        cpu_watchpoint_remove_all(env);
+        gdb_continue(s);
+        put_packet(s, "OK");
+        break;
     case 's':
         if (*p != '\0') {
             addr = strtoull(p, (char **)&p, 16);