[PATCH] server: Don't fail setting hw debug registers for invalid breakpoint addresses on x64.
Paul Gofman
pgofman at codeweavers.com
Fri Jul 3 08:36:06 CDT 2020
Fixes hardware breakpoints for some debuggers.
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/ntdll/tests/exception.c | 50 +++++++++++++++++++++++++++++++-----
server/ptrace.c | 21 ++++++++++++---
2 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 95d25375f77..f98c5bdae07 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -161,6 +161,8 @@ static int (CDECL *p_setjmp)(_JUMP_BUFFER*);
static int my_argc;
static char** my_argv;
+static const BOOL is_win64 = sizeof(void *) == 8;
+
#ifdef __i386__
#ifndef __WINE_WINTRNL_H
@@ -2807,9 +2809,10 @@ static void test_debug_registers(void)
{ 0x42424240, 0, 0x126bb070, 0x0badbad0, 0, 0xffff0115 },
{ 0x42424242, 0, 0x100f0fe7, 0x0abebabe, 0, 0x115 },
};
+ BOOL is_native_win32 = !is_win64 && !is_wow64;
NTSTATUS status;
- CONTEXT ctx;
HANDLE thread;
+ CONTEXT ctx;
int i;
for (i = 0; i < ARRAY_SIZE(tests); i++)
@@ -2841,15 +2844,50 @@ static void test_debug_registers(void)
memset(&ctx, 0, sizeof(ctx));
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
- ctx.Dr0 = 0xffffffff;
- ctx.Dr1 = 0xffffffff;
- ctx.Dr2 = 0xffffffff;
- ctx.Dr3 = 0xffffffff;
+ ctx.Dr0 = 0x11111111;
+ ctx.Dr1 = 0x22222222;
+ ctx.Dr2 = 0x33333333;
+ ctx.Dr3 = 0x44444444;
ctx.Dr6 = 0xffffffff;
- ctx.Dr7 = 0x00000400;
+ ctx.Dr7 = 0x00000001;
status = pNtSetContextThread(GetCurrentThread(), &ctx);
ok(status == STATUS_SUCCESS, "NtSetContextThread failed with %x\n", status);
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ ctx.Dr0 = (ULONG_PTR)~0;
+ ctx.Dr1 = 0xf2222222;
+ ctx.Dr2 = 0xf3333333;
+ ctx.Dr3 = 0xf4444444;
+ ctx.Dr6 = 0xffffffff;
+ ctx.Dr7 = 0x00000001;
+ status = pNtSetContextThread(GetCurrentThread(), &ctx);
+ ok(status == STATUS_SUCCESS, "NtSetContextThread failed with %x\n", status);
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ status = pNtGetContextThread(GetCurrentThread(), &ctx);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %x\n", status);
+
+ todo_wine_if(is_native_win32)
+ ok(!ctx.Dr0 || (is_wow64 && ctx.Dr0 == ~0u),
+ "expected 0, got %lx\n", (DWORD_PTR)ctx.Dr0);
+
+ todo_wine_if(is_native_win32)
+ ok((!is_native_win32 && ctx.Dr1 == 0xf2222222) || (is_native_win32 && !ctx.Dr1),
+ "expected 0xf2222222, got %lx\n", (DWORD_PTR)ctx.Dr1);
+
+ todo_wine_if(is_native_win32)
+ ok((!is_native_win32 && ctx.Dr2 == 0xf3333333) || (is_native_win32 && !ctx.Dr2),
+ "expected 0xf3333333, got %lx\n", (DWORD_PTR)ctx.Dr2);
+
+ todo_wine_if(is_native_win32)
+ ok((!is_native_win32 && ctx.Dr3 == 0xf4444444) || (is_native_win32 && !ctx.Dr3),
+ "expected 0xf4444444, got %lx\n", (DWORD_PTR)ctx.Dr3);
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+
thread = CreateThread(NULL, 0, register_check_thread, NULL, CREATE_SUSPENDED, NULL);
ok(thread != INVALID_HANDLE_VALUE, "CreateThread failed with %d\n", GetLastError());
diff --git a/server/ptrace.c b/server/ptrace.c
index 49347791d8c..985559e1f39 100644
--- a/server/ptrace.c
+++ b/server/ptrace.c
@@ -648,10 +648,23 @@ void set_thread_context( struct thread *thread, const context_t *context, unsign
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 (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->debug.x86_64_regs.dr1 ) == -1) goto error;
- if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->debug.x86_64_regs.dr2 ) == -1) goto error;
- if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->debug.x86_64_regs.dr3 ) == -1) goto error;
+
+ if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->debug.x86_64_regs.dr0 ) == -1
+ && (errno != EINVAL || ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), 0 ) == -1))
+ goto error;
+
+ if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->debug.x86_64_regs.dr1 ) == -1
+ && (errno != EINVAL || ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), 0 ) == -1))
+ goto error;
+
+ if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->debug.x86_64_regs.dr2 ) == -1
+ && (errno != EINVAL || ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), 0 ) == -1))
+ goto error;
+
+ if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->debug.x86_64_regs.dr3 ) == -1
+ && (errno != EINVAL || ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), 0 ) == -1))
+ goto error;
+
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->debug.x86_64_regs.dr6 ) == -1) goto error;
ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->debug.x86_64_regs.dr7 | 0x55 );
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->debug.x86_64_regs.dr7 ) == -1) goto error;
--
2.26.2
More information about the wine-devel
mailing list