X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fwindows-nat.c;h=eb550259fe2bcd3969608689a87403fd16afdf4c;hb=29de418deeac717886df20ef0419240aa0dfc32a;hp=2f9e00a0a9abe58eb139425092d6a00d8c4fc178;hpb=93366324f5232374bc19d94d94b5ed6159326240;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 2f9e00a0a9..eb550259fe 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -70,10 +70,13 @@ #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 @@ -241,41 +244,9 @@ static CORE_ADDR cygwin_get_dr (int i); 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 id; - 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 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; static int saw_create; static int open_process_used = 0; #ifdef __x86_64__ @@ -361,6 +332,16 @@ struct windows_nat_target final : public x86_nat_target 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, @@ -422,42 +403,31 @@ check (BOOL ok, const char *file, int line) (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->id == 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; } @@ -477,25 +447,20 @@ static windows_thread_info * 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); - id = ptid.tid (); + gdb_assert (ptid.lwp () != 0); - if ((th = thread_rec (id, FALSE))) + if ((th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT))) return th; - th = XCNEW (windows_thread_info); - th->id = 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. @@ -554,7 +519,7 @@ windows_init_thread_list (void) init_thread_list (); for (windows_thread_info *here : thread_list) - xfree (here); + delete here; thread_list.clear (); } @@ -571,9 +536,9 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p) { 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. @@ -594,13 +559,12 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p) auto iter = std::find_if (thread_list.begin (), thread_list.end (), [=] (windows_thread_info *th) { - return th->id == id; + return th->tid == id; }); if (iter != thread_list.end ()) { - xfree ((*iter)->name); - xfree (*iter); + delete *iter; thread_list.erase (iter); } } @@ -632,6 +596,10 @@ windows_fetch_one_register (struct regcache *regcache, 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; @@ -651,14 +619,35 @@ windows_fetch_one_register (struct regcache *regcache, 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. */ @@ -716,7 +705,7 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r) dr[7] = th->context.Dr7; } } - th->reload_context = 0; + th->reload_context = false; } if (r < 0) @@ -753,8 +742,7 @@ windows_store_one_register (const struct regcache *regcache, 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. */ @@ -880,68 +868,13 @@ windows_make_so (const char *name, LPVOID load_addr) 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. +/* See nat/windows-nat.h. */ - This function assumes that this event did not occur during inferior - initialization, where their event info may be incomplete (see - do_initial_windows_stuff and windows_add_all_dlls for more info - on how we handle DLL loading during that phase). */ - -static void -handle_load_dll () +void +windows_nat::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, @@ -971,16 +904,10 @@ windows_free_so (struct so_list *so) xfree (so); } -/* Handle a DLL unload event. - Return 1 if successful, or zero otherwise. +/* See nat/windows-nat.h. */ - This function assumes that this event did not occur during inferior - initialization, where their event info may be incomplete (see - do_initial_windows_stuff and windows_add_all_dlls for more info - on how we handle DLL loading during that phase). */ - -static void -handle_unload_dll () +void +windows_nat::handle_unload_dll () { LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll; struct so_list *so; @@ -1064,11 +991,10 @@ signal_event_command (const char *args, int from_tty) 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 s; int retval = 0; @@ -1216,7 +1142,7 @@ display_selector (HANDLE thread, DWORD sel) 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; @@ -1227,45 +1153,45 @@ display_selectors (const char * args, int from_tty) 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 @@ -1273,7 +1199,7 @@ display_selectors (const char * args, int from_tty) 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); } } @@ -1294,7 +1220,8 @@ handle_exception (struct target_waitstatus *ourstatus) 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) { @@ -1424,7 +1351,9 @@ handle_exception (struct target_waitstatus *ourstatus) 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; @@ -1435,8 +1364,7 @@ handle_exception (struct target_waitstatus *ourstatus) 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; @@ -1456,7 +1384,6 @@ handle_exception (struct target_waitstatus *ourstatus) ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; break; } - exception_count++; last_sig = ourstatus->value.sig; return result; } @@ -1470,16 +1397,36 @@ windows_continue (DWORD continue_status, int id, int killed) { 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->id) - && th->suspended) + if (id == -1 || id == (int) th->tid) { + if (!th->suspended) + continue; #ifdef __x86_64__ if (wow64_process) { @@ -1537,13 +1484,17 @@ windows_continue (DWORD continue_status, int id, int killed) 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) @@ -1570,9 +1521,9 @@ fake_create_process (void) (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 */); @@ -1629,10 +1580,10 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) 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__ @@ -1697,7 +1648,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) 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 @@ -1726,6 +1677,17 @@ ctrl_c_handler (DWORD event_type) 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). */ @@ -1736,15 +1698,42 @@ windows_nat_target::get_windows_debug_event (int pid, 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++; continue_status = DBG_CONTINUE; event_code = current_event.dwDebugEventCode; @@ -1776,7 +1765,7 @@ windows_nat_target::get_windows_debug_event (int pid, /* 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 */); @@ -1788,8 +1777,8 @@ windows_nat_target::get_windows_debug_event (int pid, (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; @@ -1807,8 +1796,8 @@ windows_nat_target::get_windows_debug_event (int pid, 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 */); @@ -1829,8 +1818,8 @@ windows_nat_target::get_windows_debug_event (int pid, } 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 @@ -1925,14 +1914,36 @@ windows_nat_target::get_windows_debug_event (int pid, 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: @@ -1987,7 +1998,21 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, 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; @@ -2125,8 +2150,6 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching) struct inferior *inf; last_sig = GDB_SIGNAL_0; - event_count = 0; - exception_count = 0; open_process_used = 0; debug_registers_changed = 0; debug_registers_used = 0; @@ -3239,7 +3262,7 @@ windows_nat_target::kill () { 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; @@ -3259,8 +3282,8 @@ windows_nat_target::close () 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); } @@ -3394,7 +3417,7 @@ windows_nat_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr) { windows_thread_info *th; - th = thread_rec (ptid.tid (), 0); + th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT); if (th == NULL) return false; @@ -3407,7 +3430,7 @@ windows_nat_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr) 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. */ @@ -3415,7 +3438,7 @@ windows_nat_target::get_ada_task_ptid (long lwp, long thread) 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 (); } @@ -3574,12 +3597,10 @@ cygwin_get_dr7 (void) 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 ();