]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Make gdb.threads/watchthreads.exp fetch registers of all threads
authorPedro Alves <pedro@palves.net>
Wed, 26 Jul 2023 14:32:18 +0000 (15:32 +0100)
committerPedro Alves <pedro@palves.net>
Mon, 9 Jun 2025 17:49:19 +0000 (18:49 +0100)
With this testcase change, on Cygwin, I see:

 Running /cygdrive/c/Users/alves/rocm/gdb/src/gdb/testsuite/gdb.threads/watchthreads.exp ...
 FAIL: gdb.threads/watchthreads.exp: threaded watch loop
 FAIL: gdb.threads/watchthreads.exp: combination of threaded watchpoints = 30

Change-Id: I927bfe1bb7fe8b5b0230d4afc64c4bb86e11261c

gdb/testsuite/gdb.threads/watchthreads.exp

index 49fc7626581b3ff8b6bb732a952493f2d12d461e..66bc93e34262d2d0b477b28dfe9cafefc99ac8d5 100644 (file)
@@ -62,6 +62,41 @@ for {set i 0} {$i < 30} {incr i} {
   set test_flag_0 0
   set test_flag_1 0
   set test_flag 0
+
+  # List threads to force GDB to read the registers of all threads.
+  # This exercises a problem scenario originally observed on Windows,
+  # which can potentially affect any other target.  The observed
+  # problem was:
+  #
+  # 1 - Both threads A and B hit their watchpoint.
+  #
+  # 2 - The kernel reports the event for thread A, leaving the event
+  #     for thread B pending.
+  #
+  # 3 - Due to "info threads" (or some other reason), GDB reads the
+  #     registers of thread B (including debug registers).  At this
+  #     point, the read Dr6 (status register) indicates that the
+  #     thread hit a watchpoint, but GDB hasn't seen the corresponding
+  #     event yet.
+  #
+  # 4 - The user issues "continue".  In response, GDB core re-inserts
+  #     the watchpoints, and just prior to resumption, the Windows
+  #     backend writes the debug registers back to thread B.  The
+  #     problem is that the SetThreadContext call clears Dr6, no
+  #     matter what value we write to it, losing the watchpoint hit
+  #     status.  The thread is finally resumed.
+  #
+  # 5 - The kernel reports the pending watchpoint hit event for B
+  #     (EXCEPTION_SINGLE_STEP on Windows), which gets translated to a
+  #     SIGTRAP.
+  #
+  # 6 - GDB consults Dr6 to check if the SIGTRAP is explained by a
+  #     wathpoint hit, but finds Dr6==0.
+  #
+  # 7 - GDB reports a spurious SIGTRAP to the user.
+  #
+  gdb_test -nopass "info threads" ".*"
+
   gdb_test_multiple "continue" "threaded watch loop" {
     -re "(.*Hardware watchpoint.*)$gdb_prompt $" {
        # At least one hardware watchpoint was hit.  Check if both were.