ntdll: Get registers on the client side for NtGetContextThread on the current thread.
This commit is contained in:
parent
63ef9788dd
commit
d2ad6f8355
|
@ -32,6 +32,7 @@
|
|||
/* 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 */
|
||||
|
|
|
@ -703,6 +703,20 @@ inline static void *init_handler( const SIGCONTEXT *sigcontext, WORD *fs, WORD *
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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
|
||||
*
|
||||
|
@ -762,10 +776,7 @@ inline static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext,
|
|||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
context->ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
__asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
|
||||
#endif
|
||||
save_fpu( context );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -823,6 +834,19 @@ inline static void restore_context( const CONTEXT *context, SIGCONTEXT *sigconte
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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
|
||||
*
|
||||
|
|
|
@ -268,6 +268,17 @@ inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_cpu_context
|
||||
*
|
||||
* Get the context of the current thread.
|
||||
*/
|
||||
void get_cpu_context( CONTEXT *context )
|
||||
{
|
||||
FIXME("not implemented\n");
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* set_cpu_context
|
||||
*
|
||||
|
|
|
@ -148,6 +148,17 @@ static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_cpu_context
|
||||
*
|
||||
* Get the context of the current thread.
|
||||
*/
|
||||
void get_cpu_context( CONTEXT *context )
|
||||
{
|
||||
FIXME("not implemented\n");
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* set_cpu_context
|
||||
*
|
||||
|
|
|
@ -198,6 +198,17 @@ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_cpu_context
|
||||
*
|
||||
* Get the context of the current thread.
|
||||
*/
|
||||
void get_cpu_context( CONTEXT *context )
|
||||
{
|
||||
FIXME("not implemented\n");
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* set_cpu_context
|
||||
*
|
||||
|
|
|
@ -921,47 +921,64 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
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 )
|
||||
{
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
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();
|
||||
}
|
||||
NtResumeThread( handle, &dummy );
|
||||
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)
|
||||
{
|
||||
if (NtSuspendThread( handle, &dummy ) == STATUS_SUCCESS)
|
||||
{
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
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();
|
||||
}
|
||||
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 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
}
|
||||
#endif
|
||||
}
|
||||
else if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
|
||||
return ret;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -550,10 +550,9 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
|||
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 ))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue