From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16806 invoked by alias); 1 Feb 2010 12:33:47 -0000 Received: (qmail 16796 invoked by uid 22791); 1 Feb 2010 12:33:46 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00,SPF_PASS X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 01 Feb 2010 12:33:42 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 094BE2BAB17; Mon, 1 Feb 2010 07:33:41 -0500 (EST) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 4NJ6kjCBq-6O; Mon, 1 Feb 2010 07:33:40 -0500 (EST) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 4D7BD2BAACF; Mon, 1 Feb 2010 07:33:40 -0500 (EST) Received: by joel.gnat.com (Postfix, from userid 1000) id 121DBF59A0; Mon, 1 Feb 2010 16:33:13 +0400 (RET) From: Joel Brobecker To: gdb-patches@sourceware.org Cc: Joel Brobecker Subject: [RFA] gdbserver crash when running 32bits executables on 64bits windows. Date: Mon, 01 Feb 2010 12:33:00 -0000 Message-Id: <1265027586-18928-1-git-send-email-brobecker@adacore.com> 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: 2010-02/txt/msg00011.txt.bz2 From: Joel Brobecker Hello, This crash was observed on Windows64 machines running 32bit executables through gdbserver. In other words, we had on the same machine gdbserver controlling the inferior, and GDB connected to gdbserver with "target remote". The problem turns out to be caused by a spurious unloaded-dll event. These events occur during the startup phase, and they do not correspond to any DLL load event that we might have received earlier. As a result, we crash trying to dereference a NULL dll_info returned by find_inferior. One theory that was floated to explain this is that this may be caused by the WOW64 layer (the layer that interfaces the 32bit and 64bit worlds). Perhaps it is loading/unloading data and/or code as DLL directly from memory? Perhaps a plain kernel bug? We couldn't find much info on this on the web, so it's hard to tell for sure. Since it is possible for us to receive these spurious unload events, we added a check, and returned without further ado when we could not locate the associated DLL. gdbserver/ChangeLog: * inferiors.c (find_inferior): Add function documentation. (unloaded_dll): Handle the case where the unloaded dll has not been previously registered in the dll list. I tested this change on x86_64-linux, using the procedure outlined in the Wiki for doing native gdbserver testing. I also tested this change on x86-windows (XP) and x86_64-windows (Windows 2008 and Windows 7) using the AdaCore testsuite - for x86_64-windows, I used a 32bit port, obviously. OK to apply? Thanks, -- Joel --- gdb/gdbserver/ChangeLog.GNAT | 9 +++++++++ gdb/gdbserver/inferiors.c | 25 ++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c index c1a1881..097326d 100644 --- a/gdb/gdbserver/inferiors.c +++ b/gdb/gdbserver/inferiors.c @@ -249,6 +249,9 @@ remove_thread (struct thread_info *thread) free_one_thread (&thread->entry); } +/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG) + returns non-zero. If no entry is found then return NULL. */ + struct inferior_list_entry * find_inferior (struct inferior_list *list, int (*func) (struct inferior_list_entry *, void *), void *arg) @@ -366,9 +369,25 @@ unloaded_dll (const char *name, CORE_ADDR base_addr) key_dll.base_addr = base_addr; dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll); - remove_inferior (&all_dlls, &dll->entry); - free_one_dll (&dll->entry); - dlls_changed = 1; + + if (dll == NULL) + /* For some inferiors we might get unloaded_dll events without having + a corresponding loaded_dll. In that case, the dll cannot be found + in ALL_DLL, and there is nothing further for us to do. + + This has been observed when running 32bit executables on Windows64 + (i.e. through WOW64, the interface between the 32bits and 64bits + worlds). In that case, the inferior always does some strange + unloading of unnamed dll. */ + return; + else + { + /* DLL has been found so remove the entry and free associated + resources. */ + remove_inferior (&all_dlls, &dll->entry); + free_one_dll (&dll->entry); + dlls_changed = 1; + } } #define clear_list(LIST) \ -- 1.6.3.3