From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 650 invoked by alias); 12 Nov 2007 02:08:06 -0000 Received: (qmail 640 invoked by uid 22791); 12 Nov 2007 02:08:04 -0000 X-Spam-Check-By: sourceware.org Received: from ug-out-1314.google.com (HELO ug-out-1314.google.com) (66.249.92.173) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 12 Nov 2007 02:08:01 +0000 Received: by ug-out-1314.google.com with SMTP id o2so756215uge for ; Sun, 11 Nov 2007 18:08:01 -0800 (PST) Received: by 10.67.26.7 with SMTP id d7mr246949ugj.1194833280822; Sun, 11 Nov 2007 18:08:00 -0800 (PST) Received: from ?192.168.0.4? ( [62.169.107.97]) by mx.google.com with ESMTPS id p34sm3975710ugc.2007.11.11.18.07.57 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 11 Nov 2007 18:07:59 -0800 (PST) Message-ID: <4737B583.6040304@portugalmail.pt> Date: Mon, 12 Nov 2007 02:08:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.8.1.6) Gecko/20070728 Thunderbird/2.0.0.6 Mnenhy/0.7.5.0 MIME-Version: 1.0 To: gdb-patches@sourceware.org, Lerele Subject: [gdbserver/wince] (7/11) Make the new interrupt method actually always work in WinCE Content-Type: multipart/mixed; boundary="------------060904040704000204080905" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-11/txt/msg00220.txt.bz2 This is a multi-part message in MIME format. --------------060904040704000204080905 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2075 Hi, The new method to interrupt the inferior should work on WinCE. Surprisingly, when writing my first version of the interrupt support patch, a few months ago, I noticed that very frequently the inferior would just crash. I could see that I was always stopping inside a kernel call when it crashed. After a few nights of severe head banging, I noticed that I could reproduce it with Microsoft's debugger, by simply touching any register value before resuming. Even if I didn't change the value, that is, I set the same value as what was already in the register, I would get an exact same crash. So, what I can get from this, is that, unfortunatelly, a SuspendThread call doesn't suspend the thread immediatelly. Well, that is actually documented, but what isn't clear from MSDN is that the SuspendThread call actually returns without error in that case. In the case that the thread is still doing something on the kernel side, after the SuspendThread call, the results of calling GetThreadContext will reflect the fact that the thread was still running. To be clear: DWORD suspend_count = SuspendThread (h); (check that is doesn't return with error) GetThreadContext (h, &context); Sleep (1000); GetThreadContext (h, &context); /* may return something different */ Sleep (1000); GetThreadContext (h, &context); /* may return something different */ Sleep (1000); Unfortunatelly, there is no way to know if the thread is finally stopped. Fortunatelly, I found that there is a register key that makes the Microsoft's debugger spit a few interesting logs. And there it was. There is no SetThreadContext call being done when resuming the inferior, unless we force the context to change in the register window. So, what this patch does, is implement the same workaround MSFT's debugger uses. Don't set the context back to the inferior, unless it has been explicitly changed by gdb or gdbserver. Actually, it is a little bit better, as it won't crash if the user sets some register's contents back to what it was when the inferior stopped. Cheers, Pedro Alves --------------060904040704000204080905 Content-Type: text/x-diff; name="set_thread_context_if_changed.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="set_thread_context_if_changed.diff" Content-length: 3639 2007-11-12 Pedro Alves * win32-low.c (win32_get_thread_context) (win32_set_thread_context): New. (thread_rec): Use win32_get_thread_context. (continue_one_thread, win32_resume): Use win32_set_thread_context. * win32-low.h (win32_thread_info) [_WIN32_WCE]: Add `base_context' field. --- gdb/gdbserver/win32-low.c | 39 ++++++++++++++++++++++++++++++++++++--- gdb/gdbserver/win32-low.h | 7 ++++++- 2 files changed, 42 insertions(+), 4 deletions(-) Index: src/gdb/gdbserver/win32-low.c =================================================================== --- src.orig/gdb/gdbserver/win32-low.c 2007-11-11 23:15:54.000000000 +0000 +++ src/gdb/gdbserver/win32-low.c 2007-11-11 23:16:02.000000000 +0000 @@ -100,6 +100,39 @@ current_inferior_tid (void) return th->tid; } +/* Get the thread context of the thread associated with TH. */ + +static void +win32_get_thread_context (win32_thread_info *th) +{ + memset (&th->context, 0, sizeof (CONTEXT)); + (*the_low_target.get_thread_context) (th, ¤t_event); +#ifdef _WIN32_WCE + memcpy (&th->base_context, &th->context, sizeof (CONTEXT)); +#endif +} + +/* Set the thread context of the thread associated with TH. */ + +static void +win32_set_thread_context (win32_thread_info *th) +{ +#ifdef _WIN32_WCE + /* Calling SuspendThread on a thread that is running kernel code + will report that the suspending was successful, but in fact, that + will often not be true. In those cases, the context returned by + GetThreadContext will not be correct by the time the thread + stops, hence we can't set that context back into the thread when + resuming - it will most likelly crash the inferior. + Unfortunately, there is no way to know when the thread will + really stop. To work around it, we'll only write the context + back to the thread when either the user or GDB explicitly change + it between stopping and resuming. */ + if (memcmp (&th->context, &th->base_context, sizeof (CONTEXT)) != 0) +#endif + (*the_low_target.set_thread_context) (th, ¤t_event); +} + /* Find a thread record given a thread id. If GET_CONTEXT is set then also retrieve the context for this thread. */ static win32_thread_info * @@ -127,7 +160,7 @@ thread_rec (DWORD id, int get_context) th->suspended = 1; } - (*the_low_target.get_thread_context) (th, ¤t_event); + win32_get_thread_context (th); } return th; @@ -434,7 +467,7 @@ continue_one_thread (struct inferior_lis { if (th->context.ContextFlags) { - (*the_low_target.set_thread_context) (th, ¤t_event); + win32_set_thread_context (th); th->context.ContextFlags = 0; } @@ -978,7 +1011,7 @@ win32_resume (struct thread_resume *resu "in this configuration.\n"); } - (*the_low_target.set_thread_context) (th, ¤t_event); + win32_set_thread_context (th); th->context.ContextFlags = 0; } } Index: src/gdb/gdbserver/win32-low.h =================================================================== --- src.orig/gdb/gdbserver/win32-low.h 2007-11-11 23:15:40.000000000 +0000 +++ src/gdb/gdbserver/win32-low.h 2007-11-11 23:16:02.000000000 +0000 @@ -31,7 +31,12 @@ typedef struct win32_thread_info /* Non zero if SuspendThread was called on this thread. */ int suspended; - /* The context of the thread. */ +#ifdef _WIN32_WCE + /* The context as retrieved right after suspending the thread. */ + CONTEXT base_context; +#endif + + /* The context of the thread, including any manipulations. */ CONTEXT context; } win32_thread_info; --------------060904040704000204080905--