Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / nat / windows-nat.c
index fa1ae9597e13bcadb54d11a38ef72e04a04f6707..0bb87ec067438c36cbd3b8463881e90d9d9a7489 100644 (file)
@@ -66,7 +66,7 @@ Wow64GetThreadContext_ftype *Wow64GetThreadContext;
 Wow64SetThreadContext_ftype *Wow64SetThreadContext;
 Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
 #endif
-
+GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent;
 
 /* Note that 'debug_events' must be locally defined in the relevant
    functions.  */
@@ -120,7 +120,13 @@ windows_thread_info::resume ()
   suspended = 0;
 }
 
-const char *
+/* Return the name of the DLL referenced by H at ADDRESS.  UNICODE
+   determines what sort of string is read from the inferior.  Returns
+   the name of the DLL, or NULL on error.  If a name is returned, it
+   is stored in a static buffer which is valid until the next call to
+   get_image_name.  */
+
+static const char *
 get_image_name (HANDLE h, void *address, int unicode)
 {
 #ifdef __CYGWIN__
@@ -333,6 +339,168 @@ handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
 #undef DEBUG_EXCEPTION_SIMPLE
 }
 
+/* Iterate over all DLLs currently mapped by our inferior, looking for
+   a DLL which is loaded at LOAD_ADDR.  If found, add the DLL to our
+   list of solibs; otherwise do nothing.  LOAD_ADDR NULL means add all
+   DLLs to the list of solibs; this is used when the inferior finishes
+   its initialization, and all the DLLs it statically depends on are
+   presumed loaded.  */
+
+static void
+windows_add_dll (LPVOID load_addr)
+{
+  HMODULE dummy_hmodule;
+  DWORD cb_needed;
+  HMODULE *hmodules;
+  int i;
+
+#ifdef __x86_64__
+  if (wow64_process)
+    {
+      if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
+                               sizeof (HMODULE), &cb_needed,
+                               LIST_MODULES_32BIT) == 0)
+       return;
+    }
+  else
+#endif
+    {
+      if (EnumProcessModules (current_process_handle, &dummy_hmodule,
+                             sizeof (HMODULE), &cb_needed) == 0)
+       return;
+    }
+
+  if (cb_needed < 1)
+    return;
+
+  hmodules = (HMODULE *) alloca (cb_needed);
+#ifdef __x86_64__
+  if (wow64_process)
+    {
+      if (EnumProcessModulesEx (current_process_handle, hmodules,
+                               cb_needed, &cb_needed,
+                               LIST_MODULES_32BIT) == 0)
+       return;
+    }
+  else
+#endif
+    {
+      if (EnumProcessModules (current_process_handle, hmodules,
+                             cb_needed, &cb_needed) == 0)
+       return;
+    }
+
+  char system_dir[MAX_PATH];
+  char syswow_dir[MAX_PATH];
+  size_t system_dir_len = 0;
+  bool convert_syswow_dir = false;
+#ifdef __x86_64__
+  if (wow64_process)
+#endif
+    {
+      /* This fails on 32bit Windows because it has no SysWOW64 directory,
+        and in this case a path conversion isn't necessary.  */
+      UINT len = GetSystemWow64DirectoryA (syswow_dir, sizeof (syswow_dir));
+      if (len > 0)
+       {
+         /* Check that we have passed a large enough buffer.  */
+         gdb_assert (len < sizeof (syswow_dir));
+
+         len = GetSystemDirectoryA (system_dir, sizeof (system_dir));
+         /* Error check.  */
+         gdb_assert (len != 0);
+         /* Check that we have passed a large enough buffer.  */
+         gdb_assert (len < sizeof (system_dir));
+
+         strcat (system_dir, "\\");
+         strcat (syswow_dir, "\\");
+         system_dir_len = strlen (system_dir);
+
+         convert_syswow_dir = true;
+       }
+
+    }
+  for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
+    {
+      MODULEINFO mi;
+#ifdef __USEWIDE
+      wchar_t dll_name[MAX_PATH];
+      char dll_name_mb[MAX_PATH];
+#else
+      char dll_name[MAX_PATH];
+#endif
+      const char *name;
+      if (GetModuleInformation (current_process_handle, hmodules[i],
+                               &mi, sizeof (mi)) == 0)
+       continue;
+
+      if (GetModuleFileNameEx (current_process_handle, hmodules[i],
+                              dll_name, sizeof (dll_name)) == 0)
+       continue;
+#ifdef __USEWIDE
+      wcstombs (dll_name_mb, dll_name, MAX_PATH);
+      name = dll_name_mb;
+#else
+      name = dll_name;
+#endif
+      /* Convert the DLL path of 32bit processes returned by
+        GetModuleFileNameEx from the 64bit system directory to the
+        32bit syswow64 directory if necessary.  */
+      std::string syswow_dll_path;
+      if (convert_syswow_dir
+         && strncasecmp (name, system_dir, system_dir_len) == 0
+         && strchr (name + system_dir_len, '\\') == nullptr)
+       {
+         syswow_dll_path = syswow_dir;
+         syswow_dll_path += name + system_dir_len;
+         name = syswow_dll_path.c_str();
+       }
+
+      /* Record the DLL if either LOAD_ADDR is NULL or the address
+        at which the DLL was loaded is equal to LOAD_ADDR.  */
+      if (!(load_addr != nullptr && mi.lpBaseOfDll != load_addr))
+       {
+         handle_load_dll (name, mi.lpBaseOfDll);
+         if (load_addr != nullptr)
+           return;
+       }
+    }
+}
+
+/* See nat/windows-nat.h.  */
+
+void
+dll_loaded_event ()
+{
+  gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);
+
+  LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
+  const char *dll_name;
+
+  /* Try getting the DLL name via the lpImageName field of the event.
+     Note that Microsoft documents this fields as strictly optional,
+     in the sense that it might be NULL.  And the first DLL event in
+     particular is explicitly documented as "likely not pass[ed]"
+     (source: MSDN LOAD_DLL_DEBUG_INFO structure).  */
+  dll_name = get_image_name (current_process_handle,
+                            event->lpImageName, event->fUnicode);
+  /* If the DLL name could not be gleaned via lpImageName, try harder
+     by enumerating all the DLLs loaded into the inferior, looking for
+     one that is loaded at base address = lpBaseOfDll. */
+  if (dll_name != nullptr)
+    handle_load_dll (dll_name, event->lpBaseOfDll);
+  else if (event->lpBaseOfDll != nullptr)
+    windows_add_dll (event->lpBaseOfDll);
+}
+
+/* See nat/windows-nat.h.  */
+
+void
+windows_add_all_dlls ()
+{
+  windows_add_dll (nullptr);
+}
+
 /* See nat/windows-nat.h.  */
 
 bool
@@ -469,6 +637,7 @@ initialize_loadable ()
       GPA (hm, Wow64SetThreadContext);
       GPA (hm, Wow64GetThreadSelectorEntry);
 #endif
+      GPA (hm, GenerateConsoleCtrlEvent);
     }
 
   /* Set variables to dummy versions of these processes if the function
This page took 0.061792 seconds and 4 git commands to generate.