+psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+{
+ DWORD len;
+ MODULEINFO mi;
+ size_t i;
+ HMODULE dh_buf[1];
+ HMODULE *DllHandle = dh_buf;
+ DWORD cbNeeded;
+ BOOL ok;
+
+ if (!load_psapi ())
+ goto failed;
+
+ cbNeeded = 0;
+ ok = (*win32_EnumProcessModules) (current_process_handle,
+ DllHandle,
+ sizeof (HMODULE),
+ &cbNeeded);
+
+ if (!ok || !cbNeeded)
+ goto failed;
+
+ DllHandle = (HMODULE *) alloca (cbNeeded);
+ if (!DllHandle)
+ goto failed;
+
+ ok = (*win32_EnumProcessModules) (current_process_handle,
+ DllHandle,
+ cbNeeded,
+ &cbNeeded);
+ if (!ok)
+ goto failed;
+
+ for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
+ {
+ if (!(*win32_GetModuleInformation) (current_process_handle,
+ DllHandle[i],
+ &mi,
+ sizeof (mi)))
+ {
+ DWORD err = GetLastError ();
+ error ("Can't get module info: (error %d): %s\n",
+ (int) err, strwinerror (err));
+ }
+
+ if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
+ {
+ len = (*win32_GetModuleFileNameExA) (current_process_handle,
+ DllHandle[i],
+ dll_name_ret,
+ MAX_PATH);
+ if (len == 0)
+ {
+ DWORD err = GetLastError ();
+ error ("Error getting dll name: (error %d): %s\n",
+ (int) err, strwinerror (err));
+ }
+ return 1;
+ }
+ }
+
+failed:
+ dll_name_ret[0] = '\0';
+ return 0;
+}
+
+typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
+typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
+typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
+
+static winapi_CreateToolhelp32Snapshot win32_CreateToolhelp32Snapshot;
+static winapi_Module32First win32_Module32First;
+static winapi_Module32Next win32_Module32Next;
+#ifdef _WIN32_WCE
+typedef BOOL (WINAPI *winapi_CloseToolhelp32Snapshot) (HANDLE);
+static winapi_CloseToolhelp32Snapshot win32_CloseToolhelp32Snapshot;
+#endif
+
+static BOOL
+load_toolhelp (void)
+{
+ static int toolhelp_loaded = 0;
+ static HMODULE dll = NULL;
+
+ if (!toolhelp_loaded)
+ {
+ toolhelp_loaded = 1;
+#ifndef _WIN32_WCE
+ dll = GetModuleHandle (_T("KERNEL32.DLL"));
+#else
+ dll = LoadLibrary (L"TOOLHELP.DLL");
+#endif
+ if (!dll)
+ return FALSE;
+
+ win32_CreateToolhelp32Snapshot =
+ GETPROCADDRESS (dll, CreateToolhelp32Snapshot);
+ win32_Module32First = GETPROCADDRESS (dll, Module32First);
+ win32_Module32Next = GETPROCADDRESS (dll, Module32Next);
+#ifdef _WIN32_WCE
+ win32_CloseToolhelp32Snapshot =
+ GETPROCADDRESS (dll, CloseToolhelp32Snapshot);
+#endif
+ }
+
+ return (win32_CreateToolhelp32Snapshot != NULL
+ && win32_Module32First != NULL
+ && win32_Module32Next != NULL
+#ifdef _WIN32_WCE
+ && win32_CloseToolhelp32Snapshot != NULL
+#endif
+ );
+}
+
+static int
+toolhelp_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+{
+ HANDLE snapshot_module;
+ MODULEENTRY32 modEntry = { sizeof (MODULEENTRY32) };
+ int found = 0;
+
+ if (!load_toolhelp ())
+ return 0;
+
+ snapshot_module = win32_CreateToolhelp32Snapshot (TH32CS_SNAPMODULE,
+ current_event.dwProcessId);
+ if (snapshot_module == INVALID_HANDLE_VALUE)
+ return 0;
+
+ /* Ignore the first module, which is the exe. */
+ if (win32_Module32First (snapshot_module, &modEntry))
+ while (win32_Module32Next (snapshot_module, &modEntry))
+ if ((DWORD) modEntry.modBaseAddr == BaseAddress)
+ {
+#ifdef UNICODE
+ wcstombs (dll_name_ret, modEntry.szExePath, MAX_PATH + 1);
+#else
+ strcpy (dll_name_ret, modEntry.szExePath);
+#endif
+ found = 1;
+ break;
+ }
+
+#ifdef _WIN32_WCE
+ win32_CloseToolhelp32Snapshot (snapshot_module);
+#else
+ CloseHandle (snapshot_module);
+#endif
+ return found;
+}
+
+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;
+ DWORD 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 ((DWORD) 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 ((DWORD) event->lpBaseOfDll, dll_buf);
+ }
+
+ dll_name = dll_buf;
+
+ if (*dll_name == '\0')
+ dll_name = get_image_name (current_process_handle,
+ event->lpImageName, event->fUnicode);
+ if (!dll_name)
+ return;
+
+ /* The symbols in a dll are offset by 0x1000, which is the
+ the offset from 0 of the first byte in an image - because
+ of the file header and the section alignment. */
+
+ load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
+ win32_add_one_solib (dll_name, load_addr);
+}
+
+static void
+handle_unload_dll (void)
+{
+ CORE_ADDR load_addr =
+ (CORE_ADDR) (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
+ load_addr += 0x1000;
+ unloaded_dll (NULL, load_addr);
+}
+
+static void