qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 07/22] GDB stub for reverse execution


From: Pavel Dovgaluk
Subject: [Qemu-devel] [RFC PATCH 07/22] GDB stub for reverse execution
Date: Tue, 1 Jul 2014 15:23:05 +0400

Adding support of reverse-stepi and reverse-contunue for gdb remote protocol.

Signed-off-by: Pavel Dovgalyuk <address@hidden>
---

diff --git a/gdbstub.c b/gdbstub.c
index 8afe0b7..ca71f38
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -40,6 +40,7 @@
 #include "cpu.h"
 #include "qemu/sockets.h"
 #include "sysemu/kvm.h"
+#include "replay/replay.h"
 
 static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
                                          uint8_t *buf, int len, bool is_write)
@@ -313,6 +314,18 @@ typedef struct GDBState {
  */
 static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER;
 
+/*! Retrieves flags for single step mode. */
+static int get_sstep_flags(void)
+{
+    /* In replay mode all events written into the log should be replayed.
+     * That is why NOIRQ flag is removed in this mode.
+     */
+    if (replay_mode != REPLAY_NONE)
+        return SSTEP_ENABLE /*| SSTEP_NOTIMER*/;
+    else
+        return sstep_flags;
+}
+
 static GDBState *gdbserver_state;
 
 bool gdb_has_xml;
@@ -835,7 +848,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
                     s->c_cpu = cpu;
                 }
                 if (res == 's') {
-                    cpu_single_step(s->c_cpu, sstep_flags);
+                    cpu_single_step(s->c_cpu, get_sstep_flags());
                 }
                 s->signal = res_signal;
                 gdb_continue(s);
@@ -863,9 +876,29 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
             addr = strtoull(p, (char **)&p, 16);
             gdb_set_cpu_pc(s, addr);
         }
-        cpu_single_step(s->c_cpu, sstep_flags);
+        cpu_single_step(s->c_cpu, get_sstep_flags());
         gdb_continue(s);
        return RS_IDLE;
+    case 'b':
+        /* backward debugging commands */
+        if (replay_mode == REPLAY_PLAY
+            && replay_get_play_submode() == REPLAY_PLAY_NORMAL) {
+            switch (*p) {
+            case 's':
+                replay_reverse_step();
+                gdb_continue(s);
+                   return RS_IDLE;
+            case 'c':
+                replay_reverse_continue();
+                gdb_continue(s);
+                   return RS_IDLE;
+            default:
+                goto unknown_command;
+            }
+        } else {
+            put_packet (s, "E22");
+        }
+        goto unknown_command;
     case 'F':
         {
             target_ulong ret;
@@ -912,6 +945,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
             len -= reg_size;
             registers += reg_size;
         }
+        replay_set_play_changed();
         put_packet(s, "OK");
         break;
     case 'm':
@@ -938,6 +972,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
                                    true) != 0) {
             put_packet(s, "E14");
         } else {
+            replay_set_play_changed();
             put_packet(s, "OK");
         }
         break;
@@ -965,6 +1000,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
         reg_size = strlen(p) / 2;
         hextomem(mem_buf, p, reg_size);
         gdb_write_register(s->g_cpu, mem_buf, addr);
+        replay_set_play_changed();
         put_packet(s, "OK");
         break;
     case 'Z':
@@ -1035,18 +1071,23 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
             put_packet(s, buf);
             break;
         } else if (strncmp(p,"qemu.sstep",10) == 0) {
-            /* Display or change the sstep_flags */
-            p += 10;
-            if (*p != '=') {
-                /* Display current setting */
-                snprintf(buf, sizeof(buf), "0x%x", sstep_flags);
-                put_packet(s, buf);
-                break;
+            if (replay_mode == REPLAY_NONE) {
+                /* Display or change the sstep_flags */
+                p += 10;
+                if (*p != '=') {
+                    /* Display current setting */
+                    snprintf(buf, sizeof(buf), "0x%x", sstep_flags);
+                    put_packet(s, buf);
+                    break;
+                }
+                p++;
+                type = strtoul(p, (char **)&p, 16);
+                sstep_flags = type;
+                put_packet(s, "OK");
+            } else {
+                /* Cannot change sstep flags in replay mode */
+                put_packet(s, "E22");
             }
-            p++;
-            type = strtoul(p, (char **)&p, 16);
-            sstep_flags = type;
-            put_packet(s, "OK");
             break;
         } else if (strcmp(p,"C") == 0) {
             /* "Current thread" remains vague in the spec, so always return
@@ -1113,6 +1154,9 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
             if (cc->gdb_core_xml_file != NULL) {
                 pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
             }
+            if (replay_mode == REPLAY_PLAY) {
+                pstrcat(buf, sizeof(buf), ";ReverseStep+;ReverseContinue+");
+            }
             put_packet(s, buf);
             break;
         }
@@ -1174,8 +1218,13 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 
 void gdb_set_stop_cpu(CPUState *cpu)
 {
-    gdbserver_state->c_cpu = cpu;
-    gdbserver_state->g_cpu = cpu;
+    /* DEBUG interrupts are also used by replay module.
+       In some cases gdb is not connected, when replay is used.
+       This check is added to prevent faults in such cases. */
+    if (gdbserver_state) {
+        gdbserver_state->c_cpu = cpu;
+        gdbserver_state->g_cpu = cpu;
+    }
 }
 
 #ifndef CONFIG_USER_ONLY




reply via email to

[Prev in Thread] Current Thread [Next in Thread]