From patchwork Tue Jul 1 11:23:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 366049 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 650481400AF for ; Tue, 1 Jul 2014 21:23:47 +1000 (EST) Received: from localhost ([::1]:46229 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X1wA5-0000x7-Hy for incoming@patchwork.ozlabs.org; Tue, 01 Jul 2014 07:23:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57887) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X1w9Y-0000Vm-Dw for qemu-devel@nongnu.org; Tue, 01 Jul 2014 07:23:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X1w9Q-00012X-UN for qemu-devel@nongnu.org; Tue, 01 Jul 2014 07:23:12 -0400 Received: from mail.ispras.ru ([83.149.199.45]:33156) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X1w9Q-00012M-I3 for qemu-devel@nongnu.org; Tue, 01 Jul 2014 07:23:04 -0400 Received: from PASHAISP (unknown [80.250.189.177]) by mail.ispras.ru (Postfix) with ESMTPSA id D314C540157 for ; Tue, 1 Jul 2014 15:23:03 +0400 (MSK) From: "Pavel Dovgaluk" To: "'QEMU Developers'" Date: Tue, 1 Jul 2014 15:23:05 +0400 Message-ID: <007b01cf951e$d40ccd40$7c2667c0$@Dovgaluk@ispras.ru> MIME-Version: 1.0 X-Mailer: Microsoft Office Outlook 12.0 Thread-Index: Ac+VHtPH/vE17N06S3ann4Vvo+zvDg== Content-Language: ru X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 83.149.199.45 Subject: [Qemu-devel] [RFC PATCH 07/22] GDB stub for reverse execution X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Adding support of reverse-stepi and reverse-contunue for gdb remote protocol. Signed-off-by: Pavel Dovgalyuk 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