[PATCH v3 3/3] ntdll: Use cached debug registers in NtGetContextThread() if hw debug breakpoints are disabled.

Paul Gofman pgofman at codeweavers.com
Thu May 27 05:16:00 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ntdll/unix/signal_i386.c   | 35 +++++++++++++++++++++--------
 dlls/ntdll/unix/signal_x86_64.c | 39 +++++++++++++++++++++++----------
 2 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index 28e95c084db..69bef162d64 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -1110,10 +1110,15 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
     struct syscall_frame *frame = x86_thread_data()->syscall_frame;
     DWORD needed_flags = context->ContextFlags & ~CONTEXT_i386;
     BOOL self = (handle == GetCurrentThread());
+    BOOL use_cached_debug_regs = FALSE;
     NTSTATUS ret;
 
-    /* debug registers require a server call */
-    if (needed_flags & CONTEXT_DEBUG_REGISTERS) self = FALSE;
+    if (self && needed_flags & CONTEXT_DEBUG_REGISTERS)
+    {
+        /* debug registers require a server call if hw breakpoints are enabled */
+        if (x86_thread_data()->dr7 & 0xff) self = FALSE;
+        else use_cached_debug_regs = TRUE;
+    }
 
     if (!self)
     {
@@ -1204,15 +1209,27 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
 
             context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
         }
-        /* update the cached version of the debug registers */
         if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386))
         {
-            x86_thread_data()->dr0 = context->Dr0;
-            x86_thread_data()->dr1 = context->Dr1;
-            x86_thread_data()->dr2 = context->Dr2;
-            x86_thread_data()->dr3 = context->Dr3;
-            x86_thread_data()->dr6 = context->Dr6;
-            x86_thread_data()->dr7 = context->Dr7;
+            if (use_cached_debug_regs)
+            {
+                context->Dr0 = x86_thread_data()->dr0;
+                context->Dr1 = x86_thread_data()->dr1;
+                context->Dr2 = x86_thread_data()->dr2;
+                context->Dr3 = x86_thread_data()->dr3;
+                context->Dr6 = x86_thread_data()->dr6;
+                context->Dr7 = x86_thread_data()->dr7;
+            }
+            else
+            {
+                /* update the cached version of the debug registers */
+                x86_thread_data()->dr0 = context->Dr0;
+                x86_thread_data()->dr1 = context->Dr1;
+                x86_thread_data()->dr2 = context->Dr2;
+                x86_thread_data()->dr3 = context->Dr3;
+                x86_thread_data()->dr6 = context->Dr6;
+                x86_thread_data()->dr7 = context->Dr7;
+            }
         }
         if ((cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX) && (xstate = xstate_from_context( context )))
         {
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 2332befdf40..448f45474b1 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -1718,18 +1718,23 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
  */
 NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
 {
-    NTSTATUS ret;
-    DWORD needed_flags;
     struct syscall_frame *frame = amd64_thread_data()->syscall_frame;
     BOOL self = (handle == GetCurrentThread());
+    BOOL use_cached_debug_regs = FALSE;
+    DWORD needed_flags;
     XSTATE *xstate;
+    NTSTATUS ret;
 
     if (!context) return STATUS_INVALID_PARAMETER;
 
     needed_flags = context->ContextFlags & ~CONTEXT_AMD64;
 
-    /* debug registers require a server call */
-    if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) self = FALSE;
+    if (self && needed_flags & CONTEXT_DEBUG_REGISTERS)
+    {
+        /* debug registers require a server call if hw breakpoints are enabled */
+        if (amd64_thread_data()->dr7 & 0xff) self = FALSE;
+        else use_cached_debug_regs = TRUE;
+    }
 
     if (!self)
     {
@@ -1812,15 +1817,27 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
             context->MxCsr = context->u.FltSave.MxCsr;
             context->ContextFlags |= CONTEXT_FLOATING_POINT;
         }
-        /* update the cached version of the debug registers */
         if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64))
         {
-            amd64_thread_data()->dr0 = context->Dr0;
-            amd64_thread_data()->dr1 = context->Dr1;
-            amd64_thread_data()->dr2 = context->Dr2;
-            amd64_thread_data()->dr3 = context->Dr3;
-            amd64_thread_data()->dr6 = context->Dr6;
-            amd64_thread_data()->dr7 = context->Dr7;
+            if (use_cached_debug_regs)
+            {
+                context->Dr0 = amd64_thread_data()->dr0;
+                context->Dr1 = amd64_thread_data()->dr1;
+                context->Dr2 = amd64_thread_data()->dr2;
+                context->Dr3 = amd64_thread_data()->dr3;
+                context->Dr6 = amd64_thread_data()->dr6;
+                context->Dr7 = amd64_thread_data()->dr7;
+            }
+            else
+            {
+                /* update the cached version of the debug registers */
+                amd64_thread_data()->dr0 = context->Dr0;
+                amd64_thread_data()->dr1 = context->Dr1;
+                amd64_thread_data()->dr2 = context->Dr2;
+                amd64_thread_data()->dr3 = context->Dr3;
+                amd64_thread_data()->dr6 = context->Dr6;
+                amd64_thread_data()->dr7 = context->Dr7;
+            }
         }
         if ((cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX) && (xstate = xstate_from_context( context )))
         {
-- 
2.31.1




More information about the wine-devel mailing list