From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31011 invoked by alias); 3 Dec 2013 19:51:05 -0000 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 Received: (qmail 30959 invoked by uid 89); 3 Dec 2013 19:51:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.3 required=5.0 tests=AWL,BAYES_50,RDNS_NONE,SPF_HELO_PASS,SPF_PASS autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from Unknown (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 03 Dec 2013 19:51:02 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rB3JoqkQ021113 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 3 Dec 2013 14:50:53 -0500 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id rB3Jop9S006511; Tue, 3 Dec 2013 14:50:52 -0500 Message-ID: <529E361B.7070807@redhat.com> Date: Tue, 03 Dec 2013 19:51:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130625 Thunderbird/17.0.7 MIME-Version: 1.0 To: Joel Brobecker CC: gdb-patches@sourceware.org Subject: Re: [RFA] nameless LOAD_DLL_DEBUG_EVENT causes ntdll.dll to be missing References: <1386070185-8020-1-git-send-email-brobecker@adacore.com> In-Reply-To: <1386070185-8020-1-git-send-email-brobecker@adacore.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-SW-Source: 2013-12/txt/msg00096.txt.bz2 On 12/03/2013 11:29 AM, Joel Brobecker wrote: > Hello, > > We observed on Windows 2012 that we were unable to unwind past > exception handlers. For instance, with any Ada program raising > an exception that does not get handled: > > % gnatmake -g a -bargs -shared > % gdb a > (gdb) start > (gdb) catch exception unhandled > Catchpoint 2: unhandled Ada exceptions > (gdb) c > Catchpoint 2, unhandled CONSTRAINT_ERROR at <__gnat_unhandled_exception> ( > e=0x645ff820 ) at s-excdeb.adb:53 > 53 s-excdeb.adb: No such file or directory. > > At this point, we can already see that something went wrong, since > the frame selected by the debugger corresponds to a runtime function > rather than the function in the user code that caused the exception > to be raised (in our case procedure A). > > This is further confirmed by the fact that we are unable to unwind > all the way to procedure A: > > (gdb) bt > #0 <__gnat_unhandled_exception> (e=0x645ff820 ) > at s-excdeb.adb:53 > #1 0x000000006444e9a3 in <__gnat_notify_unhandled_exception> (excep=0x284d20) > at a-exextr.adb:144 > #2 0x00000000645f106a in __gnat_personality_imp () > from C:\[...]\libgnat-7.3.dll > #3 0x000000006144d1b7 in _GCC_specific_handler (ms_exc=0x242fab0, > this_frame=0x242fe60, ms_orig_context=0x242f5c0, ms_disp=0x242ef70, > gcc_per=0x645f0960 <__gnat_personality_imp>) > at ../../../src/libgcc/unwind-seh.c:289 > #4 0x00000000645f1211 in __gnat_personality_seh0 () > from C:\[...]\libgnat-7.3.dll > #5 0x000007fad3879f4d in ?? () > Backtrace stopped: previous frame inner to this frame (corrupt stack?) > > It turns out that the unwinder has been doing its job flawlessly > up until frame #5. The address in frame #5 is correct, but GDB > is not able to associate it with any symbol or unwind record. > > And this is because this address is inside ntdll.dll, and when > we received the LOAD_DLL_DEBUG_EVENT for that DLL, the system > was not able to tell us the name of the library, thus causing us > to silently ignoring the event. Because GDB does not know about > ntdll.dll, it is unable to access the unwind information from it. > And because the function at that address does not use a frame > pointer, the unwinding becomes impossible. > > This patch helps recovering ntdll.dll at the end of the "run/attach" > phase, simply by trying to locate that specific DLL again. Does this happen only on "attach", or also with "run"? I ask because of this: static char * get_image_name (HANDLE h, void *address, int unicode) { ... /* Attempt to read the name of the dll that was detected. This is documented to work only when actively debugging a program. It will not work for attached processes. */ if (address == NULL) return NULL; And it sounds like get_module_name somehow is failing during the startup phase too? Must be, because get_module_name also uses EnumProcessModules. Can you share for the archives what exactly in get_module_name fails (that doesn't fail for other dlls)? > In terms of our medium to long term planning, it seems to me that > we should be able to simplify the code by ignoring LOAD_DLL_DEBUG_EVENT > during the startup phase, and modify windows_ensure_ntdll_loaded > to then detect and report all shared libraries after we've finished > inferior creation. But for a change just before 7.7 branch creation, > I thought it was safest to just handle ntdll.dll specifically. This > is less intrusive, and ntdll is the only DLL affected by the problem > I know so far. EnumProcessModules used to be exported by psapi.dll in older Windows versions (I think prior to Windows 7), I don't think we can assume that API/dll is always around. > + int i; ... > + for (i = 0; i < (int) (cb_needed / sizeof (HMODULE)); i++) Use size_t, and then you don't need the cast. Does gdbserver need this too? I'd almost bet it doesn't, due to the extra fallback on toolhelp (despite the 32 in the toolhelp API names, it works on 64-bit): static void handle_load_dll (void) { LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll; char dll_buf[MAX_PATH + 1]; char *dll_name = NULL; CORE_ADDR load_addr; dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0'; /* Windows does not report the image name of the dlls in the debug event on attaches. We resort to iterating over the list of loaded dlls looking for a match by image base. */ if (!psapi_get_dll_name (event->lpBaseOfDll, dll_buf)) { if (!server_waiting) /* On some versions of Windows and Windows CE, we can't create toolhelp snapshots while the inferior is stopped in a LOAD_DLL_DEBUG_EVENT due to a dll load, but we can while Windows is reporting the already loaded dlls. */ toolhelp_get_dll_name (event->lpBaseOfDll, dll_buf); } -- Pedro Alves