]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Windows gdb+gdbserver: Make current_event per-thread state
authorPedro Alves <pedro@palves.net>
Thu, 21 Oct 2021 17:16:58 +0000 (18:16 +0100)
committerPedro Alves <pedro@palves.net>
Mon, 9 Jun 2025 17:09:14 +0000 (18:09 +0100)
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
gdb/nat/windows-nat.h
gdb/windows-nat.c
gdbserver/win32-low.cc
gdbserver/win32-low.h

index fe707fff9051df11f323f9731fb859c4da24bece..53d891f65d0635654e87fdc38af40cc32a602e02 100644 (file)
@@ -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.
index 8ac16311650a5edbbf35d0838f578ec875f473ee..0b89c751e898795d51093e8c245ab0b0cad5c383 100644 (file)
@@ -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 @@ private:
 
      Return true if the exception was handled; return false otherwise.  */
 
-  bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
+  bool handle_ms_vc_exception (const DEBUG_EVENT &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
index 47a5df8df44fa8b77c5c2244d982f2f4f32d1ed7..067c3f8db39a27d9bb7819d26e48f31136b436a9 100644 (file)
@@ -109,9 +109,10 @@ DEF_ENUM_FLAGS_TYPE (windows_continue_flag, windows_continue_flags);
 struct windows_per_inferior : public windows_process_info
 {
   windows_thread_info *find_thread (ptid_t ptid) override;
-  DWORD handle_output_debug_string (struct target_waitstatus *ourstatus) override;
+  DWORD handle_output_debug_string (const DEBUG_EVENT &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);
@@ -313,7 +314,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);
 
@@ -344,7 +346,7 @@ private:
   windows_thread_info *add_thread (ptid_t ptid, HANDLE h, void *tlb,
                                   bool main_thread_p);
   void delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p);
-  DWORD fake_create_process ();
+  DWORD fake_create_process (const DEBUG_EVENT &current_event);
 
   BOOL windows_continue (DWORD continue_status, int id,
                         windows_continue_flags cont_flags = 0);
@@ -955,7 +957,7 @@ windows_per_inferior::handle_load_dll (const char *dll_name, LPVOID base)
 /* See nat/windows-nat.h.  */
 
 void
-windows_per_inferior::handle_unload_dll ()
+windows_per_inferior::handle_unload_dll (const DEBUG_EVENT &current_event)
 {
   LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
 
@@ -1018,7 +1020,8 @@ signal_event_command (const char *args, int from_tty)
 
 DWORD
 windows_per_inferior::handle_output_debug_string
-     (struct target_waitstatus *ourstatus)
+  (const DEBUG_EVENT &current_event,
+   struct target_waitstatus *ourstatus)
 {
   DWORD thread_id = 0;
 
@@ -1301,11 +1304,11 @@ windows_nat_target::windows_continue (DWORD continue_status, int id,
 /* Called in pathological case where Windows fails to send a
    CREATE_PROCESS_DEBUG_EVENT after an attach.  */
 DWORD
-windows_nat_target::fake_create_process ()
+windows_nat_target::fake_create_process (const DEBUG_EVENT &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
@@ -1314,12 +1317,11 @@ windows_nat_target::fake_create_process ()
       throw_winerror_with_name (_("OpenProcess call failed"), err);
       /*  We can not debug anything in that case.  */
     }
-  add_thread (ptid_t (windows_process.current_event.dwProcessId,
-                     windows_process.current_event.dwThreadId, 0),
-                     windows_process.current_event.u.CreateThread.hThread,
-                     windows_process.current_event.u.CreateThread.lpThreadLocalBase,
+  add_thread (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
+                     current_event.u.CreateThread.hThread,
+                     current_event.u.CreateThread.lpThreadLocalBase,
                      true /* main_thread_p */);
-  return windows_process.current_event.dwThreadId;
+  return current_event.dwThreadId;
 }
 
 void
@@ -1336,6 +1338,13 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
   if (resume_all)
     ptid = inferior_ptid;
 
+  DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
+             ptid.pid (), (unsigned) ptid.lwp (), step, sig);
+
+  /* Get currently selected thread.  */
+  th = windows_process.find_thread (inferior_ptid);
+  gdb_assert (th != nullptr);
+
   if (sig != GDB_SIGNAL_0)
     {
       /* Note it is OK to call get_last_debug_event_ptid() from the
@@ -1348,8 +1357,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
          DEBUG_EXCEPT ("Cannot continue with signal %d here.  "
                        "Not last-event thread", sig);
        }
-      else if (windows_process.current_event.dwDebugEventCode
-         != EXCEPTION_DEBUG_EVENT)
+      else if (th->last_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
        {
          DEBUG_EXCEPT ("Cannot continue with signal %d here.  "
                        "Not stopped for EXCEPTION_DEBUG_EVENT", sig);
@@ -1366,7 +1374,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
          for (const xlate_exception &x : xlate)
            if (x.us == sig)
              {
-               current_event.u.Exception.ExceptionRecord.ExceptionCode
+               th->last_event.u.Exception.ExceptionRecord.ExceptionCode
                  = x.them;
                continue_status = DBG_EXCEPTION_NOT_HANDLED;
                break;
@@ -1383,25 +1391,17 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
 
   windows_process.last_sig = GDB_SIGNAL_0;
 
-  DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
-             ptid.pid (), (unsigned) ptid.lwp (), step, sig);
-
-  /* Get context for currently selected thread.  */
-  th = windows_process.find_thread (inferior_ptid);
-  if (th)
+  windows_process.with_context (th, [&] (auto *context)
     {
-      windows_process.with_context (th, [&] (auto *context)
+      if (step)
        {
-         if (step)
-           {
-             /* Single step by setting t bit.  */
-             regcache *regcache = get_thread_regcache (inferior_thread ());
-             struct gdbarch *gdbarch = regcache->arch ();
-             fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
-             context->EFlags |= FLAG_TRACE_BIT;
-           }
-       });
-    }
+         /* Single step by setting t bit.  */
+         regcache *regcache = get_thread_regcache (inferior_thread ());
+         struct gdbarch *gdbarch = regcache->arch ();
+         fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
+         context->EFlags |= FLAG_TRACE_BIT;
+       }
+    });
 
   /* Allow continuing with the same signal that interrupted us.
      Otherwise complain.  */
@@ -1463,7 +1463,8 @@ windows_nat_target::pass_ctrlc ()
 
 ptid_t
 windows_nat_target::get_windows_debug_event
-     (int pid, struct target_waitstatus *ourstatus, target_wait_flags options)
+  (int pid, struct target_waitstatus *ourstatus, target_wait_flags options,
+   DEBUG_EVENT *current_event)
 {
   DWORD continue_status, event_code;
   DWORD thread_id = 0;
@@ -1481,7 +1482,7 @@ windows_nat_target::get_windows_debug_event
          thread_id = th->tid;
          *ourstatus = th->pending_stop.status;
          th->pending_stop.status.set_ignore ();
-         windows_process.current_event = th->pending_stop.event;
+         *current_event = th->last_event;
 
          ptid_t ptid (windows_process.process_id, thread_id);
          windows_process.invalidate_context (th.get ());
@@ -1490,7 +1491,6 @@ windows_nat_target::get_windows_debug_event
     }
 
   windows_process.last_sig = GDB_SIGNAL_0;
-  DEBUG_EVENT *current_event = &windows_process.current_event;
 
   if ((options & TARGET_WNOHANG) != 0 && !m_debug_event_pending)
     {
@@ -1498,11 +1498,11 @@ windows_nat_target::get_windows_debug_event
       return minus_one_ptid;
     }
 
-  wait_for_debug_event_main_thread (&windows_process.current_event);
+  wait_for_debug_event_main_thread (current_event);
 
   continue_status = DBG_CONTINUE;
 
-  event_code = windows_process.current_event.dwDebugEventCode;
+  event_code = current_event->dwDebugEventCode;
   ourstatus->set_spurious ();
 
   switch (event_code)
@@ -1520,7 +1520,7 @@ windows_nat_target::get_windows_debug_event
              /* Kludge around a Windows bug where first event is a create
                 thread event.  Caused when attached process does not have
                 a main thread.  */
-             thread_id = fake_create_process ();
+             thread_id = fake_create_process (*current_event);
              if (thread_id)
                windows_process.saw_create++;
            }
@@ -1617,7 +1617,7 @@ windows_nat_target::get_windows_debug_event
        break;
       try
        {
-         windows_process.dll_loaded_event ();
+         windows_process.dll_loaded_event (*current_event);
        }
       catch (const gdb_exception &ex)
        {
@@ -1637,7 +1637,7 @@ windows_nat_target::get_windows_debug_event
        break;
       try
        {
-         windows_process.handle_unload_dll ();
+         windows_process.handle_unload_dll (*current_event);
        }
       catch (const gdb_exception &ex)
        {
@@ -1654,7 +1654,8 @@ windows_nat_target::get_windows_debug_event
                    "EXCEPTION_DEBUG_EVENT");
       if (windows_process.saw_create != 1)
        break;
-      switch (windows_process.handle_exception (ourstatus, debug_exceptions))
+      switch (windows_process.handle_exception (*current_event,
+                                               ourstatus, debug_exceptions))
        {
        case HANDLE_EXCEPTION_UNHANDLED:
        default:
@@ -1676,7 +1677,8 @@ windows_nat_target::get_windows_debug_event
                    "OUTPUT_DEBUG_STRING_EVENT");
       if (windows_process.saw_create != 1)
        break;
-      thread_id = windows_process.handle_output_debug_string (ourstatus);
+      thread_id = windows_process.handle_output_debug_string (*current_event,
+                                                             ourstatus);
       break;
 
     default:
@@ -1701,6 +1703,8 @@ windows_nat_target::get_windows_debug_event
   const ptid_t ptid = ptid_t (current_event->dwProcessId, thread_id, 0);
   windows_thread_info *th = windows_process.find_thread (ptid);
 
+  th->last_event = *current_event;
+
   if (th->suspended)
     {
       /* Pending stop.  See the comment by the definition of
@@ -1719,8 +1723,8 @@ windows_nat_target::get_windows_debug_event
          th->stopped_at_software_breakpoint = true;
          th->pc_adjusted = false;
        }
+
       th->pending_stop.status = *ourstatus;
-      th->pending_stop.event = *current_event;
       ourstatus->set_ignore ();
 
       continue_last_debug_event_main_thread
@@ -1746,7 +1750,10 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
 
   while (1)
     {
-      ptid_t result = get_windows_debug_event (pid, ourstatus, options);
+      DEBUG_EVENT current_event;
+
+      ptid_t result = get_windows_debug_event (pid, ourstatus, options,
+                                              &current_event);
 
       if ((options & TARGET_WNOHANG) != 0
          && ourstatus->kind () == TARGET_WAITKIND_IGNORE)
@@ -1765,11 +1772,11 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
              windows_thread_info *th = windows_process.find_thread (result);
 
              th->stopped_at_software_breakpoint = false;
-             if (windows_process.current_event.dwDebugEventCode
+             if (current_event.dwDebugEventCode
                  == EXCEPTION_DEBUG_EVENT
-                 && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
+                 && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
                       == EXCEPTION_BREAKPOINT)
-                     || (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
+                     || (current_event.u.Exception.ExceptionRecord.ExceptionCode
                          == STATUS_WX86_BREAKPOINT))
                  && windows_process.windows_initialization_done)
                {
@@ -1810,8 +1817,6 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
   windows_process.cygwin_load_end = 0;
 #endif
   windows_process.process_id = pid;
-  memset (&windows_process.current_event, 0,
-         sizeof (windows_process.current_event));
   inf = current_inferior ();
   if (!inf->target_is_pushed (this))
     inf->push_target (this);
@@ -1857,7 +1862,10 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
          && status.kind () != TARGET_WAITKIND_SPURIOUS)
        break;
 
-      this->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
+      /* Don't use windows_nat_target::resume here because that
+        assumes that inferior_ptid points at a valid thread, and we
+        haven't switched to any thread yet.  */
+      windows_continue (DBG_CONTINUE, -1);
     }
 
   switch_to_thread (this->find_thread (last_ptid));
@@ -2133,7 +2141,7 @@ windows_nat_target::detach (inferior *inf, int from_tty)
   if (process_alive)
     do_synchronously ([&] ()
       {
-       if (!DebugActiveProcessStop (windows_process.current_event.dwProcessId))
+       if (!DebugActiveProcessStop (windows_process.process_id))
          err = (unsigned) GetLastError ();
        else
          DebugSetProcessKillOnExit (FALSE);
@@ -2144,7 +2152,7 @@ windows_nat_target::detach (inferior *inf, int from_tty)
     {
       std::string msg
        = string_printf (_("Can't detach process %u"),
-                        (unsigned) windows_process.current_event.dwProcessId);
+                        windows_process.process_id);
       throw_winerror_with_name (msg.c_str (), *err);
     }
 
@@ -2941,9 +2949,9 @@ windows_nat_target::kill ()
     {
       if (!windows_continue (DBG_CONTINUE, -1, WCONT_KILLED))
        break;
-      wait_for_debug_event_main_thread (&windows_process.current_event);
-      if (windows_process.current_event.dwDebugEventCode
-         == EXIT_PROCESS_DEBUG_EVENT)
+      DEBUG_EVENT current_event;
+      wait_for_debug_event_main_thread (&current_event);
+      if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
        break;
     }
 
index ebce67cd72df0330818d6ef2f83d2ef6d483047d..a4000980f67b2221ebbe141a01a8f4522f323c96 100644 (file)
@@ -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",
index b170eb898f6df08ec1eeda9cc2ece62bef04afa2..1891f82b04633d59641d893b33faf4eeb25dfc98 100644 (file)
@@ -182,9 +182,10 @@ public:
 struct gdbserver_windows_process : public windows_nat::windows_process_info
 {
   windows_nat::windows_thread_info *find_thread (ptid_t ptid) override;
-  DWORD handle_output_debug_string (struct target_waitstatus *ourstatus) override;
+  DWORD handle_output_debug_string (const DEBUG_EVENT &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;