Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Joel Brobecker <brobecker@adacore.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [RFA] nameless LOAD_DLL_DEBUG_EVENT causes ntdll.dll to be missing
Date: Tue, 03 Dec 2013 19:51:00 -0000	[thread overview]
Message-ID: <529E361B.7070807@redhat.com> (raw)
In-Reply-To: <1386070185-8020-1-git-send-email-brobecker@adacore.com>

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 <constraint_error>) 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 <constraint_error>)
>         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 = &current_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


  reply	other threads:[~2013-12-03 19:51 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-03 11:31 Joel Brobecker
2013-12-03 19:51 ` Pedro Alves [this message]
2013-12-03 20:11   ` Eli Zaretskii
2013-12-05 10:54   ` Joel Brobecker
2013-12-05 12:38     ` Pedro Alves
2013-12-09 11:33       ` Joel Brobecker
2013-12-09 17:08         ` Pedro Alves
2013-12-10 10:06           ` pushed: " Joel Brobecker
2013-12-10 10:06             ` Joel Brobecker
2013-12-10 10:56         ` Joel Brobecker
2013-12-10 13:41           ` Pedro Alves
2013-12-10 13:58             ` Pedro Alves
2013-12-12 18:18               ` Joel Brobecker
2013-12-12 18:51                 ` Eli Zaretskii
2013-12-12 19:08                 ` Pedro Alves
2013-12-12 22:06                 ` Tom Tromey
2013-12-13 10:06                   ` Pedro Alves
2013-12-13 11:04                     ` Joel Brobecker
2013-12-13 11:21                       ` Pedro Alves
2013-12-13 19:38                     ` Tom Tromey
2013-12-13 14:17                 ` Joel Brobecker
2013-12-13 14:42                   ` Pedro Alves
2013-12-13 15:45                     ` Joel Brobecker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=529E361B.7070807@redhat.com \
    --to=palves@redhat.com \
    --cc=brobecker@adacore.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox