Module: wine Branch: refs/heads/master Commit: d2ad6f83556449bcd8a798191cfc8f0ae8b6d950 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=d2ad6f83556449bcd8a79819...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Apr 20 15:40:28 2006 +0200
ntdll: Get registers on the client side for NtGetContextThread on the current thread.
---
dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/signal_i386.c | 32 ++++++++++++++++--- dlls/ntdll/signal_powerpc.c | 11 ++++++ dlls/ntdll/signal_sparc.c | 11 ++++++ dlls/ntdll/signal_x86_64.c | 11 ++++++ dlls/ntdll/thread.c | 74 ++++++++++++++++++++++++++----------------- server/context_i386.c | 5 +-- 7 files changed, 109 insertions(+), 36 deletions(-)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 35cbd5b..fa18e46 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -32,6 +32,7 @@ #define MAX_NT_PATH_LENGTH 277 /* exceptions */ extern void wait_suspend( CONTEXT *context ); extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT ); +extern void get_cpu_context( CONTEXT *context ); extern void set_cpu_context( const CONTEXT *context );
/* debug helper */ diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 39b20d0..398dbdf 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -704,6 +704,20 @@ #endif
/*********************************************************************** + * save_fpu + * + * Save the thread FPU context. + */ +inline static void save_fpu( CONTEXT *context ) +{ +#ifdef __GNUC__ + context->ContextFlags |= CONTEXT_FLOATING_POINT; + __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) ); +#endif +} + + +/*********************************************************************** * restore_fpu * * Restore the FPU context to a sigcontext. @@ -762,10 +776,7 @@ #ifdef FPU_sig else #endif { -#ifdef __GNUC__ - context->ContextFlags |= CONTEXT_FLOATING_POINT; - __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) ); -#endif + save_fpu( context ); } }
@@ -824,6 +835,19 @@ #endif
/*********************************************************************** + * get_cpu_context + * + * Register function to get the context of the current thread. + */ +void WINAPI __regs_get_cpu_context( CONTEXT *context, CONTEXT *regs ) +{ + *context = *regs; + save_fpu( context ); +} +DEFINE_REGS_ENTRYPOINT( get_cpu_context, 4, 4 ); + + +/*********************************************************************** * set_cpu_context * * Set the new CPU context. Used by NtSetContextThread. diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 50d48d4..cbe4f80 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -269,6 +269,17 @@ #undef C
/*********************************************************************** + * get_cpu_context + * + * Get the context of the current thread. + */ +void get_cpu_context( CONTEXT *context ) +{ + FIXME("not implemented\n"); +} + + +/*********************************************************************** * set_cpu_context * * Set the new CPU context. diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c index 4ae3340..0bf8dac 100644 --- a/dlls/ntdll/signal_sparc.c +++ b/dlls/ntdll/signal_sparc.c @@ -149,6 +149,17 @@ static void restore_fpu( CONTEXT *contex
/*********************************************************************** + * get_cpu_context + * + * Get the context of the current thread. + */ +void get_cpu_context( CONTEXT *context ) +{ + FIXME("not implemented\n"); +} + + +/*********************************************************************** * set_cpu_context * * Set the new CPU context. diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 87d40b5..4ae61e7 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -199,6 +199,17 @@ static void restore_context( const CONTE
/*********************************************************************** + * get_cpu_context + * + * Get the context of the current thread. + */ +void get_cpu_context( CONTEXT *context ) +{ + FIXME("not implemented\n"); +} + + +/*********************************************************************** * set_cpu_context * * Set the new CPU context. diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index b4226f9..67e6930 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -921,47 +921,64 @@ NTSTATUS WINAPI NtGetContextThread( HAND NTSTATUS ret; CONTEXT ctx; DWORD dummy, i; - BOOL self = FALSE; + DWORD needed_flags = context->ContextFlags; + BOOL self = (handle == GetCurrentThread());
- SERVER_START_REQ( get_thread_context ) - { - req->handle = handle; - req->flags = context->ContextFlags; - req->suspend = 0; - wine_server_set_reply( req, &ctx, sizeof(ctx) ); - ret = wine_server_call( req ); - self = reply->self; - } - SERVER_END_REQ; +#ifdef __i386__ + /* on i386 debug registers always require a server call */ + if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) self = FALSE; +#endif
- if (ret == STATUS_PENDING) + if (!self) { - if (NtSuspendThread( handle, &dummy ) == STATUS_SUCCESS) + SERVER_START_REQ( get_thread_context ) + { + req->handle = handle; + req->flags = context->ContextFlags; + req->suspend = 0; + wine_server_set_reply( req, &ctx, sizeof(ctx) ); + ret = wine_server_call( req ); + self = reply->self; + } + SERVER_END_REQ; + + if (ret == STATUS_PENDING) { - for (i = 0; i < 100; i++) + if (NtSuspendThread( handle, &dummy ) == STATUS_SUCCESS) { - SERVER_START_REQ( get_thread_context ) + for (i = 0; i < 100; i++) { - req->handle = handle; - req->flags = context->ContextFlags; - req->suspend = 0; - wine_server_set_reply( req, &ctx, sizeof(ctx) ); - ret = wine_server_call( req ); + SERVER_START_REQ( get_thread_context ) + { + req->handle = handle; + req->flags = context->ContextFlags; + req->suspend = 0; + wine_server_set_reply( req, &ctx, sizeof(ctx) ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + if (ret != STATUS_PENDING) break; + NtYieldExecution(); } - SERVER_END_REQ; - if (ret != STATUS_PENDING) break; - NtYieldExecution(); + NtResumeThread( handle, &dummy ); } - NtResumeThread( handle, &dummy ); + if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED; } + if (ret) return ret; + copy_context( context, &ctx, context->ContextFlags & ctx.ContextFlags ); + needed_flags &= ~ctx.ContextFlags; }
- if (ret == STATUS_SUCCESS) + if (self) { - copy_context( context, &ctx, context->ContextFlags ); + if (needed_flags) + { + get_cpu_context( &ctx ); + copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); + } #ifdef __i386__ /* update the cached version of the debug registers */ - if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386))) + if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) { struct ntdll_thread_regs * const regs = ntdll_get_thread_regs(); regs->dr0 = context->Dr0; @@ -973,8 +990,7 @@ #ifdef __i386__ } #endif } - else if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED; - return ret; + return STATUS_SUCCESS; }
diff --git a/server/context_i386.c b/server/context_i386.c index ce7fd9b..0a3a329 100644 --- a/server/context_i386.c +++ b/server/context_i386.c @@ -550,10 +550,9 @@ void get_thread_context( struct thread * flags &= ~CONTEXT_i386; /* get rid of CPU id */
if (thread->context) /* thread is inside an exception event or suspended */ - { copy_context( context, thread->context, flags ); - flags &= CONTEXT_DEBUG_REGISTERS; - } + + flags &= CONTEXT_DEBUG_REGISTERS;
if (flags && suspend_for_ptrace( thread )) {