Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: gdb-patches@sourceware.org
Subject: [PATCH v2 26/47] Windows gdb+gdbserver: Make current_event per-thread state
Date: Mon, 19 May 2025 14:22:47 +0100	[thread overview]
Message-ID: <20250519132308.3553663-27-pedro@palves.net> (raw)
In-Reply-To: <20250519132308.3553663-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.

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


  parent reply	other threads:[~2025-05-19 13:33 UTC|newest]

Thread overview: 97+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-19 13:22 [PATCH v2 00/47] Windows non-stop mode Pedro Alves
2025-05-19 13:22 ` [PATCH v2 01/47] Make default_gdb_exit resilient to failed closes Pedro Alves
2025-05-19 13:56   ` Andrew Burgess
2025-06-06 13:56     ` Pedro Alves
2025-05-19 13:22 ` [PATCH v2 02/47] Add test for continuing with some threads running Pedro Alves
2025-05-21 19:36   ` Kevin Buettner
2026-04-02 13:07     ` Pedro Alves
2025-05-19 13:22 ` [PATCH v2 03/47] infrun: Remove unnecessary currently_stepping call Pedro Alves
2025-05-21 19:44   ` Kevin Buettner
2026-04-02 13:17     ` Pedro Alves
2025-05-19 13:22 ` [PATCH v2 04/47] infrun: Split currently_stepping, fix sw watchpoints issue Pedro Alves
2026-04-02 13:33   ` Pedro Alves
2025-05-19 13:22 ` [PATCH v2 05/47] thread_info::executing+resumed -> thread_info::internal_state Pedro Alves
2026-04-06 18:01   ` Pedro Alves
2025-05-19 13:22 ` [PATCH v2 06/47] Windows gdb: Dead code in windows_nat_target::do_initial_windows_stuff Pedro Alves
2025-05-19 13:22 ` [PATCH v2 07/47] Windows gdb: Eliminate global current_process.dr[8] global Pedro Alves
2025-05-28 19:09   ` Tom Tromey
2026-04-06 19:44   ` Pedro Alves
2025-05-19 13:22 ` [PATCH v2 08/47] Windows gdb+gdbserver: New find_thread, replaces thread_rec(DONT_INVALIDATE_CONTEXT) Pedro Alves
2025-05-19 13:22 ` [PATCH v2 09/47] Windows gdb: handle_output_debug_string return type Pedro Alves
2025-05-19 13:22 ` [PATCH v2 10/47] Windows gdb: Eliminate reload_context Pedro Alves
2025-05-19 13:22 ` [PATCH v2 11/47] Windows gdb+gdbserver: Eliminate thread_rec(INVALIDATE_CONTEXT) calls Pedro Alves
2025-05-19 13:22 ` [PATCH v2 12/47] Windows gdb+gdbserver: Eliminate DONT_SUSPEND Pedro Alves
2025-05-19 13:22 ` [PATCH v2 13/47] Windows gdb+gdbserver: Eliminate windows_process_info::thread_rec Pedro Alves
2025-05-19 13:22 ` [PATCH v2 14/47] Windows gdb: Simplify windows_nat_target::wait Pedro Alves
2025-05-28 19:16   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 15/47] Windows gdb+gdbserver: Move suspending thread to when returning event Pedro Alves
2025-05-28 19:17   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 16/47] Windows gdb: Introduce continue_last_debug_event_main_thread Pedro Alves
2025-05-28 19:18   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 17/47] Windows gdb: Introduce windows_continue_flags Pedro Alves
2025-05-19 13:22 ` [PATCH v2 18/47] Windows gdb: Factor code out of windows_nat_target::windows_continue Pedro Alves
2025-05-19 13:22 ` [PATCH v2 19/47] Windows gdb: Pending stop and current_event Pedro Alves
2025-05-19 13:22 ` [PATCH v2 20/47] Windows gdb+gdbserver: Elim desired_stop_thread_id / rework pending_stops Pedro Alves
2025-05-30 20:41   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 21/47] Windows gdb+gdbserver: Introduce get_last_debug_event_ptid Pedro Alves
2025-05-28 19:21   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 22/47] Windows gdb: Can't pass signal to thread other than last stopped thread Pedro Alves
2025-05-28 19:22   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 23/47] Windows gdbserver: Fix scheduler-locking Pedro Alves
2025-05-30 20:37   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 24/47] Windows gdb: Enable "set scheduler-locking on" Pedro Alves
2025-05-19 13:22 ` [PATCH v2 25/47] Windows gdbserver: Eliminate soft-interrupt mechanism Pedro Alves
2025-05-19 13:22 ` Pedro Alves [this message]
2025-05-28 19:30   ` [PATCH v2 26/47] Windows gdb+gdbserver: Make current_event per-thread state Tom Tromey
2025-05-19 13:22 ` [PATCH v2 27/47] Windows gdb+gdbserver: Make last_sig " Pedro Alves
2025-05-28 19:31   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 28/47] Windows gdb+gdbserver: Make siginfo_er " Pedro Alves
2025-05-28 19:33   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 29/47] Add backpointer from windows_thread_info to windows_process_info Pedro Alves
2025-05-19 13:22 ` [PATCH v2 30/47] Windows gdb+gdbserver: Share $_siginfo reading code Pedro Alves
2025-05-19 13:22 ` [PATCH v2 31/47] Windows gdb+gdbserver: Eliminate struct pending_stop Pedro Alves
2025-05-28 19:36   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 32/47] Windows gdb: Change serial_event management Pedro Alves
2025-05-28 19:37   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 33/47] Windows gdb: cygwin_set_dr => windows_set_dr, etc Pedro Alves
2025-05-19 13:22 ` [PATCH v2 34/47] Windows gdb: Avoid writing debug registers if watchpoint hit pending Pedro Alves
2025-05-30 20:43   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 35/47] Windows gdb+gdbserver: Check whether DBG_REPLY_LATER is available Pedro Alves
2025-05-19 13:22 ` [PATCH v2 36/47] linux-nat: Factor out get_detach_signal code to common code Pedro Alves
2025-05-28 19:44   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 37/47] Windows GDB: make windows_thread_info be private thread_info data Pedro Alves
2025-05-28 19:52   ` Tom Tromey
2025-05-19 13:22 ` [PATCH v2 38/47] Introduce windows_nat::event_code_to_string Pedro Alves
2025-05-28 19:53   ` Tom Tromey
2025-05-19 13:23 ` [PATCH v2 39/47] Windows gdb: Add non-stop support Pedro Alves
2025-06-05 16:21   ` Tom Tromey
2025-05-19 13:23 ` [PATCH v2 40/47] Windows gdb: Eliminate invalidate_context Pedro Alves
2025-05-28 19:54   ` Tom Tromey
2025-05-19 13:23 ` [PATCH v2 41/47] Windows gdb: Watchpoints while running (internal vs external stops) Pedro Alves
2025-05-30 20:50   ` Tom Tromey
2025-05-19 13:23 ` [PATCH v2 42/47] gdb_test_multiple: Anchor prompt match if -lbl Pedro Alves
2025-05-21 15:19   ` Tom de Vries
2025-05-27 22:41     ` Pedro Alves
2025-05-27 23:20       ` Pedro Alves
2025-05-28 11:59         ` [PATCH v2] of " Pedro Alves
2025-06-05 16:37           ` Pedro Alves
2025-06-05 17:20             ` [PATCH v3] " Pedro Alves
2025-06-06  9:58               ` Tom de Vries
2025-06-06 13:53                 ` Pedro Alves
2025-05-19 13:23 ` [PATCH v2 43/47] Windows gdb: extra thread info => show exiting Pedro Alves
2025-05-28 19:58   ` Tom Tromey
2025-05-19 13:23 ` [PATCH v2 44/47] Add gdb.threads/leader-exit-schedlock.exp Pedro Alves
2025-05-29 16:09   ` Tom Tromey
2025-05-19 13:23 ` [PATCH v2 45/47] infrun: with AS+NS, prefer process exit over thread exit Pedro Alves
2025-05-19 13:23 ` [PATCH v2 46/47] Windows gdb: Always non-stop (default to "maint set target-non-stop on") Pedro Alves
2025-05-29 16:02   ` Tom Tromey
2025-05-19 13:23 ` [PATCH v2 47/47] Mention Windows scheduler-locking and non-stop support in NEWS Pedro Alves
2025-05-19 14:07   ` Eli Zaretskii
2025-06-05 17:57 ` [PATCH v2 00/47] Windows non-stop mode Tom Tromey
2025-06-11 22:06   ` [PATCH] Improve attach on Windows (was: Re: [PATCH v2 00/47] Windows non-stop mode) Pedro Alves
2026-04-02 12:21     ` [PATCH] Improve attach on Windows Pedro Alves
2026-04-02 18:52       ` Tom Tromey
2025-06-11 23:51   ` [PATCH v2 00/47] Windows non-stop mode Pedro Alves
2025-06-12 19:23     ` Tom Tromey
2025-06-13 10:34       ` Pedro Alves
2025-06-13 14:23         ` Tom Tromey

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=20250519132308.3553663-27-pedro@palves.net \
    --to=pedro@palves.net \
    --cc=gdb-patches@sourceware.org \
    /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