[PATCH 2/3] server: Set RW and LEN bits of DR7 before setting DR0-DR3.

Grazvydas Ignotas notasas at gmail.com
Fri Jul 15 15:19:10 CDT 2011


Linux 2.6.33+ started validating debug register writes. Wine writes
debug registers in order, which means that at the time address is
being written, LEN could be set to a size that requires alignment
not valid for the new address, which is then rejected by kernel.

Addresses must be aligned according to Intel manuals, and the kernel
recently started enforcing it.
---
 dlls/ntdll/tests/exception.c |    2 --
 server/ptrace.c              |    3 +++
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 194bfae..9f80651 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -509,12 +509,10 @@ static void check_debug_registers(int test_num, const struct dbgreg_test *test)
 
     CHECK_DEBUG_REG(0, ~0);
     CHECK_DEBUG_REG(1, ~0);
-if (test_num == 2) todo_wine
     CHECK_DEBUG_REG(2, ~0);
 if (test_num == 2) todo_wine
     CHECK_DEBUG_REG(3, ~0);
     CHECK_DEBUG_REG(6, 0x0f);
-if (test_num == 2) todo_wine
     CHECK_DEBUG_REG(7, ~0xdc00);
 }
 
diff --git a/server/ptrace.c b/server/ptrace.c
index 69747ed..6df9555 100644
--- a/server/ptrace.c
+++ b/server/ptrace.c
@@ -593,6 +593,8 @@ void set_thread_context( struct thread *thread, const context_t *context, unsign
     switch (context->cpu)
     {
     case CPU_x86:
+        /* Linux 2.6.33+ does DR0-DR3 alignment validation, so it has to know LEN bits first */
+        if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->debug.i386_regs.dr7 & 0xffff0000 ) == -1) goto error;
         if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->debug.i386_regs.dr0 ) == -1) goto error;
         if (thread->context) thread->context->debug.i386_regs.dr0 = context->debug.i386_regs.dr0;
         if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->debug.i386_regs.dr1 ) == -1) goto error;
@@ -607,6 +609,7 @@ void set_thread_context( struct thread *thread, const context_t *context, unsign
         if (thread->context) thread->context->debug.i386_regs.dr7 = context->debug.i386_regs.dr7;
         break;
     case CPU_x86_64:
+        if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->debug.x86_64_regs.dr7 & 0xffff0000 ) == -1) goto error;
         if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->debug.x86_64_regs.dr0 ) == -1) goto error;
         if (thread->context) thread->context->debug.x86_64_regs.dr0 = context->debug.x86_64_regs.dr0;
         if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->debug.x86_64_regs.dr1 ) == -1) goto error;
-- 
1.7.0.4




More information about the wine-patches mailing list