Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>
Subject: [pushed 19/28] Windows gdb+gdbserver: Make current_event per-thread state
Date: Fri, 24 Apr 2026 21:44:59 +0100	[thread overview]
Message-ID: <20260424204508.1343973-20-pedro@palves.net> (raw)
In-Reply-To: <20260424204508.1343973-1-pedro@palves.net>

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.

Approved-By: Tom Tromey <tom@tromey.com>
Change-Id: Ice09a5d932c912210608d5af25e1898f823e3c99
commit-id:ca7e9182
---
 gdb/nat/windows-nat.c  | 13 +++---
 gdb/nat/windows-nat.h  | 24 ++++++-----
 gdb/windows-nat.c      | 90 +++++++++++++++++++++++-------------------
 gdb/windows-nat.h      | 10 +++--
 gdbserver/win32-low.cc | 68 +++++++++++++++----------------
 gdbserver/win32-low.h  |  5 ++-
 6 files changed, 112 insertions(+), 98 deletions(-)

diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 11151fdc28a..4adca4afa64 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;
@@ -610,11 +613,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 8d97ecc4cb6..4710ec39130 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 614d85ac8f7..64c53b53934 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -557,7 +557,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;
 
@@ -620,7 +620,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;
 
@@ -753,11 +754,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
@@ -766,12 +767,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
@@ -788,6 +788,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
@@ -800,8 +807,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);
@@ -818,7 +824,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;
@@ -835,12 +841,8 @@ 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 != nullptr && step)
+  if (step)
     {
       /* Single step by setting t bit.  */
       regcache *regcache = get_thread_regcache (inferior_thread ());
@@ -915,7 +917,8 @@ windows_nat_target::stop (ptid_t ptid)
 
 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;
@@ -933,7 +936,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_thread_context (th.get ());
@@ -942,7 +945,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)
     {
@@ -950,11 +952,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)
@@ -972,7 +974,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++;
 	    }
@@ -1069,7 +1071,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)
 	{
@@ -1089,7 +1091,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)
 	{
@@ -1106,7 +1108,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:
@@ -1128,7 +1131,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:
@@ -1153,6 +1157,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
@@ -1168,8 +1174,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
@@ -1195,7 +1201,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)
@@ -1214,11 +1223,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)
 		{
@@ -1261,8 +1270,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);
@@ -1292,7 +1299,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));
@@ -1575,7 +1585,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);
@@ -1586,7 +1596,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);
     }
 
@@ -2383,9 +2393,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/gdb/windows-nat.h b/gdb/windows-nat.h
index 0f586cd195e..15a177214f2 100644
--- a/gdb/windows-nat.h
+++ b/gdb/windows-nat.h
@@ -63,9 +63,10 @@ DEF_ENUM_FLAGS_TYPE (windows_continue_flag, windows_continue_flags);
 struct windows_per_inferior : public windows_nat::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;
 
   /* Invalidate the thread context.  */
@@ -172,7 +173,8 @@ struct windows_nat_target : public 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);
 
@@ -244,7 +246,7 @@ struct windows_nat_target : public 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);
 
   void continue_one_thread (windows_thread_info *th,
 			    windows_continue_flags cont_flags);
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 5caec960082..aa484fcda4a 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -291,9 +291,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))
@@ -590,7 +587,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;
@@ -658,14 +656,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 ();
@@ -744,8 +741,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",
@@ -884,7 +880,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;
@@ -918,7 +914,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);
@@ -927,8 +923,8 @@ 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
-      && (*the_low_target.is_sw_breakpoint) (&windows_process.current_event
+  if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
+      && (*the_low_target.is_sw_breakpoint) (&current_event
 					     .u.Exception.ExceptionRecord)
       && windows_process.child_initialization_done)
     {
@@ -943,7 +939,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;
 
@@ -954,8 +951,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);
@@ -968,8 +963,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;
 	  }
@@ -978,7 +973,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();
 
@@ -1073,7 +1068,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;
@@ -1085,7 +1080,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;
 
@@ -1094,7 +1089,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;
@@ -1105,7 +1101,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:
@@ -1117,10 +1113,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
@@ -1129,9 +1127,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
@@ -1155,13 +1152,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 ())
@@ -1170,20 +1170,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 9c672bfce1a..01a904043eb 100644
--- a/gdbserver/win32-low.h
+++ b/gdbserver/win32-low.h
@@ -179,9 +179,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.53.0


  parent reply	other threads:[~2026-04-24 20:48 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-24 20:44 [pushed 00/28] Windows non-stop prep Pedro Alves
2026-04-24 20:44 ` [pushed 01/28] Windows gdb+gdbserver: New find_thread, replaces thread_rec(DONT_INVALIDATE_CONTEXT) Pedro Alves
2026-04-24 20:44 ` [pushed 02/28] Windows gdb: handle_output_debug_string return type Pedro Alves
2026-04-24 20:44 ` [pushed 03/28] Windows gdb: Eliminate reload_context Pedro Alves
2026-04-24 20:44 ` [pushed 04/28] Windows gdb+gdbserver: Eliminate thread_rec(INVALIDATE_CONTEXT) calls Pedro Alves
2026-04-24 20:44 ` [pushed 05/28] Windows gdb+gdbserver: Eliminate DONT_SUSPEND Pedro Alves
2026-04-24 20:44 ` [pushed 06/28] Windows gdb+gdbserver: Eliminate windows_process_info::thread_rec Pedro Alves
2026-04-24 20:44 ` [pushed 07/28] Windows gdb: Simplify windows_nat_target::wait Pedro Alves
2026-04-26 12:52   ` Hannes Domani
2026-04-27 12:09     ` [pushed/ob] Restore windows_nat_target::wait is_sw_breakpoint change Pedro Alves
2026-04-24 20:44 ` [pushed 08/28] Windows gdb+gdbserver: Move suspending thread to when returning event Pedro Alves
2026-04-24 20:44 ` [pushed 09/28] Windows gdb: Introduce continue_last_debug_event_main_thread Pedro Alves
2026-04-24 20:44 ` [pushed 10/28] Windows gdb: Introduce windows_continue_flags Pedro Alves
2026-04-24 20:44 ` [pushed 11/28] Windows gdb: Factor code out of windows_nat_target::windows_continue Pedro Alves
2026-04-24 20:44 ` [pushed 12/28] Windows gdb: Pending stop and current_event Pedro Alves
2026-04-24 20:44 ` [pushed 13/28] Windows gdb+gdbserver: Elim desired_stop_thread_id / rework pending_stops Pedro Alves
2026-04-24 20:44 ` [pushed 14/28] Windows gdb+gdbserver: Introduce get_last_debug_event_ptid Pedro Alves
2026-04-24 20:44 ` [pushed 15/28] Windows gdb: Can't pass signal to thread other than last stopped thread Pedro Alves
2026-04-24 20:44 ` [pushed 16/28] Windows gdbserver: Fix scheduler-locking Pedro Alves
2026-04-24 20:44 ` [pushed 17/28] Windows gdb: Enable "set scheduler-locking on" Pedro Alves
2026-04-27 12:57   ` [pushed] Mention Windows scheduler-locking in NEWS (Re: [pushed 17/28] Windows gdb: Enable "set scheduler-locking on") Pedro Alves
2026-04-24 20:44 ` [pushed 18/28] Windows gdbserver: Eliminate soft-interrupt mechanism Pedro Alves
2026-04-24 20:44 ` Pedro Alves [this message]
2026-04-24 20:45 ` [pushed 20/28] Windows gdb+gdbserver: Make last_sig per-thread state Pedro Alves
2026-04-24 20:45 ` [pushed 21/28] Windows gdb+gdbserver: Make siginfo_er " Pedro Alves
2026-04-24 20:45 ` [pushed 22/28] Add backpointer from windows_thread_info to windows_process_info Pedro Alves
2026-04-24 20:45 ` [pushed 23/28] Windows gdb+gdbserver: Share $_siginfo reading code Pedro Alves
2026-04-24 20:45 ` [pushed 24/28] Windows gdb+gdbserver: Eliminate struct pending_stop Pedro Alves
2026-04-24 20:45 ` [pushed 25/28] Windows gdb: Change serial_event management Pedro Alves
2026-04-24 20:45 ` [pushed 26/28] Windows gdb: cygwin_set_dr => windows_set_dr, etc Pedro Alves
2026-04-24 20:45 ` [pushed 27/28] Windows gdb: Move debug macros to windows-nat.h Pedro Alves
2026-04-24 20:45 ` [pushed 28/28] Windows gdb: Avoid writing debug registers if watchpoint hit pending Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260424204508.1343973-20-pedro@palves.net \
    --to=pedro@palves.net \
    --cc=gdb-patches@sourceware.org \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox