#include "gdbsupport/gdb_tilde_expand.h"
#include "gdbsupport/pathstuff.h"
#include "gdbsupport/gdb_wait.h"
+#include "nat/windows-nat.h"
#define STATUS_WX86_BREAKPOINT 0x4000001F
#define STATUS_WX86_SINGLE_STEP 0x4000001E
+using namespace windows_nat;
+
#define AdjustTokenPrivileges dyn_AdjustTokenPrivileges
#define DebugActiveProcessStop dyn_DebugActiveProcessStop
#define DebugBreakProcess dyn_DebugBreakProcess
static unsigned long cygwin_get_dr6 (void);
static unsigned long cygwin_get_dr7 (void);
-static enum gdb_signal last_sig = GDB_SIGNAL_0;
-/* Set if a signal was received from the debugged process. */
-
-/* Thread information structure used to track information that is
- not available in gdb's thread structure. */
-struct windows_thread_info
- {
- DWORD tid;
- HANDLE h;
- CORE_ADDR thread_local_base;
- char *name;
- int suspended;
- int reload_context;
- union
- {
- CONTEXT context;
-#ifdef __x86_64__
- WOW64_CONTEXT wow64_context;
-#endif
- };
- };
-
static std::vector<windows_thread_info *> thread_list;
-/* The process and thread handles for the above context. */
-
-static DEBUG_EVENT current_event; /* The current debug event from
- WaitForDebugEvent */
-static HANDLE current_process_handle; /* Currently executing process */
-static windows_thread_info *current_thread; /* Info on currently selected thread */
-static EXCEPTION_RECORD siginfo_er; /* Contents of $_siginfo */
-
/* Counts of things. */
static int exception_count = 0;
static int event_count = 0;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
+ bool stopped_by_sw_breakpoint () override
+ {
+ return current_windows_thread->stopped_at_software_breakpoint;
+ }
+
+ bool supports_stopped_by_sw_breakpoint () override
+ {
+ return true;
+ }
+
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
(unsigned) GetLastError ());
}
-/* Find a thread record given a thread id. If GET_CONTEXT is not 0,
- then also retrieve the context for this thread. If GET_CONTEXT is
- negative, then don't suspend the thread. */
-static windows_thread_info *
-thread_rec (DWORD id, int get_context)
+/* See nat/windows-nat.h. */
+
+windows_thread_info *
+windows_nat::thread_rec (ptid_t ptid, thread_disposition_type disposition)
{
for (windows_thread_info *th : thread_list)
- if (th->tid == id)
+ if (th->tid == ptid.lwp ())
{
- if (!th->suspended && get_context)
+ if (!th->suspended)
{
- if (get_context > 0 && id != current_event.dwThreadId)
+ switch (disposition)
{
- if (SuspendThread (th->h) == (DWORD) -1)
- {
- DWORD err = GetLastError ();
-
- /* We get Access Denied (5) when trying to suspend
- threads that Windows started on behalf of the
- debuggee, usually when those threads are just
- about to exit.
- We can get Invalid Handle (6) if the main thread
- has exited. */
- if (err != ERROR_INVALID_HANDLE
- && err != ERROR_ACCESS_DENIED)
- warning (_("SuspendThread (tid=0x%x) failed."
- " (winerr %u)"),
- (unsigned) id, (unsigned) err);
- th->suspended = -1;
- }
- else
- th->suspended = 1;
+ case DONT_INVALIDATE_CONTEXT:
+ /* Nothing. */
+ break;
+ case INVALIDATE_CONTEXT:
+ if (ptid.lwp () != current_event.dwThreadId)
+ th->suspend ();
+ th->reload_context = true;
+ break;
+ case DONT_SUSPEND:
+ th->reload_context = true;
+ th->suspended = -1;
+ break;
}
- else if (get_context < 0)
- th->suspended = -1;
- th->reload_context = 1;
}
return th;
}
windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
{
windows_thread_info *th;
- DWORD id;
- gdb_assert (ptid.tid () != 0);
+ gdb_assert (ptid.lwp () != 0);
- id = ptid.tid ();
-
- if ((th = thread_rec (id, FALSE)))
+ if ((th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
return th;
- th = XCNEW (windows_thread_info);
- th->tid = id;
- th->h = h;
- th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
+ CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
#ifdef __x86_64__
/* For WOW64 processes, this is actually the pointer to the 64bit TIB,
and the 32bit TIB is exactly 2 pages after it. */
if (wow64_process)
- th->thread_local_base += 0x2000;
+ base += 0x2000;
#endif
+ th = new windows_thread_info (ptid.lwp (), h, base);
thread_list.push_back (th);
/* Add this new thread to the list of threads.
init_thread_list ();
for (windows_thread_info *here : thread_list)
- xfree (here);
+ delete here;
thread_list.clear ();
}
{
DWORD id;
- gdb_assert (ptid.tid () != 0);
+ gdb_assert (ptid.lwp () != 0);
- id = ptid.tid ();
+ id = ptid.lwp ();
/* Emit a notification about the thread being deleted.
if (iter != thread_list.end ())
{
- xfree ((*iter)->name);
- xfree (*iter);
+ delete *iter;
thread_list.erase (iter);
}
}
struct gdbarch *gdbarch = regcache->arch ();
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ gdb_assert (!gdbarch_read_pc_p (gdbarch));
+ gdb_assert (gdbarch_pc_regnum (gdbarch) >= 0);
+ gdb_assert (!gdbarch_write_pc_p (gdbarch));
+
if (r == I387_FISEG_REGNUM (tdep))
{
long l = *((long *) context_offset) & 0xffff;
regcache->raw_supply (r, (char *) &l);
}
else
- regcache->raw_supply (r, context_offset);
+ {
+ if (th->stopped_at_software_breakpoint
+ && r == gdbarch_pc_regnum (gdbarch))
+ {
+ int size = register_size (gdbarch, r);
+ if (size == 4)
+ {
+ uint32_t value;
+ memcpy (&value, context_offset, size);
+ value -= gdbarch_decr_pc_after_break (gdbarch);
+ memcpy (context_offset, &value, size);
+ }
+ else
+ {
+ gdb_assert (size == 8);
+ uint64_t value;
+ memcpy (&value, context_offset, size);
+ value -= gdbarch_decr_pc_after_break (gdbarch);
+ memcpy (context_offset, &value, size);
+ }
+ }
+ regcache->raw_supply (r, context_offset);
+ }
}
void
windows_nat_target::fetch_registers (struct regcache *regcache, int r)
{
- DWORD tid = regcache->ptid ().tid ();
- windows_thread_info *th = thread_rec (tid, TRUE);
+ windows_thread_info *th = thread_rec (regcache->ptid (), INVALIDATE_CONTEXT);
/* Check if TH exists. Windows sometimes uses a non-existent
thread id in its events. */
dr[7] = th->context.Dr7;
}
}
- th->reload_context = 0;
+ th->reload_context = false;
}
if (r < 0)
void
windows_nat_target::store_registers (struct regcache *regcache, int r)
{
- DWORD tid = regcache->ptid ().tid ();
- windows_thread_info *th = thread_rec (tid, TRUE);
+ windows_thread_info *th = thread_rec (regcache->ptid (), INVALIDATE_CONTEXT);
/* Check if TH exists. Windows sometimes uses a non-existent
thread id in its events. */
return so;
}
-static char *
-get_image_name (HANDLE h, void *address, int unicode)
-{
-#ifdef __CYGWIN__
- static char buf[__PMAX];
-#else
- static char buf[(2 * __PMAX) + 1];
-#endif
- DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
- char *address_ptr;
- int len = 0;
- char b[2];
- SIZE_T done;
-
- /* 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;
-
- /* See if we could read the address of a string, and that the
- address isn't null. */
- if (!ReadProcessMemory (h, address, &address_ptr,
- sizeof (address_ptr), &done)
- || done != sizeof (address_ptr) || !address_ptr)
- return NULL;
-
- /* Find the length of the string. */
- while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
- && (b[0] != 0 || b[size - 1] != 0) && done == size)
- continue;
-
- if (!unicode)
- ReadProcessMemory (h, address_ptr, buf, len, &done);
- else
- {
- WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
- ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
- &done);
-#ifdef __CYGWIN__
- wcstombs (buf, unicode_address, __PMAX);
-#else
- WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
- 0, 0);
-#endif
- }
-
- return buf;
-}
-
/* Handle a DLL load event, and return 1.
This function assumes that this event did not occur during inferior
handle_load_dll ()
{
LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll;
- char *dll_name;
+ 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,
CloseHandle ((HANDLE) event_id);
}
-/* Handle DEBUG_STRING output from child process.
- Cygwin prepends its messages with a "cygwin:". Interpret this as
- a Cygwin signal. Otherwise just print the string as a warning. */
-static int
-handle_output_debug_string (struct target_waitstatus *ourstatus)
+/* See nat/windows-nat.h. */
+
+int
+windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
{
gdb::unique_xmalloc_ptr<char> s;
int retval = 0;
static void
display_selectors (const char * args, int from_tty)
{
- if (!current_thread)
+ if (!current_windows_thread)
{
puts_filtered ("Impossible to display selectors now.\n");
return;
if (wow64_process)
{
puts_filtered ("Selector $cs\n");
- display_selector (current_thread->h,
- current_thread->wow64_context.SegCs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->wow64_context.SegCs);
puts_filtered ("Selector $ds\n");
- display_selector (current_thread->h,
- current_thread->wow64_context.SegDs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->wow64_context.SegDs);
puts_filtered ("Selector $es\n");
- display_selector (current_thread->h,
- current_thread->wow64_context.SegEs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->wow64_context.SegEs);
puts_filtered ("Selector $ss\n");
- display_selector (current_thread->h,
- current_thread->wow64_context.SegSs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->wow64_context.SegSs);
puts_filtered ("Selector $fs\n");
- display_selector (current_thread->h,
- current_thread->wow64_context.SegFs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->wow64_context.SegFs);
puts_filtered ("Selector $gs\n");
- display_selector (current_thread->h,
- current_thread->wow64_context.SegGs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->wow64_context.SegGs);
}
else
#endif
{
puts_filtered ("Selector $cs\n");
- display_selector (current_thread->h,
- current_thread->context.SegCs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->context.SegCs);
puts_filtered ("Selector $ds\n");
- display_selector (current_thread->h,
- current_thread->context.SegDs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->context.SegDs);
puts_filtered ("Selector $es\n");
- display_selector (current_thread->h,
- current_thread->context.SegEs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->context.SegEs);
puts_filtered ("Selector $ss\n");
- display_selector (current_thread->h,
- current_thread->context.SegSs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->context.SegSs);
puts_filtered ("Selector $fs\n");
- display_selector (current_thread->h,
- current_thread->context.SegFs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->context.SegFs);
puts_filtered ("Selector $gs\n");
- display_selector (current_thread->h,
- current_thread->context.SegGs);
+ display_selector (current_windows_thread->h,
+ current_windows_thread->context.SegGs);
}
}
else
int sel;
sel = parse_and_eval_long (args);
printf_filtered ("Selector \"%s\"\n",args);
- display_selector (current_thread->h, sel);
+ display_selector (current_windows_thread->h, sel);
}
}
ourstatus->kind = TARGET_WAITKIND_STOPPED;
/* Record the context of the current thread. */
- thread_rec (current_event.dwThreadId, -1);
+ thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
+ DONT_SUSPEND);
switch (code)
{
if (named_thread_id == (DWORD) -1)
named_thread_id = current_event.dwThreadId;
- named_thread = thread_rec (named_thread_id, 0);
+ named_thread = thread_rec (ptid_t (current_event.dwProcessId,
+ named_thread_id, 0),
+ DONT_INVALIDATE_CONTEXT);
if (named_thread != NULL)
{
int thread_name_len;
if (thread_name_len > 0)
{
thread_name.get ()[thread_name_len - 1] = '\0';
- xfree (named_thread->name);
- named_thread->name = thread_name.release ();
+ named_thread->name = std::move (thread_name);
}
}
ourstatus->value.sig = GDB_SIGNAL_TRAP;
{
BOOL res;
+ desired_stop_thread_id = id;
+
+ /* If there are pending stops, and we might plausibly hit one of
+ them, we don't want to actually continue the inferior -- we just
+ want to report the stop. In this case, we just pretend to
+ continue. See the comment by the definition of "pending_stops"
+ for details on why this is needed. */
+ for (const auto &item : pending_stops)
+ {
+ if (desired_stop_thread_id == -1
+ || desired_stop_thread_id == item.thread_id)
+ {
+ DEBUG_EVENTS (("windows_continue - pending stop anticipated, "
+ "desired=0x%x, item=0x%x\n",
+ desired_stop_thread_id, item.thread_id));
+ return TRUE;
+ }
+ }
+
DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s);\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
+ (unsigned) last_wait_event.dwProcessId,
+ (unsigned) last_wait_event.dwThreadId,
continue_status == DBG_CONTINUE ?
"DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
for (windows_thread_info *th : thread_list)
- if ((id == -1 || id == (int) th->tid)
- && th->suspended)
+ if (id == -1 || id == (int) th->tid)
{
+ if (!th->suspended)
+ continue;
#ifdef __x86_64__
if (wow64_process)
{
th->context.ContextFlags = 0;
}
}
- if (th->suspended > 0)
- (void) ResumeThread (th->h);
- th->suspended = 0;
+ th->resume ();
+ }
+ else
+ {
+ /* When single-stepping a specific thread, other threads must
+ be suspended. */
+ th->suspend ();
}
- res = ContinueDebugEvent (current_event.dwProcessId,
- current_event.dwThreadId,
+ res = ContinueDebugEvent (last_wait_event.dwProcessId,
+ last_wait_event.dwThreadId,
continue_status);
if (!res)
(unsigned) GetLastError ());
/* We can not debug anything in that case. */
}
- current_thread
- = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
+ current_windows_thread
+ = windows_add_thread (ptid_t (current_event.dwProcessId,
+ current_event.dwThreadId, 0),
current_event.u.CreateThread.hThread,
current_event.u.CreateThread.lpThreadLocalBase,
true /* main_thread_p */);
last_sig = GDB_SIGNAL_0;
DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=0x%x, step=%d, sig=%d);\n",
- ptid.pid (), (unsigned) ptid.tid (), step, sig));
+ ptid.pid (), (unsigned) ptid.lwp (), step, sig));
/* Get context for currently selected thread. */
- th = thread_rec (inferior_ptid.tid (), FALSE);
+ th = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
if (th)
{
#ifdef __x86_64__
if (resume_all)
windows_continue (continue_status, -1, 0);
else
- windows_continue (continue_status, ptid.tid (), 0);
+ windows_continue (continue_status, ptid.lwp (), 0);
}
/* Ctrl-C handler used when the inferior is not run in the same console. The
return TRUE;
}
+/* A wrapper for WaitForDebugEvent that sets "last_wait_event"
+ appropriately. */
+static BOOL
+wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout)
+{
+ BOOL result = WaitForDebugEvent (event, timeout);
+ if (result)
+ last_wait_event = *event;
+ return result;
+}
+
/* Get the next event from the child. Returns a non-zero thread id if the event
requires handling by WFI (or whatever). */
BOOL debug_event;
DWORD continue_status, event_code;
windows_thread_info *th;
- static windows_thread_info dummy_thread_info;
+ static windows_thread_info dummy_thread_info (0, 0, 0);
DWORD thread_id = 0;
+ /* If there is a relevant pending stop, report it now. See the
+ comment by the definition of "pending_stops" for details on why
+ this is needed. */
+ for (auto iter = pending_stops.begin ();
+ iter != pending_stops.end ();
+ ++iter)
+ {
+ if (desired_stop_thread_id == -1
+ || desired_stop_thread_id == iter->thread_id)
+ {
+ thread_id = iter->thread_id;
+ *ourstatus = iter->status;
+ current_event = iter->event;
+
+ inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
+ current_windows_thread = thread_rec (inferior_ptid,
+ INVALIDATE_CONTEXT);
+ current_windows_thread->reload_context = 1;
+
+ DEBUG_EVENTS (("get_windows_debug_event - "
+ "pending stop found in 0x%x (desired=0x%x)\n",
+ thread_id, desired_stop_thread_id));
+
+ pending_stops.erase (iter);
+ return thread_id;
+ }
+ }
+
last_sig = GDB_SIGNAL_0;
- if (!(debug_event = WaitForDebugEvent (¤t_event, 1000)))
+ if (!(debug_event = wait_for_debug_event (¤t_event, 1000)))
goto out;
event_count++;
/* Record the existence of this thread. */
thread_id = current_event.dwThreadId;
th = windows_add_thread
- (ptid_t (current_event.dwProcessId, 0, current_event.dwThreadId),
+ (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
current_event.u.CreateThread.hThread,
current_event.u.CreateThread.lpThreadLocalBase,
false /* main_thread_p */);
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"EXIT_THREAD_DEBUG_EVENT"));
- windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
+ windows_delete_thread (ptid_t (current_event.dwProcessId,
+ current_event.dwThreadId, 0),
current_event.u.ExitThread.dwExitCode,
false /* main_thread_p */);
th = &dummy_thread_info;
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
/* Add the main thread. */
th = windows_add_thread
- (ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
+ (ptid_t (current_event.dwProcessId,
+ current_event.dwThreadId, 0),
current_event.u.CreateProcessInfo.hThread,
current_event.u.CreateProcessInfo.lpThreadLocalBase,
true /* main_thread_p */);
}
else if (saw_create == 1)
{
- windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
+ windows_delete_thread (ptid_t (current_event.dwProcessId,
+ current_event.dwThreadId, 0),
0, true /* main_thread_p */);
DWORD exit_status = current_event.u.ExitProcess.dwExitCode;
/* If the exit status looks like a fatal exception, but we
if (!thread_id || saw_create != 1)
{
- CHECK (windows_continue (continue_status, -1, 0));
+ CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));
+ }
+ else if (desired_stop_thread_id != -1 && desired_stop_thread_id != thread_id)
+ {
+ /* Pending stop. See the comment by the definition of
+ "pending_stops" for details on why this is needed. */
+ DEBUG_EVENTS (("get_windows_debug_event - "
+ "unexpected stop in 0x%x (expecting 0x%x)\n",
+ thread_id, desired_stop_thread_id));
+
+ if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
+ && (current_event.u.Exception.ExceptionRecord.ExceptionCode
+ == EXCEPTION_BREAKPOINT)
+ && windows_initialization_done)
+ {
+ ptid_t ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
+ th = thread_rec (ptid, INVALIDATE_CONTEXT);
+ th->stopped_at_software_breakpoint = true;
+ }
+ pending_stops.push_back ({thread_id, *ourstatus, current_event});
+ thread_id = 0;
+ CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));
}
else
{
- inferior_ptid = ptid_t (current_event.dwProcessId, 0, thread_id);
- current_thread = th;
- if (!current_thread)
- current_thread = thread_rec (thread_id, TRUE);
+ inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
+ current_windows_thread = th;
+ if (!current_windows_thread)
+ current_windows_thread = thread_rec (inferior_ptid,
+ INVALIDATE_CONTEXT);
}
out:
SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
if (retval)
- return ptid_t (current_event.dwProcessId, 0, retval);
+ {
+ ptid_t result = ptid_t (current_event.dwProcessId, retval, 0);
+
+ if (current_windows_thread != nullptr)
+ {
+ current_windows_thread->stopped_at_software_breakpoint = false;
+ if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
+ && (current_event.u.Exception.ExceptionRecord.ExceptionCode
+ == EXCEPTION_BREAKPOINT)
+ && windows_initialization_done)
+ current_windows_thread->stopped_at_software_breakpoint = true;
+ }
+
+ return result;
+ }
else
{
int detach = 0;
{
if (!windows_continue (DBG_CONTINUE, -1, 1))
break;
- if (!WaitForDebugEvent (¤t_event, INFINITE))
+ if (!wait_for_debug_event (¤t_event, INFINITE))
break;
if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
break;
std::string
windows_nat_target::pid_to_str (ptid_t ptid)
{
- if (ptid.tid () != 0)
- return string_printf ("Thread %d.0x%lx", ptid.pid (), ptid.tid ());
+ if (ptid.lwp () != 0)
+ return string_printf ("Thread %d.0x%lx", ptid.pid (), ptid.lwp ());
return normal_pid_to_str (ptid);
}
{
windows_thread_info *th;
- th = thread_rec (ptid.tid (), 0);
+ th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
if (th == NULL)
return false;
ptid_t
windows_nat_target::get_ada_task_ptid (long lwp, long thread)
{
- return ptid_t (inferior_ptid.pid (), 0, lwp);
+ return ptid_t (inferior_ptid.pid (), lwp, 0);
}
/* Implementation of the to_thread_name method. */
const char *
windows_nat_target::thread_name (struct thread_info *thr)
{
- return thread_rec (thr->ptid.tid (), 0)->name;
+ return thread_rec (thr->ptid, DONT_INVALIDATE_CONTEXT)->name.get ();
}
bool
windows_nat_target::thread_alive (ptid_t ptid)
{
- int tid;
-
- gdb_assert (ptid.tid () != 0);
- tid = ptid.tid ();
+ gdb_assert (ptid.lwp () != 0);
- return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) != WAIT_OBJECT_0;
+ return (WaitForSingleObject (thread_rec (ptid, DONT_INVALIDATE_CONTEXT)->h, 0)
+ != WAIT_OBJECT_0);
}
void _initialize_check_for_gdb_ini ();