mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-19 23:28:16 +00:00
ntdll: Use a syscall thunk for NtGetContextThread().
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
15b3584603
commit
57f419993e
|
@ -219,7 +219,7 @@
|
|||
# @ stub NtFreeUserPhysicalPages
|
||||
@ stdcall -syscall NtFreeVirtualMemory(long ptr ptr long)
|
||||
@ stdcall -syscall NtFsControlFile(long long ptr ptr ptr long ptr long ptr long)
|
||||
@ stdcall -norelay NtGetContextThread(long ptr)
|
||||
@ stdcall -norelay -syscall NtGetContextThread(long ptr)
|
||||
@ stdcall -syscall NtGetCurrentProcessorNumber()
|
||||
# @ stub NtGetDevicePowerState
|
||||
@ stdcall NtGetNlsSectionPtr(long long long ptr ptr)
|
||||
|
@ -1207,7 +1207,7 @@
|
|||
# @ stub ZwFreeUserPhysicalPages
|
||||
@ stdcall -private -syscall ZwFreeVirtualMemory(long ptr ptr long) NtFreeVirtualMemory
|
||||
@ stdcall -private -syscall ZwFsControlFile(long long ptr ptr ptr long ptr long ptr long) NtFsControlFile
|
||||
@ stdcall -private -norelay ZwGetContextThread(long ptr) NtGetContextThread
|
||||
@ stdcall -private -norelay -syscall ZwGetContextThread(long ptr) NtGetContextThread
|
||||
@ stdcall -private -syscall ZwGetCurrentProcessorNumber() NtGetCurrentProcessorNumber
|
||||
# @ stub ZwGetDevicePowerState
|
||||
@ stdcall -private ZwGetNlsSectionPtr(long long long ptr ptr) NtGetNlsSectionPtr
|
||||
|
|
|
@ -331,55 +331,6 @@ __ASM_STDCALL_FUNC( RtlCaptureContext, 4,
|
|||
"ret $4" )
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* NtGetContextThread (NTDLL.@)
|
||||
* ZwGetContextThread (NTDLL.@)
|
||||
*
|
||||
* Note: we use a small assembly wrapper to save the necessary registers
|
||||
* in case we are fetching the context of the current thread.
|
||||
*/
|
||||
NTSTATUS CDECL DECLSPEC_HIDDEN __regs_NtGetContextThread( DWORD edi, DWORD esi, DWORD ebx, DWORD eflags,
|
||||
DWORD ebp, DWORD retaddr, HANDLE handle,
|
||||
CONTEXT *context )
|
||||
{
|
||||
DWORD needed_flags = context->ContextFlags & ~CONTEXT_i386;
|
||||
|
||||
/* preset the registers that we got from the asm wrapper */
|
||||
if (needed_flags & CONTEXT_INTEGER)
|
||||
{
|
||||
context->Ebx = ebx;
|
||||
context->Esi = esi;
|
||||
context->Edi = edi;
|
||||
}
|
||||
if (needed_flags & CONTEXT_CONTROL)
|
||||
{
|
||||
context->Ebp = ebp;
|
||||
context->Esp = (DWORD)&retaddr;
|
||||
context->Eip = (DWORD)NtGetContextThread + 12;
|
||||
context->EFlags = eflags;
|
||||
}
|
||||
return unix_funcs->NtGetContextThread( handle, context );
|
||||
}
|
||||
__ASM_STDCALL_FUNC( NtGetContextThread, 8,
|
||||
"pushl %ebp\n\t"
|
||||
__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
|
||||
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
|
||||
"movl %esp,%ebp\n\t"
|
||||
__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
|
||||
"pushfl\n\t"
|
||||
"pushl %ebx\n\t"
|
||||
__ASM_CFI(".cfi_rel_offset %ebx,-8\n\t")
|
||||
"pushl %esi\n\t"
|
||||
__ASM_CFI(".cfi_rel_offset %esi,-12\n\t")
|
||||
"pushl %edi\n\t"
|
||||
__ASM_CFI(".cfi_rel_offset %edi,-16\n\t")
|
||||
"call " __ASM_NAME("__regs_NtGetContextThread") "\n\t"
|
||||
"leave\n\t"
|
||||
__ASM_CFI(".cfi_def_cfa %esp,4\n\t")
|
||||
__ASM_CFI(".cfi_same_value %ebp\n\t")
|
||||
"ret $8" )
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* RtlUnwind (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -240,15 +240,3 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void)
|
|||
{
|
||||
return NtCurrentTeb()->ActiveFrame;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* NtGetContextThread (NTDLL.@)
|
||||
* ZwGetContextThread (NTDLL.@)
|
||||
*/
|
||||
#ifndef __i386__
|
||||
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||
{
|
||||
return unix_funcs->NtGetContextThread( handle, context );
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1361,7 +1361,6 @@ static double CDECL ntdll_tan( double d ) { return tan( d ); }
|
|||
static struct unix_funcs unix_funcs =
|
||||
{
|
||||
NtCurrentTeb,
|
||||
NtGetContextThread,
|
||||
DbgUiIssueRemoteBreakin,
|
||||
RtlGetSystemTimePrecise,
|
||||
RtlWaitOnAddress,
|
||||
|
|
|
@ -339,45 +339,6 @@ static unsigned int get_server_context_flags( DWORD flags )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* copy_context
|
||||
*
|
||||
* Copy a register context according to the flags.
|
||||
*/
|
||||
static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||
{
|
||||
flags &= ~CONTEXT_ARM; /* get rid of CPU id */
|
||||
if (flags & CONTEXT_CONTROL)
|
||||
{
|
||||
to->Sp = from->Sp;
|
||||
to->Lr = from->Lr;
|
||||
to->Pc = from->Pc;
|
||||
to->Cpsr = from->Cpsr;
|
||||
}
|
||||
if (flags & CONTEXT_INTEGER)
|
||||
{
|
||||
to->R0 = from->R0;
|
||||
to->R1 = from->R1;
|
||||
to->R2 = from->R2;
|
||||
to->R3 = from->R3;
|
||||
to->R4 = from->R4;
|
||||
to->R5 = from->R5;
|
||||
to->R6 = from->R6;
|
||||
to->R7 = from->R7;
|
||||
to->R8 = from->R8;
|
||||
to->R9 = from->R9;
|
||||
to->R10 = from->R10;
|
||||
to->R11 = from->R11;
|
||||
to->R12 = from->R12;
|
||||
}
|
||||
if (flags & CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
to->Fpscr = from->Fpscr;
|
||||
memcpy( to->u.D, from->u.D, sizeof(to->u.D) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* context_to_server
|
||||
*
|
||||
|
@ -512,7 +473,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|||
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
DWORD needed_flags = context->ContextFlags;
|
||||
struct syscall_frame *frame = arm_thread_data()->syscall_frame;
|
||||
DWORD needed_flags = context->ContextFlags & ~CONTEXT_ARM;
|
||||
BOOL self = (handle == GetCurrentThread());
|
||||
|
||||
if (!self)
|
||||
|
@ -525,12 +487,34 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
needed_flags &= ~context->ContextFlags;
|
||||
}
|
||||
|
||||
if (self && needed_flags)
|
||||
if (self)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
RtlCaptureContext( &ctx );
|
||||
copy_context( context, &ctx, ctx.ContextFlags & needed_flags );
|
||||
context->ContextFlags |= ctx.ContextFlags & needed_flags;
|
||||
if (needed_flags & CONTEXT_INTEGER)
|
||||
{
|
||||
context->R0 = 0;
|
||||
context->R1 = 0;
|
||||
context->R2 = 0;
|
||||
context->R3 = 0;
|
||||
context->R4 = frame->r4;
|
||||
context->R5 = frame->r5;
|
||||
context->R6 = frame->r6;
|
||||
context->R7 = frame->r7;
|
||||
context->R8 = frame->r8;
|
||||
context->R9 = frame->r9;
|
||||
context->R10 = frame->r10;
|
||||
context->R11 = frame->r11;
|
||||
context->R12 = 0;
|
||||
context->ContextFlags |= CONTEXT_INTEGER;
|
||||
}
|
||||
if (needed_flags & CONTEXT_CONTROL)
|
||||
{
|
||||
context->Sp = (DWORD)&frame->r4;
|
||||
context->Lr = frame->thunk_addr;
|
||||
context->Pc = frame->thunk_addr;
|
||||
context->Cpsr = frame->cpsr;
|
||||
context->ContextFlags |= CONTEXT_CONTROL;
|
||||
}
|
||||
if (needed_flags & CONTEXT_FLOATING_POINT) FIXME( "floating point not implemented\n" );
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -69,9 +69,7 @@
|
|||
#include "unix_private.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#ifdef HAVE_LIBUNWIND
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
* signal context platform-specific definitions
|
||||
|
@ -347,42 +345,6 @@ static unsigned int get_server_context_flags( DWORD flags )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* copy_context
|
||||
*
|
||||
* Copy a register context according to the flags.
|
||||
*/
|
||||
static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||
{
|
||||
flags &= ~CONTEXT_ARM64; /* get rid of CPU id */
|
||||
if (flags & CONTEXT_CONTROL)
|
||||
{
|
||||
to->u.s.Fp = from->u.s.Fp;
|
||||
to->u.s.Lr = from->u.s.Lr;
|
||||
to->Sp = from->Sp;
|
||||
to->Pc = from->Pc;
|
||||
to->Cpsr = from->Cpsr;
|
||||
}
|
||||
if (flags & CONTEXT_INTEGER)
|
||||
{
|
||||
memcpy( to->u.X, from->u.X, sizeof(to->u.X) );
|
||||
}
|
||||
if (flags & CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
memcpy( to->V, from->V, sizeof(to->V) );
|
||||
to->Fpcr = from->Fpcr;
|
||||
to->Fpsr = from->Fpsr;
|
||||
}
|
||||
if (flags & CONTEXT_DEBUG_REGISTERS)
|
||||
{
|
||||
memcpy( to->Bcr, from->Bcr, sizeof(to->Bcr) );
|
||||
memcpy( to->Bvr, from->Bvr, sizeof(to->Bvr) );
|
||||
memcpy( to->Wcr, from->Wcr, sizeof(to->Wcr) );
|
||||
memcpy( to->Wvr, from->Wvr, sizeof(to->Wvr) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* context_to_server
|
||||
*
|
||||
|
@ -514,7 +476,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|||
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
DWORD needed_flags = context->ContextFlags;
|
||||
struct syscall_frame *frame = arm64_thread_data()->syscall_frame;
|
||||
DWORD needed_flags = context->ContextFlags & ~CONTEXT_ARM64;
|
||||
BOOL self = (handle == GetCurrentThread());
|
||||
|
||||
if (!self)
|
||||
|
@ -527,12 +490,26 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
needed_flags &= ~context->ContextFlags;
|
||||
}
|
||||
|
||||
if (self && needed_flags)
|
||||
if (self)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
RtlCaptureContext( &ctx );
|
||||
copy_context( context, &ctx, ctx.ContextFlags & needed_flags );
|
||||
context->ContextFlags |= ctx.ContextFlags & needed_flags;
|
||||
if (needed_flags & CONTEXT_INTEGER)
|
||||
{
|
||||
memset( context->u.X, 0, sizeof(context->u.X[0]) * 18 );
|
||||
context->u.X[18] = (DWORD64)NtCurrentTeb();
|
||||
memcpy( context->u.X + 19, &frame->x19, sizeof(context->u.X[0]) * 10 );
|
||||
context->ContextFlags |= CONTEXT_INTEGER;
|
||||
}
|
||||
if (needed_flags & CONTEXT_CONTROL)
|
||||
{
|
||||
context->u.s.Fp = frame->x29;
|
||||
context->u.s.Lr = frame->ret_addr;
|
||||
context->Sp = (ULONG64)&frame->thunk_x29;
|
||||
context->Pc = frame->thunk_addr;
|
||||
context->Cpsr = 0;
|
||||
context->ContextFlags |= CONTEXT_CONTROL;
|
||||
}
|
||||
if (needed_flags & CONTEXT_FLOATING_POINT) FIXME( "floating point not supported\n" );
|
||||
if (needed_flags & CONTEXT_DEBUG_REGISTERS) FIXME( "debug registers not supported\n" );
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1150,6 +1150,7 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|||
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
struct syscall_frame *frame = x86_thread_data()->syscall_frame;
|
||||
DWORD needed_flags = context->ContextFlags & ~CONTEXT_i386;
|
||||
BOOL self = (handle == GetCurrentThread());
|
||||
|
||||
|
@ -1171,16 +1172,21 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
if (needed_flags & CONTEXT_INTEGER)
|
||||
{
|
||||
context->Eax = 0;
|
||||
context->Ebx = frame->ebx;
|
||||
context->Ecx = 0;
|
||||
context->Edx = 0;
|
||||
/* other registers already set from asm wrapper */
|
||||
context->Esi = frame->esi;
|
||||
context->Edi = frame->edi;
|
||||
context->ContextFlags |= CONTEXT_INTEGER;
|
||||
}
|
||||
if (needed_flags & CONTEXT_CONTROL)
|
||||
{
|
||||
context->Esp = (DWORD)&frame->thunk_addr;
|
||||
context->Ebp = frame->ebp;
|
||||
context->Eip = frame->thunk_addr;
|
||||
context->EFlags = 0x202;
|
||||
context->SegCs = get_cs();
|
||||
context->SegSs = get_ds();
|
||||
/* other registers already set from asm wrapper */
|
||||
context->ContextFlags |= CONTEXT_CONTROL;
|
||||
}
|
||||
if (needed_flags & CONTEXT_SEGMENTS)
|
||||
|
|
|
@ -1548,64 +1548,6 @@ static unsigned int get_server_context_flags( DWORD flags )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* copy_context
|
||||
*
|
||||
* Copy a register context according to the flags.
|
||||
*/
|
||||
static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||
{
|
||||
flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
|
||||
if (flags & CONTEXT_CONTROL)
|
||||
{
|
||||
to->Rbp = from->Rbp;
|
||||
to->Rip = from->Rip;
|
||||
to->Rsp = from->Rsp;
|
||||
to->SegCs = from->SegCs;
|
||||
to->SegSs = from->SegSs;
|
||||
to->EFlags = from->EFlags;
|
||||
}
|
||||
if (flags & CONTEXT_INTEGER)
|
||||
{
|
||||
to->Rax = from->Rax;
|
||||
to->Rcx = from->Rcx;
|
||||
to->Rdx = from->Rdx;
|
||||
to->Rbx = from->Rbx;
|
||||
to->Rsi = from->Rsi;
|
||||
to->Rdi = from->Rdi;
|
||||
to->R8 = from->R8;
|
||||
to->R9 = from->R9;
|
||||
to->R10 = from->R10;
|
||||
to->R11 = from->R11;
|
||||
to->R12 = from->R12;
|
||||
to->R13 = from->R13;
|
||||
to->R14 = from->R14;
|
||||
to->R15 = from->R15;
|
||||
}
|
||||
if (flags & CONTEXT_SEGMENTS)
|
||||
{
|
||||
to->SegDs = from->SegDs;
|
||||
to->SegEs = from->SegEs;
|
||||
to->SegFs = from->SegFs;
|
||||
to->SegGs = from->SegGs;
|
||||
}
|
||||
if (flags & CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
to->MxCsr = from->MxCsr;
|
||||
to->u.FltSave = from->u.FltSave;
|
||||
}
|
||||
if (flags & CONTEXT_DEBUG_REGISTERS)
|
||||
{
|
||||
to->Dr0 = from->Dr0;
|
||||
to->Dr1 = from->Dr1;
|
||||
to->Dr2 = from->Dr2;
|
||||
to->Dr3 = from->Dr3;
|
||||
to->Dr6 = from->Dr6;
|
||||
to->Dr7 = from->Dr7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* context_to_server
|
||||
*
|
||||
|
@ -1796,11 +1738,12 @@ 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());
|
||||
|
||||
if (!context) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
needed_flags = context->ContextFlags;
|
||||
needed_flags = context->ContextFlags & ~CONTEXT_AMD64;
|
||||
|
||||
/* debug registers require a server call */
|
||||
if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) self = FALSE;
|
||||
|
@ -1817,12 +1760,49 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
|
||||
if (self)
|
||||
{
|
||||
if (needed_flags)
|
||||
if (needed_flags & CONTEXT_INTEGER)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
RtlCaptureContext( &ctx );
|
||||
copy_context( context, &ctx, ctx.ContextFlags & needed_flags );
|
||||
context->ContextFlags |= ctx.ContextFlags & needed_flags;
|
||||
context->Rax = 0;
|
||||
context->Rbx = frame->rbx;
|
||||
context->Rcx = 0;
|
||||
context->Rdx = 0;
|
||||
context->Rsi = frame->rsi;
|
||||
context->Rdi = frame->rdi;
|
||||
context->R8 = 0;
|
||||
context->R9 = 0;
|
||||
context->R10 = 0;
|
||||
context->R11 = 0;
|
||||
context->R12 = frame->r12;
|
||||
context->R13 = frame->r13;
|
||||
context->R14 = frame->r14;
|
||||
context->R15 = frame->r15;
|
||||
context->ContextFlags |= CONTEXT_INTEGER;
|
||||
}
|
||||
if (needed_flags & CONTEXT_CONTROL)
|
||||
{
|
||||
context->Rsp = (ULONG64)&frame->ret_addr;
|
||||
context->Rbp = frame->rbp;
|
||||
context->Rip = frame->thunk_addr;
|
||||
context->EFlags = 0x202;
|
||||
__asm__( "movw %%cs,%0" : "=g" (context->SegCs) );
|
||||
__asm__( "movw %%ss,%0" : "=g" (context->SegSs) );
|
||||
context->ContextFlags |= CONTEXT_CONTROL;
|
||||
}
|
||||
if (needed_flags & CONTEXT_SEGMENTS)
|
||||
{
|
||||
__asm__( "movw %%ds,%0" : "=g" (context->SegDs) );
|
||||
__asm__( "movw %%es,%0" : "=g" (context->SegEs) );
|
||||
__asm__( "movw %%fs,%0" : "=g" (context->SegFs) );
|
||||
__asm__( "movw %%gs,%0" : "=g" (context->SegGs) );
|
||||
context->ContextFlags |= CONTEXT_SEGMENTS;
|
||||
}
|
||||
if (needed_flags & CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
__asm__( "fxsave %0" : "=m" (context->u.FltSave) );
|
||||
context->MxCsr = frame->mxcsr;
|
||||
memset( &context->u.s.Xmm0, 0, 6 * sizeof(context->u.s.Xmm0) );
|
||||
memcpy( &context->u.s.Xmm6, frame->xmm, 10 * sizeof(context->u.s.Xmm0) );
|
||||
context->ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
}
|
||||
/* update the cached version of the debug registers */
|
||||
if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64))
|
||||
|
|
|
@ -34,7 +34,6 @@ struct unix_funcs
|
|||
{
|
||||
/* Nt* functions */
|
||||
TEB * (WINAPI *NtCurrentTeb)(void);
|
||||
NTSTATUS (WINAPI *NtGetContextThread)( HANDLE handle, CONTEXT *context );
|
||||
|
||||
/* other Win32 API functions */
|
||||
NTSTATUS (WINAPI *DbgUiIssueRemoteBreakin)( HANDLE process );
|
||||
|
|
Loading…
Reference in a new issue