/* Target-vector operations for controlling win32 child processes, for GDB.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company.
#define DEBUG_MEM(x) if (debug_memory) printf_unfiltered x
#define DEBUG_EXCEPT(x) if (debug_exceptions) printf_unfiltered x
-static void win32_stop (void);
+static void win32_stop (ptid_t);
static int win32_win32_thread_alive (ptid_t);
static void win32_kill_inferior (void);
return NULL;
}
-/* Add a thread to the thread list */
+/* Add a thread to the thread list. */
static thread_info *
-win32_add_thread (DWORD id, HANDLE h)
+win32_add_thread (ptid_t ptid, HANDLE h)
{
thread_info *th;
+ DWORD id;
+
+ gdb_assert (ptid_get_tid (ptid) != 0);
+
+ id = ptid_get_tid (ptid);
if ((th = thread_rec (id, FALSE)))
return th;
th->h = h;
th->next = thread_head.next;
thread_head.next = th;
- add_thread (pid_to_ptid (id));
- /* Set the debug registers for the new thread in they are used. */
+ add_thread (ptid);
+ /* Set the debug registers for the new thread if they are used. */
if (debug_registers_used)
{
/* Only change the value of the debug registers. */
/* Delete a thread from the list of threads */
static void
-win32_delete_thread (DWORD id)
+win32_delete_thread (ptid_t ptid)
{
thread_info *th;
+ DWORD id;
+
+ gdb_assert (ptid_get_tid (ptid) != 0);
+
+ id = ptid_get_tid (ptid);
if (info_verbose)
- printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id)));
- delete_thread (pid_to_ptid (id));
+ printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
+ delete_thread (ptid);
for (th = &thread_head;
th->next != NULL && th->next->id != id;
do_win32_fetch_inferior_registers (struct regcache *regcache, int r)
{
char *context_offset = ((char *) ¤t_thread->context) + mappings[r];
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
long l;
if (!current_thread)
thread_info *th = current_thread;
th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
GetThreadContext (th->h, &th->context);
- /* Copy dr values from that thread. */
- dr[0] = th->context.Dr0;
- dr[1] = th->context.Dr1;
- dr[2] = th->context.Dr2;
- dr[3] = th->context.Dr3;
- dr[6] = th->context.Dr6;
- dr[7] = th->context.Dr7;
+ /* Copy dr values from that thread.
+ But only if there were not modified since last stop. PR gdb/2388 */
+ if (!debug_registers_changed)
+ {
+ dr[0] = th->context.Dr0;
+ dr[1] = th->context.Dr1;
+ dr[2] = th->context.Dr2;
+ dr[3] = th->context.Dr3;
+ dr[6] = th->context.Dr6;
+ dr[7] = th->context.Dr7;
+ }
}
current_thread->reload_context = 0;
}
-#define I387_ST0_REGNUM I386_ST0_REGNUM
-
- if (r == I387_FISEG_REGNUM)
+ if (r == I387_FISEG_REGNUM (tdep))
{
l = *((long *) context_offset) & 0xffff;
regcache_raw_supply (regcache, r, (char *) &l);
}
- else if (r == I387_FOP_REGNUM)
+ else if (r == I387_FOP_REGNUM (tdep))
{
l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
regcache_raw_supply (regcache, r, (char *) &l);
regcache_raw_supply (regcache, r, context_offset);
else
{
- for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++)
+ for (r = 0; r < gdbarch_num_regs (gdbarch); r++)
do_win32_fetch_inferior_registers (regcache, r);
}
-
-#undef I387_ST0_REGNUM
}
static void
win32_fetch_inferior_registers (struct regcache *regcache, int r)
{
- current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
+ current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
/* Check if current_thread exists. Windows sometimes uses a non-existent
thread id in its events */
if (current_thread)
static void
win32_store_inferior_registers (struct regcache *regcache, int r)
{
- current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
+ current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
/* Check if current_thread exists. Windows sometimes uses a non-existent
thread id in its events */
if (current_thread)
}
static int psapi_loaded = 0;
-static HMODULE psapi_module_handle = NULL;
-static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
-static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
-static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
-
+static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD,
+ LPDWORD);
+static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
+ DWORD);
+static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR,
+ DWORD);
+
+/* Get the name of a given module at at given base address. If base_address
+ is zero return the first loaded module (which is always the name of the
+ executable). */
static int
-psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+get_module_name (DWORD base_address, char *dll_name_ret)
{
DWORD len;
MODULEINFO mi;
int i;
HMODULE dh_buf[1];
- HMODULE *DllHandle = dh_buf;
+ HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */
DWORD cbNeeded;
- BOOL ok;
+#ifdef __CYGWIN__
+ char pathbuf[PATH_MAX + 1]; /* Temporary storage prior to converting to
+ posix form */
+#else
+ char *pathbuf = dll_name_ret; /* Just copy directly to passed-in arg */
+#endif
- if (!psapi_loaded ||
- psapi_EnumProcessModules == NULL ||
- psapi_GetModuleInformation == NULL ||
- psapi_GetModuleFileNameExA == NULL)
- {
- if (psapi_loaded)
- goto failed;
- psapi_loaded = 1;
- psapi_module_handle = LoadLibrary ("psapi.dll");
- if (!psapi_module_handle)
- {
- /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
- goto failed;
- }
- psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
- psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
- psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
- "GetModuleFileNameExA");
- if (psapi_EnumProcessModules == NULL ||
- psapi_GetModuleInformation == NULL ||
- psapi_GetModuleFileNameExA == NULL)
- goto failed;
- }
+ /* If psapi_loaded < 0 either psapi.dll is not available or it does not contain
+ the needed functions. */
+ if (psapi_loaded <= 0)
+ goto failed;
cbNeeded = 0;
- ok = (*psapi_EnumProcessModules) (current_process_handle,
- DllHandle,
- sizeof (HMODULE),
- &cbNeeded);
-
- if (!ok || !cbNeeded)
+ /* Find size of buffer needed to handle list of modules loaded in inferior */
+ if (!psapi_EnumProcessModules (current_process_handle, DllHandle,
+ sizeof (HMODULE), &cbNeeded) || !cbNeeded)
goto failed;
+ /* Allocate correct amount of space for module list */
DllHandle = (HMODULE *) alloca (cbNeeded);
if (!DllHandle)
goto failed;
- ok = (*psapi_EnumProcessModules) (current_process_handle,
- DllHandle,
- cbNeeded,
- &cbNeeded);
- if (!ok)
+ /* Get the list of modules */
+ if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
+ &cbNeeded))
goto failed;
for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
{
- if (!(*psapi_GetModuleInformation) (current_process_handle,
- DllHandle[i],
- &mi,
- sizeof (mi)))
+ /* Get information on this module */
+ if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
+ &mi, sizeof (mi)))
error (_("Can't get module info"));
- len = (*psapi_GetModuleFileNameExA) (current_process_handle,
- DllHandle[i],
- dll_name_ret,
- MAX_PATH);
- if (len == 0)
- error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
-
- if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
- return 1;
+ if (!base_address || (DWORD) (mi.lpBaseOfDll) == base_address)
+ {
+ /* Try to find the name of the given module */
+ len = psapi_GetModuleFileNameExA (current_process_handle,
+ DllHandle[i], pathbuf, MAX_PATH);
+ if (len == 0)
+ error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
+#ifdef __CYGWIN__
+ /* Cygwin prefers that the path be in /x/y/z format */
+ cygwin_conv_to_full_posix_path (pathbuf, dll_name_ret);
+#endif
+ return 1; /* success */
+ }
}
failed:
dll_name_ret[0] = '\0';
- return 0;
+ return 0; /* failure */
}
/* Encapsulate the information required in a call to
safe_symbol_file_add_stub (void *argv)
{
#define p ((struct safe_symbol_file_add_args *) argv)
- struct so_list *so = &solib_start;
-
p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
return !!p->ret;
#undef p
asection *text = NULL;
CORE_ADDR text_vma;
- abfd = bfd_openr (name, "pei-i386");
+ abfd = bfd_openr (so->so_name, "pei-i386");
if (!abfd)
return so;
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
- if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
+ if (!get_module_name ((DWORD) event->lpBaseOfDll, dll_buf))
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
dll_name = dll_buf;
solib_end->next = win32_make_so (dll_name, (DWORD) event->lpBaseOfDll);
solib_end = solib_end->next;
+ DEBUG_EVENTS (("gdb: Loading dll \"%s\" at 0x%lx.\n", solib_end->so_name,
+ (DWORD) solib_end->lm_info->load_addr));
+
return 1;
}
so->next = sodel->next;
if (!so->next)
solib_end = so;
+ DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
+
win32_free_so (sodel);
solib_add (NULL, 0, NULL, auto_solib_add);
return 1;
int retval = 0;
if (!target_read_string
- ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
+ ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
+ &s, 1024, 0)
|| !s || !*s)
/* nothing to do */;
else if (strncmp (s, _CYGWIN_SIGNAL_STRING, sizeof (_CYGWIN_SIGNAL_STRING) - 1) != 0)
and will be sent as a cygwin-specific-signal. So, ignore SEGVs if they show up
within the text segment of the DLL itself. */
char *fn;
- bfd_vma addr = (bfd_vma) current_event.u.Exception.ExceptionRecord.ExceptionAddress;
+ bfd_vma addr = (bfd_vma) (uintptr_t) current_event.u.Exception.
+ ExceptionRecord.ExceptionAddress;
if ((!cygwin_exceptions && (addr >= cygwin_load_start && addr < cygwin_load_end))
|| (find_pc_partial_function (addr, &fn, NULL, NULL)
&& strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0))
/* We can not debug anything in that case. */
}
main_thread_id = current_event.dwThreadId;
- current_thread = win32_add_thread (main_thread_id,
+ current_thread = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
current_event.u.CreateThread.hThread);
return main_thread_id;
}
thread_info *th;
DWORD continue_status = DBG_CONTINUE;
- int pid = PIDGET (ptid);
+ /* A specific PTID means `step only this thread id'. */
+ int resume_all = ptid_equal (ptid, minus_one_ptid);
+
+ /* If we're continuing all threads, it's the current inferior that
+ should be handled specially. */
+ if (resume_all)
+ ptid = inferior_ptid;
if (sig != TARGET_SIGNAL_0)
{
last_sig = TARGET_SIGNAL_0;
- DEBUG_EXEC (("gdb: win32_resume (pid=%d, step=%d, sig=%d);\n",
- pid, step, sig));
+ DEBUG_EXEC (("gdb: win32_resume (pid=%d, tid=%ld, step=%d, sig=%d);\n",
+ ptid_get_pid (ptid), ptid_get_tid (ptid), step, sig));
/* Get context for currently selected thread */
- th = thread_rec (current_event.dwThreadId, FALSE);
+ th = thread_rec (ptid_get_tid (inferior_ptid), FALSE);
if (th)
{
if (step)
/* Allow continuing with the same signal that interrupted us.
Otherwise complain. */
- win32_continue (continue_status, pid);
+ if (resume_all)
+ win32_continue (continue_status, -1);
+ else
+ win32_continue (continue_status, ptid_get_tid (ptid));
}
/* Get the next event from the child. Return 1 if the event requires
thread_info *th;
static thread_info dummy_thread_info;
int retval = 0;
- ptid_t ptid = {-1};
last_sig = TARGET_SIGNAL_0;
/* Kludge around a Windows bug where first event is a create
thread event. Caused when attached process does not have
a main thread. */
- retval = ourstatus->value.related_pid = fake_create_process ();
+ retval = fake_create_process ();
if (retval)
saw_create++;
}
break;
}
/* Record the existence of this thread */
- th = win32_add_thread (current_event.dwThreadId,
- current_event.u.CreateThread.hThread);
- if (info_verbose)
- printf_unfiltered ("[New %s]\n",
- target_pid_to_str (
- pid_to_ptid (current_event.dwThreadId)));
retval = current_event.dwThreadId;
+ th = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
+ current_event.u.CreateThread.hThread);
break;
case EXIT_THREAD_DEBUG_EVENT:
"EXIT_THREAD_DEBUG_EVENT"));
if (current_event.dwThreadId != main_thread_id)
{
- win32_delete_thread (current_event.dwThreadId);
+ win32_delete_thread (ptid_build (current_event.dwProcessId, 0,
+ current_event.dwThreadId));
th = &dummy_thread_info;
}
break;
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
if (main_thread_id)
- win32_delete_thread (main_thread_id);
+ win32_delete_thread (ptid_build (current_event.dwProcessId, 0,
+ main_thread_id));
main_thread_id = current_event.dwThreadId;
/* Add the main thread */
- th = win32_add_thread (main_thread_id,
+ th = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
current_event.u.CreateProcessInfo.hThread);
- retval = ourstatus->value.related_pid = current_event.dwThreadId;
+ retval = current_event.dwThreadId;
break;
case EXIT_PROCESS_DEBUG_EVENT:
if (!retval || saw_create != 1)
{
if (continue_status == -1)
- win32_resume (ptid, 0, 1);
+ win32_resume (minus_one_ptid, 0, 1);
else
CHECK (win32_continue (continue_status, -1));
}
else
{
- inferior_ptid = pid_to_ptid (retval);
+ inferior_ptid = ptid_build (current_event.dwProcessId, 0,
+ retval);
current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
}
return retval;
}
-/* Wait for interesting events to occur in the target process. */
+/* Wait for interesting events to occur in the target process. */
static ptid_t
win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
- int pid = PIDGET (ptid);
+ int pid = -1;
target_terminal_ours ();
while (1)
{
- int retval = get_win32_debug_event (pid, ourstatus);
+ int retval;
+
+ /* Ignore CTRL+C signals while waiting for a debug event.
+ FIXME: brobecker/2008-05-20: When the user presses CTRL+C while
+ the inferior is running, both the inferior and GDB receive the
+ associated signal. If the inferior receives the signal first
+ and the delay until GDB receives that signal is sufficiently long,
+ GDB can sometimes receive the SIGINT after we have unblocked
+ the CTRL+C handler. This would lead to the debugger to stop
+ prematurely while handling the new-thread event that comes
+ with the handling of the SIGINT inside the inferior, and then
+ stop again immediately when the user tries to resume the execution
+ in the inferior. This is a classic race, and it would be nice
+ to find a better solution to that problem. But in the meantime,
+ the current approach already greatly mitigate this issue. */
+ SetConsoleCtrlHandler (NULL, TRUE);
+ retval = get_win32_debug_event (pid, ourstatus);
+ SetConsoleCtrlHandler (NULL, FALSE);
+
if (retval)
- return pid_to_ptid (retval);
+ return ptid_build (current_event.dwProcessId, 0, retval);
else
{
int detach = 0;
{
extern int stop_after_trap;
int i;
+ struct thread_info *tp;
last_sig = TARGET_SIGNAL_0;
event_count = 0;
terminal_init_inferior_with_pgrp (pid);
target_terminal_inferior ();
+ stop_soon = STOP_QUIETLY;
while (1)
{
stop_after_trap = 1;
- wait_for_inferior ();
- if (stop_signal != TARGET_SIGNAL_TRAP)
- resume (0, stop_signal);
+ wait_for_inferior (0);
+ tp = inferior_thread ();
+ if (tp->stop_signal != TARGET_SIGNAL_TRAP)
+ resume (0, tp->stop_signal);
else
break;
}
+
+ stop_soon = NO_STOP_QUIETLY;
stop_after_trap = 0;
return;
}
static char *
win32_pid_to_exec_file (int pid)
{
- /* Try to find the process path using the Cygwin internal process list
- pid isn't a valid pid, unfortunately. Use current_event.dwProcessId
- instead. */
-
static char path[MAX_PATH + 1];
- char *path_ptr = NULL;
#ifdef __CYGWIN__
- /* TODO: Also find native Windows processes using CW_GETPINFO_FULL. */
- int cpid;
- struct external_pinfo *pinfo;
-
- cygwin_internal (CW_LOCK_PINFO, 1000);
- for (cpid = 0;
- (pinfo = (struct external_pinfo *)
- cygwin_internal (CW_GETPINFO, cpid | CW_NEXTPID));
- cpid = pinfo->pid)
+ /* Try to find exe name as symlink target of /proc/<pid>/exe */
+ int nchars;
+ char procexe[sizeof ("/proc/4294967295/exe")];
+ sprintf (procexe, "/proc/%u/exe", pid);
+ nchars = readlink (procexe, path, sizeof(path));
+ if (nchars > 0 && nchars < sizeof (path))
{
- if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */
- {
- cygwin_conv_to_full_posix_path (pinfo->progname, path);
- path_ptr = path;
- break;
- }
+ path[nchars] = '\0'; /* Got it */
+ return path;
}
- cygwin_internal (CW_UNLOCK_PINFO);
#endif
- return path_ptr;
+ /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
+ of gdb, or we're trying to debug a non-Cygwin windows executable. */
+ if (!get_module_name (0, path))
+ path[0] = '\0';
+
+ return path;
}
/* Print status information about what we're accessing. */
error (_("Error creating process %s, (error %d)."),
exec_file, (unsigned) GetLastError ());
+ CloseHandle (pi.hThread);
+ CloseHandle (pi.hProcess);
+
if (useshell && shell[0] != '\0')
saw_create = -1;
else
^C on the controlling terminal. */
static void
-win32_stop (void)
+win32_stop (ptid_t ptid)
{
DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
if (write)
{
DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
- len, (DWORD) memaddr));
- if (!WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
+ len, (DWORD) (uintptr_t) memaddr));
+ if (!WriteProcessMemory (current_process_handle,
+ (LPVOID) (uintptr_t) memaddr, our,
len, &done))
done = 0;
- FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
+ FlushInstructionCache (current_process_handle,
+ (LPCVOID) (uintptr_t) memaddr, len);
}
else
{
DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
- len, (DWORD) memaddr));
- if (!ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our,
+ len, (DWORD) (uintptr_t) memaddr));
+ if (!ReadProcessMemory (current_process_handle,
+ (LPCVOID) (uintptr_t) memaddr, our,
len, &done))
done = 0;
}
win32_pid_to_str (ptid_t ptid)
{
static char buf[80];
- int pid = PIDGET (ptid);
- if ((DWORD) pid == current_event.dwProcessId)
- sprintf (buf, "process %d", pid);
- else
- sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
- return buf;
+ if (ptid_get_tid (ptid) != 0)
+ {
+ snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
+ ptid_get_pid (ptid), ptid_get_tid (ptid));
+ return buf;
+ }
+
+ return normal_pid_to_str (ptid);
}
static LONGEST
case TARGET_OBJECT_MEMORY:
if (readbuf)
return (*ops->deprecated_xfer_memory) (offset, readbuf,
- len, 0/*write*/, NULL, ops);
+ len, 0/*read*/, NULL, ops);
if (writebuf)
return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
len, 1/*write*/, NULL, ops);
win32_ops.to_open = win32_open;
win32_ops.to_close = win32_close;
win32_ops.to_attach = win32_attach;
+ win32_ops.to_attach_no_wait = 1;
win32_ops.to_detach = win32_detach;
win32_ops.to_resume = win32_resume;
win32_ops.to_wait = win32_wait;
win32_ops.to_has_stack = 1;
win32_ops.to_has_registers = 1;
win32_ops.to_has_execution = 1;
- win32_ops.to_magic = OPS_MAGIC;
win32_ops.to_pid_to_exec_file = win32_pid_to_exec_file;
+ win32_ops.to_magic = OPS_MAGIC;
}
static void
return dr[6];
}
-/* Determine if the thread referenced by "pid" is alive
+/* Determine if the thread referenced by "ptid" is alive
by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
- it means that the pid has died. Otherwise it is assumed to be alive. */
+ it means that the thread has died. Otherwise it is assumed to be alive. */
static int
win32_win32_thread_alive (ptid_t ptid)
{
- int pid = PIDGET (ptid);
+ int tid;
- return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
+ gdb_assert (ptid_get_tid (ptid) != 0);
+ tid = ptid_get_tid (ptid);
+
+ return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
FALSE : TRUE;
}
}
}
}
+
+void
+_initialize_psapi (void)
+{
+ /* Load optional functions used for retrieving filename information
+ associated with the currently debugged process or its dlls. */
+ if (!psapi_loaded)
+ {
+ HMODULE psapi_module_handle;
+
+ psapi_loaded = -1;
+
+ psapi_module_handle = LoadLibrary ("psapi.dll");
+ if (psapi_module_handle)
+ {
+ psapi_EnumProcessModules = (void *) GetProcAddress (psapi_module_handle, "EnumProcessModules");
+ psapi_GetModuleInformation = (void *) GetProcAddress (psapi_module_handle, "GetModuleInformation");
+ psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle, "GetModuleFileNameExA");
+
+ if (psapi_EnumProcessModules != NULL
+ && psapi_GetModuleInformation != NULL
+ && psapi_GetModuleFileNameExA != NULL)
+ psapi_loaded = 1;
+ }
+ }
+
+ /* This will probably fail on Windows 9x/Me. Let the user know that we're
+ missing some functionality. */
+ if (psapi_loaded < 0)
+ warning(_("cannot automatically find executable file or library to read symbols. Use \"file\" or \"dll\" command to load executable/libraries directly."));
+}