[PATCH v2 26/47] Windows gdb+gdbserver: Make current_event per-thread state

Pedro Alves
2025-05-19T13:33:18Z

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
---
gdb/nat/windows-nat.c | 13 +++--
gdb/nat/windows-nat.h | 24 ++++-----
gdb/windows-nat.c | 120 ++++++++++++++++++++++-------------------
gdbserver/win32-low.cc | 70 ++++++++++++------------
gdbserver/win32-low.h | 5 +-
5 files changed, 121 insertions(+), 111 deletions(-)

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 &current_event)
{
+ const EXCEPTION_RECORD *rec = &current_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 &current_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 &current_event)
{
gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);

- LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
+ const LOAD_DLL_DEBUG_INFO *event = &current_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 &current_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 &current_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 &current_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 &current_event);

/* Iterate over all DLLs currently mapped by our inferior, and
add them to our list of solibs. */
@@ -247,7 +245,7 @@ struct windows_process_info

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 &current_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 1197c2f8fe1..8ccb7048665 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -110,9 +110,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 &current_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 &current_event) override;
bool handle_access_violation (const EXCEPTION_RECORD *rec) override;

void invalidate_context (windows_thread_info *th);
@@ -314,7 +315,8 @@ struct windows_nat_target final : public x86_nat_target<inf_child_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);

@@ -345,7 +347,7 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target>
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 &current_event);

BOOL windows_continue (DWORD continue_status, int id,
windows_continue_flags cont_flags = 0);
@@ -951,7 +953,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 &current_event)
{
LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;

@@ -1014,7 +1016,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 &current_event,
+ struct target_waitstatus *ourstatus)
{
DWORD thread_id = 0;

@@ -1297,11 +1300,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 &current_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
@@ -1310,12 +1313,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
@@ -1332,6 +1334,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
@@ -1344,8 +1353,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);
@@ -1362,7 +1370,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;
@@ -1379,25 +1387,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. */
@@ -1459,7 +1459,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;
@@ -1477,7 +1478,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 ());
@@ -1486,7 +1487,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)
{
@@ -1494,11 +1494,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)
@@ -1516,7 +1516,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++;
}
@@ -1613,7 +1613,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)
{
@@ -1633,7 +1633,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)
{
@@ -1650,7 +1650,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:
@@ -1672,7 +1673,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:
@@ -1697,6 +1699,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
@@ -1715,8 +1719,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
@@ -1742,7 +1746,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,
+ &current_event);

if ((options & TARGET_WNOHANG) != 0
&& ourstatus->kind () == TARGET_WAITKIND_IGNORE)
@@ -1761,11 +1768,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)
{
@@ -1806,8 +1813,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);
@@ -1853,7 +1858,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));
@@ -2129,7 +2137,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);
@@ -2140,7 +2148,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);
}

@@ -2937,9 +2945,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 (&current_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 &current_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 (&current_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 &current_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 &current_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,
+ &current_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 (&current_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 @@ class win32_process_target : public process_stratum_target
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 &current_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 &current_event) override;
bool handle_access_violation (const EXCEPTION_RECORD *rec) override;

int attaching = 0;
--
2.49.0