nameless LOAD_DLL_DEBUG_EVENT causes ntdll.dll to be missing
authorJoel Brobecker <brobecker@adacore.com>
Thu, 12 Dec 2013 17:53:45 +0000 (12:53 -0500)
committerJoel Brobecker <brobecker@adacore.com>
Fri, 13 Dec 2013 15:42:54 +0000 (16:42 +0100)
This is the gdbserver-equivalent of the change made in GDB to handle
the case, in x64 windows version 2012, where the kernel produces
a LOAD_DLL_DEBUG_EVENT where the name of the associated DLL cannot
be determined at that time, and thus has to be processed later.

The visible symptom is that ntdll.dll is missing from the list of
shared libraries known to be mapped by the inferior, with other
side-effects such as failure to unwind through code provided by
that DLL (such as exception handling routines).

gdb/gdbserver/ChangeLog:

* Makefile.in (safe-ctype.o, lbasename.o): New rules.
* configure.srv: Add safe-ctype.o and lbasename.o to srv_tgtobj
for all targets that use win32-low.c.
* win32-low.c (win32_ensure_ntdll_loaded): New function.
(do_initial_child_stuff): Add call to win32_ensure_ntdll_loaded.

gdb/gdbserver/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/configure.srv
gdb/gdbserver/win32-low.c

index 9f8eb9ef378dec5006725fbb7b483a3dc21f5a7c..c73840feae83afe3aae116ca7e96cf329f0ad220 100644 (file)
@@ -1,3 +1,11 @@
+2013-12-13  Joel Brobecker  <brobecker@adacore.com>
+
+       * Makefile.in (safe-ctype.o, lbasename.o): New rules.
+       * configure.srv: Add safe-ctype.o and lbasename.o to srv_tgtobj
+       for all targets that use win32-low.c.
+       * win32-low.c (win32_ensure_ntdll_loaded): New function.
+       (do_initial_child_stuff): Add call to win32_ensure_ntdll_loaded.
+
 2013-12-13  Pedro Alves  <palves@redhat.com>
 
        * target.c (mywait): Set OURSTATUS->KIND to TARGET_WAITKIND_STOPPED
index 641ea17f964154b9833b6650d40b9d4b9c72768c..c8d971b755b42f5d0434a73945e0c6790759902f 100644 (file)
@@ -543,6 +543,12 @@ vasprintf.o: $(srcdir)/../../libiberty/vasprintf.c
 vsnprintf.o: $(srcdir)/../../libiberty/vsnprintf.c
        $(COMPILE) $<
        $(POSTCOMPILE)
+safe-ctype.o: $(srcdir)/../../libiberty/safe-ctype.c
+       $(COMPILE) $<
+       $(POSTCOMPILE)
+lbasename.o: $(srcdir)/../../libiberty/lbasename.c
+       $(COMPILE) $<
+       $(POSTCOMPILE)
 
 aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c
index 32d935aa133159ca449d23d56fba31c489e4799e..f4e61541d33e10a6b258cf4aa8d331be3f41fc4d 100644 (file)
@@ -77,6 +77,7 @@ case "${target}" in
                        ;;
   arm*-*-mingw32ce*)   srv_regobj=reg-arm.o
                        srv_tgtobj="win32-low.o win32-arm-low.o"
+                       srv_tgtobj="${srv_tgtobj} safe-ctype.o lbasename.o"
                        srv_tgtobj="${srv_tgtobj} wincecompat.o"
                        # hostio_last_error implementation is in win32-low.c
                        srv_hostio_err_objs=""
@@ -100,6 +101,7 @@ case "${target}" in
                        ;;
   i[34567]86-*-cygwin*)        srv_regobj="$srv_i386_regobj"
                        srv_tgtobj="i386-low.o win32-low.o win32-i386-low.o"
+                       srv_tgtobj="${srv_tgtobj} safe-ctype.o lbasename.o"
                        srv_xmlfiles="$srv_i386_xmlfiles"
                        ;;
   i[34567]86-*-linux*) srv_regobj="$srv_i386_linux_regobj"
@@ -126,6 +128,7 @@ case "${target}" in
   i[34567]86-*-mingw32ce*)
                        srv_regobj="$srv_i386_regobj"
                        srv_tgtobj="i386-low.o win32-low.o win32-i386-low.o"
+                       srv_tgtobj="${srv_tgtobj} safe-ctype.o lbasename.o"
                        srv_tgtobj="${srv_tgtobj} wincecompat.o"
                        srv_xmlfiles="$srv_i386_xmlfiles"
                        # hostio_last_error implementation is in win32-low.c
@@ -135,6 +138,7 @@ case "${target}" in
                        ;;
   i[34567]86-*-mingw*) srv_regobj="$srv_i386_regobj"
                        srv_tgtobj="i386-low.o win32-low.o win32-i386-low.o"
+                       srv_tgtobj="${srv_tgtobj} safe-ctype.o lbasename.o"
                        srv_xmlfiles="$srv_i386_xmlfiles"
                        srv_mingw=yes
                        ;;
@@ -326,11 +330,13 @@ case "${target}" in
                        ;;
   x86_64-*-mingw*)     srv_regobj="$srv_amd64_regobj"
                        srv_tgtobj="i386-low.o i387-fp.o win32-low.o win32-i386-low.o"
+                       srv_tgtobj="${srv_tgtobj} safe-ctype.o lbasename.o"
                        srv_xmlfiles="$srv_i386_xmlfiles $srv_amd64_xmlfiles"
                        srv_mingw=yes
                        ;;
   x86_64-*-cygwin*)    srv_regobj="$srv_amd64_regobj"
                        srv_tgtobj="i386-low.o i387-fp.o win32-low.o win32-i386-low.o"
+                       srv_tgtobj="${srv_tgtobj} safe-ctype.o lbasename.o"
                        srv_xmlfiles="$srv_i386_xmlfiles"
                        ;;
 
index a4c9e77a0fd7004bb0ed58c7ec593c25fa223b9f..bcc77fbf109c68332939020ca49131cc21514312 100644 (file)
@@ -105,6 +105,9 @@ typedef BOOL (WINAPI *winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
 static ptid_t win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus,
                          int options);
 static void win32_resume (struct thread_resume *resume_info, size_t n);
+#ifndef _WIN32_WCE
+static void win32_ensure_ntdll_loaded (void);
+#endif
 
 /* Get the thread ID from the current selected inferior (the current
    thread).  */
@@ -371,6 +374,10 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
        win32_resume (&resume, 1);
       }
     }
+
+#ifndef _WIN32_WCE
+  win32_ensure_ntdll_loaded ();
+#endif
 }
 
 /* Resume all artificially suspended threads if we are continuing
@@ -1134,6 +1141,86 @@ failed:
   return 0;
 }
 
+#ifndef _WIN32_WCE
+/* On certain versions of Windows, the information about ntdll.dll
+   is not available yet at the time we get the LOAD_DLL_DEBUG_EVENT,
+   thus preventing us from reporting this DLL as an SO. This has been
+   witnessed on Windows 8.1, for instance.  A possible explanation
+   is that ntdll.dll might be mapped before the SO info gets created
+   by the Windows system -- ntdll.dll is the first DLL to be reported
+   via LOAD_DLL_DEBUG_EVENT and other DLLs do not seem to suffer from
+   that problem.
+
+   If we indeed are missing ntdll.dll, this function tries to recover
+   from this issue, after the fact.  Do nothing if we encounter any
+   issue trying to locate that DLL.  */
+
+static void
+win32_ensure_ntdll_loaded (void)
+{
+  struct inferior_list_entry *dll_e;
+  size_t i;
+  HMODULE dh_buf[1];
+  HMODULE *DllHandle = dh_buf;
+  DWORD cbNeeded;
+  BOOL ok;
+
+  for (dll_e = all_dlls.head; dll_e != NULL; dll_e = dll_e->next)
+    {
+      struct dll_info *dll = (struct dll_info *) dll_e;
+
+      if (strcasecmp (lbasename (dll->name), "ntdll.dll") == 0)
+       return;
+    }
+
+  if (!load_psapi ())
+    return;
+
+  cbNeeded = 0;
+  ok = (*win32_EnumProcessModules) (current_process_handle,
+                                   DllHandle,
+                                   sizeof (HMODULE),
+                                   &cbNeeded);
+
+  if (!ok || !cbNeeded)
+    return;
+
+  DllHandle = (HMODULE *) alloca (cbNeeded);
+  if (!DllHandle)
+    return;
+
+  ok = (*win32_EnumProcessModules) (current_process_handle,
+                                   DllHandle,
+                                   cbNeeded,
+                                   &cbNeeded);
+  if (!ok)
+    return;
+
+  for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
+    {
+      MODULEINFO mi;
+      char dll_name[MAX_PATH];
+
+      if (!(*win32_GetModuleInformation) (current_process_handle,
+                                         DllHandle[i],
+                                         &mi,
+                                         sizeof (mi)))
+       continue;
+      if ((*win32_GetModuleFileNameExA) (current_process_handle,
+                                        DllHandle[i],
+                                        dll_name,
+                                        MAX_PATH) == 0)
+       continue;
+      if (strcasecmp (lbasename (dll_name), "ntdll.dll") == 0)
+       {
+         win32_add_one_solib (dll_name,
+                              (CORE_ADDR) (uintptr_t) mi.lpBaseOfDll);
+         return;
+       }
+    }
+}
+#endif
+
 typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
 typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
 typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);