From: Pedro Alves Date: Thu, 21 Oct 2021 17:16:58 +0000 (+0100) Subject: Windows gdb+gdbserver: Make current_event per-thread state X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6451013c097b410000f9429460ffa7efe9d5e4a0;p=thirdparty%2Fbinutils-gdb.git Windows gdb+gdbserver: Make current_event per-thread state With non-stop mode, each thread is controlled independently of the others, and each thread has its own independent reason for its last stop. Thus, any thread-specific state that is currently per-process must be converted to per-thread state. This patch converts windows_process_info::current_event, moving it to windows_thread_info instead, renamed to last_event. Since each thread will have its own copy of its last Windows debug event, we no longer need the same information stored in struct pending_stop. Since windows_process.current_event no longer exists, we need to pass the current event as parameter to a number of methods. This adjusts both native gdb and gdbserver. Change-Id: Ice09a5d932c912210608d5af25e1898f823e3c99 --- diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c index fe707fff905..53d891f65d0 100644 --- a/gdb/nat/windows-nat.c +++ b/gdb/nat/windows-nat.c @@ -300,8 +300,10 @@ get_image_name (HANDLE h, void *address, int unicode) /* See nat/windows-nat.h. */ bool -windows_process_info::handle_ms_vc_exception (const EXCEPTION_RECORD *rec) +windows_process_info::handle_ms_vc_exception (const DEBUG_EVENT ¤t_event) { + const EXCEPTION_RECORD *rec = ¤t_event.u.Exception.ExceptionRecord; + if (rec->NumberParameters >= 3 && (rec->ExceptionInformation[0] & 0xffffffff) == 0x1000) { @@ -342,7 +344,8 @@ windows_process_info::handle_ms_vc_exception (const EXCEPTION_RECORD *rec) #define MS_VC_EXCEPTION 0x406d1388 handle_exception_result -windows_process_info::handle_exception (struct target_waitstatus *ourstatus, +windows_process_info::handle_exception (DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus, bool debug_exceptions) { #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \ @@ -470,7 +473,7 @@ windows_process_info::handle_exception (struct target_waitstatus *ourstatus, break; case MS_VC_EXCEPTION: DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION"); - if (handle_ms_vc_exception (rec)) + if (handle_ms_vc_exception (current_event)) { ourstatus->set_stopped (GDB_SIGNAL_TRAP); result = HANDLE_EXCEPTION_IGNORED; @@ -605,11 +608,11 @@ windows_process_info::add_dll (LPVOID load_addr) /* See nat/windows-nat.h. */ void -windows_process_info::dll_loaded_event () +windows_process_info::dll_loaded_event (const DEBUG_EVENT ¤t_event) { gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT); - LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll; + const LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll; const char *dll_name; /* Try getting the DLL name via the lpImageName field of the event. diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h index 8ac16311650..0b89c751e89 100644 --- a/gdb/nat/windows-nat.h +++ b/gdb/nat/windows-nat.h @@ -46,10 +46,6 @@ struct pending_stop /* The target waitstatus we computed. TARGET_WAITKIND_IGNORE if the thread does not have a pending stop. */ target_waitstatus status; - - /* The event. A few fields of this can be referenced after a stop, - and it seemed simplest to store the entire event. */ - DEBUG_EVENT event; }; @@ -104,6 +100,10 @@ struct windows_thread_info process them once the step has completed. See PR gdb/22992. */ struct pending_stop pending_stop {}; + /* The last Windows event returned by WaitForDebugEvent for this + thread. */ + DEBUG_EVENT last_event {}; + /* The context of the thread, including any manipulations. */ union { @@ -149,10 +149,6 @@ struct windows_process_info DWORD main_thread_id = 0; enum gdb_signal last_sig = GDB_SIGNAL_0; - /* The current debug event from WaitForDebugEvent or from a pending - stop. */ - DEBUG_EVENT current_event {}; - /* Contents of $_siginfo */ EXCEPTION_RECORD siginfo_er {}; @@ -176,7 +172,8 @@ struct windows_process_info a Cygwin signal. Otherwise just print the string as a warning. This function must be supplied by the embedding application. */ - virtual DWORD handle_output_debug_string (struct target_waitstatus *ourstatus) = 0; + virtual DWORD handle_output_debug_string (const DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus) = 0; /* Handle a DLL load event. @@ -197,7 +194,7 @@ struct windows_process_info This function must be supplied by the embedding application. */ - virtual void handle_unload_dll () = 0; + virtual void handle_unload_dll (const DEBUG_EVENT ¤t_event) = 0; /* When EXCEPTION_ACCESS_VIOLATION is processed, we give the embedding application a chance to change it to be considered "unhandled". @@ -207,11 +204,12 @@ struct windows_process_info virtual bool handle_access_violation (const EXCEPTION_RECORD *rec) = 0; handle_exception_result handle_exception - (struct target_waitstatus *ourstatus, bool debug_exceptions); + (DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus, bool debug_exceptions); /* Call to indicate that a DLL was loaded. */ - void dll_loaded_event (); + void dll_loaded_event (const DEBUG_EVENT ¤t_event); /* Iterate over all DLLs currently mapped by our inferior, and add them to our list of solibs. */ @@ -247,7 +245,7 @@ private: Return true if the exception was handled; return false otherwise. */ - bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec); + bool handle_ms_vc_exception (const DEBUG_EVENT ¤t_event); /* 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 diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 47a5df8df44..067c3f8db39 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -109,9 +109,10 @@ DEF_ENUM_FLAGS_TYPE (windows_continue_flag, windows_continue_flags); struct windows_per_inferior : public windows_process_info { windows_thread_info *find_thread (ptid_t ptid) override; - DWORD handle_output_debug_string (struct target_waitstatus *ourstatus) override; + DWORD handle_output_debug_string (const DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus) override; void handle_load_dll (const char *dll_name, LPVOID base) override; - void handle_unload_dll () override; + void handle_unload_dll (const DEBUG_EVENT ¤t_event) override; bool handle_access_violation (const EXCEPTION_RECORD *rec) override; void invalidate_context (windows_thread_info *th); @@ -313,7 +314,8 @@ struct windows_nat_target final : public x86_nat_target const char *thread_name (struct thread_info *) override; ptid_t get_windows_debug_event (int pid, struct target_waitstatus *ourstatus, - target_wait_flags options); + target_wait_flags options, + DEBUG_EVENT *current_event); void do_initial_windows_stuff (DWORD pid, bool attaching); @@ -344,7 +346,7 @@ private: windows_thread_info *add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p); void delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p); - DWORD fake_create_process (); + DWORD fake_create_process (const DEBUG_EVENT ¤t_event); BOOL windows_continue (DWORD continue_status, int id, windows_continue_flags cont_flags = 0); @@ -955,7 +957,7 @@ windows_per_inferior::handle_load_dll (const char *dll_name, LPVOID base) /* See nat/windows-nat.h. */ void -windows_per_inferior::handle_unload_dll () +windows_per_inferior::handle_unload_dll (const DEBUG_EVENT ¤t_event) { LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll; @@ -1018,7 +1020,8 @@ signal_event_command (const char *args, int from_tty) DWORD windows_per_inferior::handle_output_debug_string - (struct target_waitstatus *ourstatus) + (const DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus) { DWORD thread_id = 0; @@ -1301,11 +1304,11 @@ windows_nat_target::windows_continue (DWORD continue_status, int id, /* Called in pathological case where Windows fails to send a CREATE_PROCESS_DEBUG_EVENT after an attach. */ DWORD -windows_nat_target::fake_create_process () +windows_nat_target::fake_create_process (const DEBUG_EVENT ¤t_event) { windows_process.handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, - windows_process.current_event.dwProcessId); + current_event.dwProcessId); if (windows_process.handle != NULL) windows_process.open_process_used = 1; else @@ -1314,12 +1317,11 @@ windows_nat_target::fake_create_process () throw_winerror_with_name (_("OpenProcess call failed"), err); /* We can not debug anything in that case. */ } - add_thread (ptid_t (windows_process.current_event.dwProcessId, - windows_process.current_event.dwThreadId, 0), - windows_process.current_event.u.CreateThread.hThread, - windows_process.current_event.u.CreateThread.lpThreadLocalBase, + 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 */); - return windows_process.current_event.dwThreadId; + return current_event.dwThreadId; } void @@ -1336,6 +1338,13 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) if (resume_all) ptid = inferior_ptid; + DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d", + ptid.pid (), (unsigned) ptid.lwp (), step, sig); + + /* Get currently selected thread. */ + th = windows_process.find_thread (inferior_ptid); + gdb_assert (th != nullptr); + if (sig != GDB_SIGNAL_0) { /* Note it is OK to call get_last_debug_event_ptid() from the @@ -1348,8 +1357,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) DEBUG_EXCEPT ("Cannot continue with signal %d here. " "Not last-event thread", sig); } - else if (windows_process.current_event.dwDebugEventCode - != EXCEPTION_DEBUG_EVENT) + else if (th->last_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) { DEBUG_EXCEPT ("Cannot continue with signal %d here. " "Not stopped for EXCEPTION_DEBUG_EVENT", sig); @@ -1366,7 +1374,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) for (const xlate_exception &x : xlate) if (x.us == sig) { - current_event.u.Exception.ExceptionRecord.ExceptionCode + th->last_event.u.Exception.ExceptionRecord.ExceptionCode = x.them; continue_status = DBG_EXCEPTION_NOT_HANDLED; break; @@ -1383,25 +1391,17 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) windows_process.last_sig = GDB_SIGNAL_0; - DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d", - ptid.pid (), (unsigned) ptid.lwp (), step, sig); - - /* Get context for currently selected thread. */ - th = windows_process.find_thread (inferior_ptid); - if (th) + windows_process.with_context (th, [&] (auto *context) { - windows_process.with_context (th, [&] (auto *context) + if (step) { - if (step) - { - /* Single step by setting t bit. */ - regcache *regcache = get_thread_regcache (inferior_thread ()); - struct gdbarch *gdbarch = regcache->arch (); - fetch_registers (regcache, gdbarch_ps_regnum (gdbarch)); - context->EFlags |= FLAG_TRACE_BIT; - } - }); - } + /* Single step by setting t bit. */ + regcache *regcache = get_thread_regcache (inferior_thread ()); + struct gdbarch *gdbarch = regcache->arch (); + fetch_registers (regcache, gdbarch_ps_regnum (gdbarch)); + context->EFlags |= FLAG_TRACE_BIT; + } + }); /* Allow continuing with the same signal that interrupted us. Otherwise complain. */ @@ -1463,7 +1463,8 @@ windows_nat_target::pass_ctrlc () ptid_t windows_nat_target::get_windows_debug_event - (int pid, struct target_waitstatus *ourstatus, target_wait_flags options) + (int pid, struct target_waitstatus *ourstatus, target_wait_flags options, + DEBUG_EVENT *current_event) { DWORD continue_status, event_code; DWORD thread_id = 0; @@ -1481,7 +1482,7 @@ windows_nat_target::get_windows_debug_event thread_id = th->tid; *ourstatus = th->pending_stop.status; th->pending_stop.status.set_ignore (); - windows_process.current_event = th->pending_stop.event; + *current_event = th->last_event; ptid_t ptid (windows_process.process_id, thread_id); windows_process.invalidate_context (th.get ()); @@ -1490,7 +1491,6 @@ windows_nat_target::get_windows_debug_event } windows_process.last_sig = GDB_SIGNAL_0; - DEBUG_EVENT *current_event = &windows_process.current_event; if ((options & TARGET_WNOHANG) != 0 && !m_debug_event_pending) { @@ -1498,11 +1498,11 @@ windows_nat_target::get_windows_debug_event return minus_one_ptid; } - wait_for_debug_event_main_thread (&windows_process.current_event); + wait_for_debug_event_main_thread (current_event); continue_status = DBG_CONTINUE; - event_code = windows_process.current_event.dwDebugEventCode; + event_code = current_event->dwDebugEventCode; ourstatus->set_spurious (); switch (event_code) @@ -1520,7 +1520,7 @@ windows_nat_target::get_windows_debug_event /* Kludge around a Windows bug where first event is a create thread event. Caused when attached process does not have a main thread. */ - thread_id = fake_create_process (); + thread_id = fake_create_process (*current_event); if (thread_id) windows_process.saw_create++; } @@ -1617,7 +1617,7 @@ windows_nat_target::get_windows_debug_event break; try { - windows_process.dll_loaded_event (); + windows_process.dll_loaded_event (*current_event); } catch (const gdb_exception &ex) { @@ -1637,7 +1637,7 @@ windows_nat_target::get_windows_debug_event break; try { - windows_process.handle_unload_dll (); + windows_process.handle_unload_dll (*current_event); } catch (const gdb_exception &ex) { @@ -1654,7 +1654,8 @@ windows_nat_target::get_windows_debug_event "EXCEPTION_DEBUG_EVENT"); if (windows_process.saw_create != 1) break; - switch (windows_process.handle_exception (ourstatus, debug_exceptions)) + switch (windows_process.handle_exception (*current_event, + ourstatus, debug_exceptions)) { case HANDLE_EXCEPTION_UNHANDLED: default: @@ -1676,7 +1677,8 @@ windows_nat_target::get_windows_debug_event "OUTPUT_DEBUG_STRING_EVENT"); if (windows_process.saw_create != 1) break; - thread_id = windows_process.handle_output_debug_string (ourstatus); + thread_id = windows_process.handle_output_debug_string (*current_event, + ourstatus); break; default: @@ -1701,6 +1703,8 @@ windows_nat_target::get_windows_debug_event const ptid_t ptid = ptid_t (current_event->dwProcessId, thread_id, 0); windows_thread_info *th = windows_process.find_thread (ptid); + th->last_event = *current_event; + if (th->suspended) { /* Pending stop. See the comment by the definition of @@ -1719,8 +1723,8 @@ windows_nat_target::get_windows_debug_event th->stopped_at_software_breakpoint = true; th->pc_adjusted = false; } + th->pending_stop.status = *ourstatus; - th->pending_stop.event = *current_event; ourstatus->set_ignore (); continue_last_debug_event_main_thread @@ -1746,7 +1750,10 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, while (1) { - ptid_t result = get_windows_debug_event (pid, ourstatus, options); + DEBUG_EVENT current_event; + + ptid_t result = get_windows_debug_event (pid, ourstatus, options, + ¤t_event); if ((options & TARGET_WNOHANG) != 0 && ourstatus->kind () == TARGET_WAITKIND_IGNORE) @@ -1765,11 +1772,11 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, windows_thread_info *th = windows_process.find_thread (result); th->stopped_at_software_breakpoint = false; - if (windows_process.current_event.dwDebugEventCode + if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT - && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode + && ((current_event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) - || (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode + || (current_event.u.Exception.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT)) && windows_process.windows_initialization_done) { @@ -1810,8 +1817,6 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching) windows_process.cygwin_load_end = 0; #endif windows_process.process_id = pid; - memset (&windows_process.current_event, 0, - sizeof (windows_process.current_event)); inf = current_inferior (); if (!inf->target_is_pushed (this)) inf->push_target (this); @@ -1857,7 +1862,10 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching) && status.kind () != TARGET_WAITKIND_SPURIOUS) break; - this->resume (minus_one_ptid, 0, GDB_SIGNAL_0); + /* Don't use windows_nat_target::resume here because that + assumes that inferior_ptid points at a valid thread, and we + haven't switched to any thread yet. */ + windows_continue (DBG_CONTINUE, -1); } switch_to_thread (this->find_thread (last_ptid)); @@ -2133,7 +2141,7 @@ windows_nat_target::detach (inferior *inf, int from_tty) if (process_alive) do_synchronously ([&] () { - if (!DebugActiveProcessStop (windows_process.current_event.dwProcessId)) + if (!DebugActiveProcessStop (windows_process.process_id)) err = (unsigned) GetLastError (); else DebugSetProcessKillOnExit (FALSE); @@ -2144,7 +2152,7 @@ windows_nat_target::detach (inferior *inf, int from_tty) { std::string msg = string_printf (_("Can't detach process %u"), - (unsigned) windows_process.current_event.dwProcessId); + windows_process.process_id); throw_winerror_with_name (msg.c_str (), *err); } @@ -2941,9 +2949,9 @@ windows_nat_target::kill () { if (!windows_continue (DBG_CONTINUE, -1, WCONT_KILLED)) break; - wait_for_debug_event_main_thread (&windows_process.current_event); - if (windows_process.current_event.dwDebugEventCode - == EXIT_PROCESS_DEBUG_EVENT) + DEBUG_EVENT current_event; + wait_for_debug_event_main_thread (¤t_event); + if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; } diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc index ebce67cd72d..a4000980f67 100644 --- a/gdbserver/win32-low.cc +++ b/gdbserver/win32-low.cc @@ -296,9 +296,6 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached) windows_process.open_process_used = true; - memset (&windows_process.current_event, 0, - sizeof (windows_process.current_event)); - #ifdef __x86_64__ BOOL wow64; if (!IsWow64Process (proch, &wow64)) @@ -601,7 +598,8 @@ win32_process_target::attach (unsigned long pid) DWORD gdbserver_windows_process::handle_output_debug_string - (struct target_waitstatus *ourstatus) + (const DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus) { #define READ_BUFFER_LEN 1024 CORE_ADDR addr; @@ -669,14 +667,13 @@ win32_process_target::kill (process_info *process) { if (!child_continue_for_kill (DBG_CONTINUE, -1)) break; - if (!wait_for_debug_event (&windows_process.current_event, INFINITE)) + DEBUG_EVENT current_event; + if (!wait_for_debug_event (¤t_event, INFINITE)) break; - if (windows_process.current_event.dwDebugEventCode - == EXIT_PROCESS_DEBUG_EVENT) + if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; - else if (windows_process.current_event.dwDebugEventCode - == OUTPUT_DEBUG_STRING_EVENT) - windows_process.handle_output_debug_string (nullptr); + else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) + windows_process.handle_output_debug_string (current_event, nullptr); } win32_clear_process (); @@ -755,8 +752,7 @@ resume_one_thread (thread_info *thread, bool step, gdb_signal sig, OUTMSG (("Cannot continue with signal %d here. " "Not last-event thread", sig)); } - else if (windows_process.current_event.dwDebugEventCode - != EXCEPTION_DEBUG_EVENT) + else if (th->last_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) { OUTMSG (("Cannot continue with signal %s here. " "Not stopped for EXCEPTION_DEBUG_EVENT.\n", @@ -895,7 +891,7 @@ gdbserver_windows_process::handle_load_dll (const char *name, LPVOID base) /* See nat/windows-nat.h. */ void -gdbserver_windows_process::handle_unload_dll () +gdbserver_windows_process::handle_unload_dll (const DEBUG_EVENT ¤t_event) { CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll; @@ -929,7 +925,7 @@ gdbserver_windows_process::handle_access_violation PC. */ static void -maybe_adjust_pc () +maybe_adjust_pc (const DEBUG_EVENT ¤t_event) { regcache *regcache = get_thread_regcache (current_thread); child_fetch_inferior_registers (regcache, -1); @@ -938,10 +934,10 @@ maybe_adjust_pc () = windows_process.find_thread (current_thread->id); th->stopped_at_software_breakpoint = false; - if (windows_process.current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT - && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode + if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT + && ((current_event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) - || (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode + || (current_event.u.Exception.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT)) && windows_process.child_initialization_done) { @@ -956,7 +952,8 @@ maybe_adjust_pc () static int get_child_debug_event (DWORD *continue_status, - struct target_waitstatus *ourstatus) + struct target_waitstatus *ourstatus, + DEBUG_EVENT *current_event) { ptid_t ptid; @@ -967,8 +964,6 @@ get_child_debug_event (DWORD *continue_status, /* Check if GDB sent us an interrupt request. */ check_remote_input_interrupt_request (); - DEBUG_EVENT *current_event = &windows_process.current_event; - windows_process.attaching = 0; { process_info *proc = find_process_pid (windows_process.process_id); @@ -981,8 +976,8 @@ get_child_debug_event (DWORD *continue_status, { *ourstatus = th->pending_stop.status; th->pending_stop.status.set_ignore (); - windows_process.current_event = th->pending_stop.event; - ptid = debug_event_ptid (&windows_process.current_event); + *current_event = th->last_event; + ptid = debug_event_ptid (current_event); switch_to_thread (find_thread_ptid (ptid)); return 1; } @@ -991,7 +986,7 @@ get_child_debug_event (DWORD *continue_status, /* Keep the wait time low enough for comfortable remote interruption, but high enough so gdbserver doesn't become a bottleneck. */ - if (!wait_for_debug_event (&windows_process.current_event, 250)) + if (!wait_for_debug_event (current_event, 250)) { DWORD e = GetLastError(); @@ -1086,7 +1081,7 @@ get_child_debug_event (DWORD *continue_status, CloseHandle (current_event->u.LoadDll.hFile); if (! windows_process.child_initialization_done) break; - windows_process.dll_loaded_event (); + windows_process.dll_loaded_event (*current_event); ourstatus->set_loaded (); break; @@ -1098,7 +1093,7 @@ get_child_debug_event (DWORD *continue_status, (unsigned) current_event->dwThreadId)); if (! windows_process.child_initialization_done) break; - windows_process.handle_unload_dll (); + windows_process.handle_unload_dll (*current_event); ourstatus->set_loaded (); break; @@ -1107,7 +1102,8 @@ get_child_debug_event (DWORD *continue_status, "for pid=%u tid=%x\n", (unsigned) current_event->dwProcessId, (unsigned) current_event->dwThreadId)); - if (windows_process.handle_exception (ourstatus, debug_threads) + if (windows_process.handle_exception (*current_event, + ourstatus, debug_threads) == HANDLE_EXCEPTION_UNHANDLED) *continue_status = DBG_EXCEPTION_NOT_HANDLED; break; @@ -1118,7 +1114,7 @@ get_child_debug_event (DWORD *continue_status, "for pid=%u tid=%x\n", (unsigned) current_event->dwProcessId, (unsigned) current_event->dwThreadId)); - windows_process.handle_output_debug_string (nullptr); + windows_process.handle_output_debug_string (*current_event, nullptr); break; default: @@ -1130,10 +1126,12 @@ get_child_debug_event (DWORD *continue_status, break; } - ptid = debug_event_ptid (&windows_process.current_event); + ptid = debug_event_ptid (current_event); windows_thread_info *th = windows_process.find_thread (ptid); + th->last_event = *current_event; + if (th != nullptr && th->suspended) { /* Pending stop. See the comment by the definition of @@ -1142,9 +1140,8 @@ get_child_debug_event (DWORD *continue_status, OUTMSG2 (("get_windows_debug_event - " "unexpected stop in suspended thread 0x%x\n", th->tid)); - maybe_adjust_pc (); + maybe_adjust_pc (*current_event); th->pending_stop.status = *ourstatus; - th->pending_stop.event = *current_event; ourstatus->set_spurious (); } else @@ -1168,13 +1165,16 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus, fails). Report it now. */ *ourstatus = windows_process.cached_status; windows_process.cached_status.set_ignore (); - return debug_event_ptid (&windows_process.current_event); + return ptid_t (windows_process.process_id, + windows_process.main_thread_id, 0); } while (1) { DWORD continue_status; - if (!get_child_debug_event (&continue_status, ourstatus)) + DEBUG_EVENT current_event; + if (!get_child_debug_event (&continue_status, ourstatus, + ¤t_event)) continue; switch (ourstatus->kind ()) @@ -1183,20 +1183,20 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus, OUTMSG2 (("Child exited with retcode = %x\n", ourstatus->exit_status ())); win32_clear_process (); - return ptid_t (windows_process.current_event.dwProcessId); + return ptid_t (windows_process.process_id); case TARGET_WAITKIND_STOPPED: case TARGET_WAITKIND_SIGNALLED: case TARGET_WAITKIND_LOADED: { OUTMSG2 (("Child Stopped with signal = %d \n", ourstatus->sig ())); - maybe_adjust_pc (); + maybe_adjust_pc (current_event); /* All-stop, suspend all threads until they are explicitly resumed. */ for_each_thread (suspend_one_thread); - return debug_event_ptid (&windows_process.current_event); + return debug_event_ptid (¤t_event); } default: OUTMSG (("Ignoring unknown internal event, %d\n", diff --git a/gdbserver/win32-low.h b/gdbserver/win32-low.h index b170eb898f6..1891f82b046 100644 --- a/gdbserver/win32-low.h +++ b/gdbserver/win32-low.h @@ -182,9 +182,10 @@ public: struct gdbserver_windows_process : public windows_nat::windows_process_info { windows_nat::windows_thread_info *find_thread (ptid_t ptid) override; - DWORD handle_output_debug_string (struct target_waitstatus *ourstatus) override; + DWORD handle_output_debug_string (const DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus) override; void handle_load_dll (const char *dll_name, LPVOID base) override; - void handle_unload_dll () override; + void handle_unload_dll (const DEBUG_EVENT ¤t_event) override; bool handle_access_violation (const EXCEPTION_RECORD *rec) override; int attaching = 0;