[binutils-gdb] Windows gdb+gdbserver: Make siginfo_er per-thread state

Pedro Alves via Gdb-cvs <[email protected]>
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1139a5c8e7f555cec8bef6475eef7c5209d8d166

commit 1139a5c8e7f555cec8bef6475eef7c5209d8d166
Author: Pedro Alves <[email protected]>
Date:   Mon May 22 17:33:16 2023 +0100

    Windows gdb+gdbserver: Make siginfo_er per-thread state
    
    With non-stop mode support, each thread has its own "last event", and
    so printing $_siginfo should print the siginfo of the selected thread.
    Likewise, with all-stop and scheduler-locking.
    
    This patch reworks the siginfo functions in gdb/windows-nat.c and
    gdbserver/win32-low.cc to reuse the exception record already saved
    within each thread's 'last_event' field.
    
    Here's an example of what you'll see after the whole non-stop series:
    
      (gdb) thread apply all p -pretty -- $_siginfo
    
      Thread 3 (Thread 2612.0x1470):
      $1 = {
        ExceptionCode = DBG_CONTROL_C,
        ExceptionFlags = 0,
        ExceptionRecord = 0x0,
        ExceptionAddress = 0x7ffd0583e929 <KERNELBASE!EncodeRemotePointer+8249>,
        NumberParameters = 0,
        {
          ExceptionInformation = {0 <repeats 15 times>},
          AccessViolationInformation = {
            Type = READ_ACCESS_VIOLATION,
            Address = 0x0
          }
        }
      }
    
      Thread 2 (Thread 2612.0x1704):
      $2 = {
        ExceptionCode = SINGLE_STEP,
        ExceptionFlags = 0,
        ExceptionRecord = 0x0,
        ExceptionAddress = 0x7ffd080ad6e4 <ntdll!ZwDelayExecution+20>,
        NumberParameters = 0,
        {
          ExceptionInformation = {0 <repeats 15 times>},
          AccessViolationInformation = {
            Type = READ_ACCESS_VIOLATION,
            Address = 0x0
          }
        }
      }
    
      Thread 1 (Thread 2612.0x434):
      $3 = {
        ExceptionCode = BREAKPOINT,
        ExceptionFlags = 0,
        ExceptionRecord = 0x0,
        ExceptionAddress = 0x7ff6f691174c <main+185>,
        NumberParameters = 1,
        {
          ExceptionInformation = {0 <repeats 15 times>},
          AccessViolationInformation = {
            Type = READ_ACCESS_VIOLATION,
            Address = 0x0
          }
        }
      }
      (gdb)
    
    This was in non-stop mode, and the program originally had two threads.
    Thread 1 stopped for a breakpoint, then thread 2 was manually
    interrupted/paused and then single-stepped.  And then I typed Ctrl-C
    in the inferior's terminal, which made Windows inject thread 3 in the
    inferior, and report a DBG_CONTROL_C exception for it.
    
    Approved-By: Tom Tromey <[email protected]>
    Change-Id: I5d4f1b62f59e8aef3606642c6524df2362b0fb7d
    commit-id:e0f75dea

Diff:
---
 gdb/nat/windows-nat.c  |  2 --
 gdb/nat/windows-nat.h  |  3 ---
 gdb/windows-nat.c      | 33 ++++++++++++++++-----------------
 gdbserver/win32-low.cc | 27 ++++++++++++++-------------
 4 files changed, 30 insertions(+), 35 deletions(-)

diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 7eff99170fc..1f8967dcd8d 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -357,8 +357,6 @@ windows_process_info::handle_exception (DEBUG_EVENT &current_event,
   DWORD code = rec->ExceptionCode;
   handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
 
-  memcpy (&siginfo_er, rec, sizeof siginfo_er);
-
   switch (code)
     {
     case EXCEPTION_ACCESS_VIOLATION:
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index 8555085c9f7..152410580f0 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -152,9 +152,6 @@ struct windows_process_info
   DWORD process_id = 0;
   DWORD main_thread_id = 0;
 
-  /* Contents of $_siginfo */
-  EXCEPTION_RECORD siginfo_er {};
-
 #ifdef __x86_64__
   /* The target is a WOW64 process */
   bool wow64_process = false;
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index b5e80139c26..1593524f900 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2336,7 +2336,6 @@ windows_nat_target::mourn_inferior ()
       CHECK (CloseHandle (windows_process->handle));
       windows_process->open_process_used = 0;
     }
-  windows_process->siginfo_er.ExceptionCode = 0;
   inf_child_target::mourn_inferior ();
 }
 
@@ -2453,8 +2452,15 @@ static enum target_xfer_status
 windows_xfer_siginfo (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
 		      ULONGEST *xfered_len)
 {
-  char *buf = (char *) &windows_process->siginfo_er;
-  size_t bufsize = sizeof (windows_process->siginfo_er);
+  windows_thread_info *th = windows_process->find_thread (inferior_ptid);
+
+  if (th->last_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
+    return TARGET_XFER_E_IO;
+
+  EXCEPTION_RECORD &er = th->last_event.u.Exception.ExceptionRecord;
+
+  char *buf = (char *) &er;
+  size_t bufsize = sizeof (er);
 
 #ifdef __x86_64__
   EXCEPTION_RECORD32 er32;
@@ -2463,23 +2469,16 @@ windows_xfer_siginfo (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
       buf = (char *) &er32;
       bufsize = sizeof (er32);
 
-      er32.ExceptionCode = windows_process->siginfo_er.ExceptionCode;
-      er32.ExceptionFlags = windows_process->siginfo_er.ExceptionFlags;
-      er32.ExceptionRecord
-	= (uintptr_t) windows_process->siginfo_er.ExceptionRecord;
-      er32.ExceptionAddress
-	= (uintptr_t) windows_process->siginfo_er.ExceptionAddress;
-      er32.NumberParameters = windows_process->siginfo_er.NumberParameters;
-      int i;
-      for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
-	er32.ExceptionInformation[i]
-	  = windows_process->siginfo_er.ExceptionInformation[i];
+      er32.ExceptionCode = er.ExceptionCode;
+      er32.ExceptionFlags = er.ExceptionFlags;
+      er32.ExceptionRecord = (uintptr_t) er.ExceptionRecord;
+      er32.ExceptionAddress = (uintptr_t) er.ExceptionAddress;
+      er32.NumberParameters = er.NumberParameters;
+      for (int i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
+	er32.ExceptionInformation[i] = er.ExceptionInformation[i];
     }
 #endif
 
-  if (windows_process->siginfo_er.ExceptionCode == 0)
-    return TARGET_XFER_E_IO;
-
   if (readbuf == nullptr)
     return TARGET_XFER_E_IO;
 
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 5e09779082c..cc4a63319ef 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -643,7 +643,6 @@ win32_clear_process ()
     }
 
   for_each_thread (delete_thread_info);
-  windows_process.siginfo_er.ExceptionCode = 0;
 }
 
 /* Implementation of target_ops::kill.  */
@@ -1271,14 +1270,18 @@ win32_process_target::qxfer_siginfo (const char *annex,
 				     unsigned const char *writebuf,
 				     CORE_ADDR offset, int len)
 {
-  if (windows_process.siginfo_er.ExceptionCode == 0)
+  windows_thread_info *th = windows_process.find_thread (current_thread->id);
+
+  if (th->last_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
     return -1;
 
   if (readbuf == nullptr)
     return -1;
 
-  char *buf = (char *) &windows_process.siginfo_er;
-  size_t bufsize = sizeof (windows_process.siginfo_er);
+  EXCEPTION_RECORD &er = th->last_event.u.Exception.ExceptionRecord;
+
+  char *buf = (char *) &er;
+  size_t bufsize = sizeof (er);
 
 #ifdef __x86_64__
   EXCEPTION_RECORD32 er32;
@@ -1287,17 +1290,15 @@ win32_process_target::qxfer_siginfo (const char *annex,
       buf = (char *) &er32;
       bufsize = sizeof (er32);
 
-      er32.ExceptionCode = windows_process.siginfo_er.ExceptionCode;
-      er32.ExceptionFlags = windows_process.siginfo_er.ExceptionFlags;
+      er32.ExceptionCode = er.ExceptionCode;
+      er32.ExceptionFlags = er.ExceptionFlags;
       er32.ExceptionRecord
-	= (uintptr_t) windows_process.siginfo_er.ExceptionRecord;
+	= (uintptr_t) er.ExceptionRecord;
       er32.ExceptionAddress
-	= (uintptr_t) windows_process.siginfo_er.ExceptionAddress;
-      er32.NumberParameters = windows_process.siginfo_er.NumberParameters;
-      int i;
-      for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
-	er32.ExceptionInformation[i]
-	  = windows_process.siginfo_er.ExceptionInformation[i];
+	= (uintptr_t) er.ExceptionAddress;
+      er32.NumberParameters = er.NumberParameters;
+      for (int i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
+	er32.ExceptionInformation[i] = er.ExceptionInformation[i];
     }
 #endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.