Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: gdb-patches@sourceware.org
Subject: Re: [PATCH v2 07/47] Windows gdb: Eliminate global current_process.dr[8] global
Date: Mon, 6 Apr 2026 20:44:25 +0100	[thread overview]
Message-ID: <11ce3c82-66ea-49cc-9307-144c908e31e6@palves.net> (raw)
In-Reply-To: <20250519132308.3553663-8-pedro@palves.net>

On 2025-05-19 14:22, Pedro Alves wrote:
> current_process.dr needs to be per-thread for non-stop.  Actually, it
> doesn't even need to exist at all.

I've now rebased this patch, which required moving code around since
the x86 Windows watchpoints code meanwhile moved to new files, but all mostly
mechanical, and merged it.


> I don't understand why would windows_nat_target::resume want to call
> SetThreadContext itself.  That duplicates things as it is currently
> worrying about setting the debug registers as well.  windows_continue
> also does that, and windows_nat_target::resume always calls it.  So
> this patch simplifies windows_nat_target::resume too.

I've dropped this whole paragraph from the commit log, as meanwhile Hannes merged a
patch doing the same (commit f0f1ae77fc, "Remove duplicate code from windows_nat_target::resume").

Retested with:

  $ make check TESTS="gdb.*/*watch*.exp"

... on Cygwin.  No regressions.

Here's what I merged.

From 8de9be5a80d1ff5920e5c515571668b7cfb78ea3 Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Tue, 2 May 2023 20:42:35 +0100
Subject: [PATCH] Windows gdb: Eliminate global current_process.dr[8] global

current_process.dr needs to be per-thread for non-stop.  Actually, it
doesn't even need to exist at all.  We have x86_debug_reg_state
recording intent, and then the
cygwin_get_dr/cygwin_get_dr6/cygwin_get_dr7 functions are registered
as x86_dr_low_type vector functions, so they should return the current
value in the inferior's registers.  See this comment in x86-dregs.c:

~~~
  /* In non-stop/async, threads can be running while we change the
     global dr_mirror (and friends).  Say, we set a watchpoint, and
     let threads resume.  Now, say you delete the watchpoint, or
     add/remove watchpoints such that dr_mirror changes while threads
     are running.  On targets that support non-stop,
     inserting/deleting watchpoints updates the global dr_mirror only.
     It does not update the real thread's debug registers; that's only
     done prior to resume.  Instead, if threads are running when the
     mirror changes, a temporary and transparent stop on all threads
     is forced so they can get their copy of the debug registers
     updated on re-resume.  Now, say, a thread hit a watchpoint before
     having been updated with the new dr_mirror contents, and we
     haven't yet handled the corresponding SIGTRAP.  If we trusted
     dr_mirror below, we'd mistake the real trapped address (from the
     last time we had updated debug registers in the thread) with
     whatever was currently in dr_mirror.  So to fix this, dr_mirror
     always represents intention, what we _want_ threads to have in
     debug registers.  To get at the address and cause of the trap, we
     need to read the state the thread still has in its debug
     registers.

     In sum, always get the current debug register values the current
     thread has, instead of trusting the global mirror.  If the thread
     was running when we last changed watchpoints, the mirror no
     longer represents what was set in this thread's debug
     registers.  */
~~~

This patch makes the Windows native target follow that model as well.

Tromey pointed out that gdb/2388 mentioned in the code being removed
was moved to https://sourceware.org/bugzilla/show_bug.cgi?id=9493 in
the bugzilla migration.  I tried the reproducer mentioned there, and
it still works correctly.

Approved-By: Tom Tromey <tom@tromey.com>
Change-Id: Id762d0faa7d5e788402f2ff5adad5352447a7526
commit-id:8a975ed0
---
 gdb/nat/windows-nat.h  |  1 +
 gdb/windows-nat.c      |  1 +
 gdb/x86-windows-nat.c  | 73 ++++++++++++++++++++++--------------------
 gdbserver/win32-low.cc |  1 +
 4 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index 5411c73ff97..f4b3669df1b 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -150,6 +150,7 @@ struct windows_process_info
 {
   /* The process handle */
   HANDLE handle = 0;
+  DWORD process_id = 0;
   DWORD main_thread_id = 0;
   enum gdb_signal last_sig = GDB_SIGNAL_0;
 
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 507a25199c8..e25ae81f054 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -1235,6 +1235,7 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
   windows_process->cygwin_load_start = 0;
   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 ();
diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
index f8830809694..c7be192a894 100644
--- a/gdb/x86-windows-nat.c
+++ b/gdb/x86-windows-nat.c
@@ -44,8 +44,6 @@ enum
 
 struct x86_windows_per_inferior : public windows_per_inferior
 {
-  uintptr_t dr[8] {};
-
   /* The function to use in order to determine whether a register is
      a segment register or not.  */
   segment_register_p_ftype *segment_register_p = nullptr;
@@ -77,8 +75,6 @@ static x86_windows_per_inferior x86_windows_process;
 void
 x86_windows_nat_target::initialize_windows_arch (bool attaching)
 {
-  memset (x86_windows_process.dr, 0, sizeof (x86_windows_process.dr));
-
 #ifdef __x86_64__
   x86_windows_process.ignore_first_breakpoint
     = !attaching && x86_windows_process.wow64_process;
@@ -113,19 +109,6 @@ x86_windows_nat_target::fill_thread_context (windows_thread_info *th)
     {
       context->ContextFlags = WindowsContext<decltype(context)>::all;
       CHECK (get_thread_context (th->h, context));
-
-      /* Copy dr values from that thread.
-	 But only if there were not modified since last stop.
-	 PR gdb/2388 */
-      if (!th->debug_registers_changed)
-	{
-	  x86_windows_process.dr[0] = context->Dr0;
-	  x86_windows_process.dr[1] = context->Dr1;
-	  x86_windows_process.dr[2] = context->Dr2;
-	  x86_windows_process.dr[3] = context->Dr3;
-	  x86_windows_process.dr[6] = context->Dr6;
-	  x86_windows_process.dr[7] = context->Dr7;
-	}
     });
 }
 
@@ -137,15 +120,18 @@ x86_windows_nat_target::thread_context_continue (windows_thread_info *th,
 {
   x86_windows_process.with_context (th, [&] (auto *context)
     {
+      struct x86_debug_reg_state *state
+	= x86_debug_reg_state (windows_process->process_id);
+
       if (th->debug_registers_changed)
 	{
 	  context->ContextFlags |= WindowsContext<decltype(context)>::debug;
-	  context->Dr0 = x86_windows_process.dr[0];
-	  context->Dr1 = x86_windows_process.dr[1];
-	  context->Dr2 = x86_windows_process.dr[2];
-	  context->Dr3 = x86_windows_process.dr[3];
+	  context->Dr0 = state->dr_mirror[0];
+	  context->Dr1 = state->dr_mirror[1];
+	  context->Dr2 = state->dr_mirror[2];
+	  context->Dr3 = state->dr_mirror[3];
 	  context->Dr6 = DR6_CLEAR_VALUE;
-	  context->Dr7 = x86_windows_process.dr[7];
+	  context->Dr7 = state->dr_control_mirror;
 	  th->debug_registers_changed = false;
 	}
 
@@ -301,7 +287,6 @@ cygwin_set_dr (int i, CORE_ADDR addr)
 {
   if (i < 0 || i > 3)
     internal_error (_("Invalid register %d in cygwin_set_dr.\n"), i);
-  x86_windows_process.dr[i] = addr;
 
   for (auto &th : x86_windows_process.thread_list)
     th->debug_registers_changed = true;
@@ -313,8 +298,6 @@ cygwin_set_dr (int i, CORE_ADDR addr)
 static void
 cygwin_set_dr7 (unsigned long val)
 {
-  x86_windows_process.dr[7] = (CORE_ADDR) val;
-
   for (auto &th : x86_windows_process.thread_list)
     th->debug_registers_changed = true;
 }
@@ -324,26 +307,48 @@ cygwin_set_dr7 (unsigned long val)
 static CORE_ADDR
 cygwin_get_dr (int i)
 {
-  return x86_windows_process.dr[i];
+  windows_thread_info *th
+    = windows_process->thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
+
+  return windows_process->with_context (th, [&] (auto *context) -> CORE_ADDR
+    {
+      gdb_assert (context->ContextFlags != 0);
+      switch (i)
+	{
+	case 0:
+	  return context->Dr0;
+	case 1:
+	  return context->Dr1;
+	case 2:
+	  return context->Dr2;
+	case 3:
+	  return context->Dr3;
+	case 6:
+	  return context->Dr6;
+	case 7:
+	  return context->Dr7;
+	};
+
+      gdb_assert_not_reached ("invalid x86 dr register number: %d", i);
+    });
 }
 
-/* Get the value of the DR6 debug status register from the inferior.
-   Here we just return the value stored in dr[6]
-   by the last call to thread_rec for current_event.dwThreadId id.  */
+/* Get the value of the DR6 debug status register from the
+   inferior.  */
+
 static unsigned long
 cygwin_get_dr6 (void)
 {
-  return (unsigned long) x86_windows_process.dr[6];
+  return cygwin_get_dr (6);
 }
 
-/* Get the value of the DR7 debug status register from the inferior.
-   Here we just return the value stored in dr[7] by the last call to
-   thread_rec for current_event.dwThreadId id.  */
+/* Get the value of the DR7 debug status register from the
+   inferior.  */
 
 static unsigned long
 cygwin_get_dr7 (void)
 {
-  return (unsigned long) x86_windows_process.dr[7];
+  return cygwin_get_dr (7);
 }
 
 static int
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index b05f6af6b56..ddc5e5475ec 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -291,6 +291,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
 
   windows_process.last_sig = GDB_SIGNAL_0;
   windows_process.handle = proch;
+  windows_process.process_id = pid;
   windows_process.main_thread_id = 0;
 
   windows_process.soft_interrupt_requested = 0;

base-commit: fb1546987b21e3a63e43d4587d320fcbddf83025
-- 
2.53.0



  parent reply	other threads:[~2026-04-06 19:45 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 [this message]
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 ` [PATCH v2 26/47] Windows gdb+gdbserver: Make current_event per-thread state Pedro Alves
2025-05-28 19:30   ` 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=11ce3c82-66ea-49cc-9307-144c908e31e6@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