From patchwork Fri Feb 17 16:21:21 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Meador Inge X-Patchwork-Id: 141867 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A126FB6F13 for ; Sat, 18 Feb 2012 03:21:42 +1100 (EST) Received: from localhost ([::1]:49223 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RyQZ1-0007tA-MC for incoming@patchwork.ozlabs.org; Fri, 17 Feb 2012 11:21:39 -0500 Received: from eggs.gnu.org ([140.186.70.92]:59941) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RyQYw-0007q2-3Q for qemu-devel@nongnu.org; Fri, 17 Feb 2012 11:21:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RyQYn-00063o-Fq for qemu-devel@nongnu.org; Fri, 17 Feb 2012 11:21:34 -0500 Received: from relay1.mentorg.com ([192.94.38.131]:57649) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RyQYn-00063d-2A for qemu-devel@nongnu.org; Fri, 17 Feb 2012 11:21:25 -0500 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1RyQYm-0000kj-Gx from meador_inge@mentor.com ; Fri, 17 Feb 2012 08:21:24 -0800 Received: from SVR-ORW-FEM-02.mgc.mentorg.com ([147.34.96.206]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Fri, 17 Feb 2012 08:21:24 -0800 Received: from dhalsim.gateway.2wire.net (147.34.91.1) by svr-orw-fem-02.mgc.mentorg.com (147.34.96.168) with Microsoft SMTP Server id 14.1.289.1; Fri, 17 Feb 2012 08:21:23 -0800 From: Meador Inge To: Date: Fri, 17 Feb 2012 10:21:21 -0600 Message-ID: <1329495681-5187-2-git-send-email-meadori@codesourcery.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1329495681-5187-1-git-send-email-meadori@codesourcery.com> References: <1329495681-5187-1-git-send-email-meadori@codesourcery.com> MIME-Version: 1.0 X-OriginalArrivalTime: 17 Feb 2012 16:21:24.0489 (UTC) FILETIME=[3149B790:01CCED90] X-detected-operating-system: by eggs.gnu.org: Solaris 10 (beta) X-Received-From: 192.94.38.131 Cc: peter.maydell@linaro.org Subject: [Qemu-devel] [PATCH v2 1/1] gdbserver: Don't send a GDB syscall until the system CPU is stopped 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 Fix an issue where the GDB server implementation was sending GDB syscall requests while the system CPU was still running. Syscall requests must be sent while the CPU is stopped otherwise replies from the GDB client might get dropped and the GDB server might be incorrectly transitioned into a 'RUN_STATE_PAUSED' state. Signed-off-by: Meador Inge Reviewed-by: Peter Maydell --- gdbstub.c | 44 ++++++++++++++++++++++++++++---------------- 1 files changed, 28 insertions(+), 16 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 7d470b6..a08532f 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -283,8 +283,7 @@ enum RSState { RS_IDLE, RS_GETLINE, RS_CHKSUM1, - RS_CHKSUM2, - RS_SYSCALL, + RS_CHKSUM2 }; typedef struct GDBState { CPUState *c_cpu; /* current CPU for step/continue ops */ @@ -304,6 +303,8 @@ typedef struct GDBState { CharDriverState *chr; CharDriverState *mon_chr; #endif + char syscall_buf[256]; + gdb_syscall_complete_cb current_syscall_cb; } GDBState; /* By default use no IRQs and no timers while single stepping so as to @@ -346,8 +347,6 @@ static int get_char(GDBState *s) } #endif -static gdb_syscall_complete_cb gdb_current_syscall_cb; - static enum { GDB_SYS_UNKNOWN, GDB_SYS_ENABLED, @@ -2095,8 +2094,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) if (*p == ',') p++; type = *p; - if (gdb_current_syscall_cb) - gdb_current_syscall_cb(s->c_cpu, ret, err); + if (s->current_syscall_cb) { + s->current_syscall_cb(s->c_cpu, ret, err); + s->current_syscall_cb = NULL; + } if (type == 'C') { put_packet(s, "T02"); } else { @@ -2396,7 +2397,12 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) const char *type; int ret; - if (running || s->state == RS_INACTIVE || s->state == RS_SYSCALL) { + if (running || s->state == RS_INACTIVE) { + return; + } + /* Is there a GDB syscall waiting to be sent? */ + if (s->current_syscall_cb) { + put_packet(s, s->syscall_buf); return; } switch (state) { @@ -2466,8 +2472,8 @@ send_packet: void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) { va_list va; - char buf[256]; char *p; + char *p_end; target_ulong addr; uint64_t i64; GDBState *s; @@ -2475,14 +2481,13 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) s = gdbserver_state; if (!s) return; - gdb_current_syscall_cb = cb; - s->state = RS_SYSCALL; + s->current_syscall_cb = cb; #ifndef CONFIG_USER_ONLY vm_stop(RUN_STATE_DEBUG); #endif - s->state = RS_IDLE; va_start(va, fmt); - p = buf; + p = s->syscall_buf; + p_end = &s->syscall_buf[sizeof(s->syscall_buf)]; *(p++) = 'F'; while (*fmt) { if (*fmt == '%') { @@ -2490,17 +2495,17 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) switch (*fmt++) { case 'x': addr = va_arg(va, target_ulong); - p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx, addr); + p += snprintf(p, p_end - p, TARGET_FMT_lx, addr); break; case 'l': if (*(fmt++) != 'x') goto bad_format; i64 = va_arg(va, uint64_t); - p += snprintf(p, &buf[sizeof(buf)] - p, "%" PRIx64, i64); + p += snprintf(p, p_end - p, "%" PRIx64, i64); break; case 's': addr = va_arg(va, target_ulong); - p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx "/%x", + p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x", addr, va_arg(va, int)); break; default: @@ -2515,10 +2520,16 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) } *p = 0; va_end(va); - put_packet(s, buf); #ifdef CONFIG_USER_ONLY + put_packet(s, s->syscall_buf); gdb_handlesig(s->c_cpu, 0); #else + /* In this case wait to send the syscall packet until notification that + the CPU has stopped. This must be done because if the packet is sent + now the reply from the syscall request could be received while the CPU + is still in the running state, which can cause packets to be dropped + and state transition 'T' packets to be sent while the syscall is still + being processed. */ cpu_exit(s->c_cpu); #endif } @@ -2917,6 +2928,7 @@ int gdbserver_start(const char *device) s->chr = chr; s->state = chr ? RS_IDLE : RS_INACTIVE; s->mon_chr = mon_chr; + s->current_syscall_cb = NULL; return 0; }