ntdll: Use a syscall thunk for NtGetContextThread().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-07-28 13:26:48 +02:00
parent 15b3584603
commit 57f419993e
9 changed files with 104 additions and 220 deletions

View file

@ -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

View file

@ -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.@)
*/

View file

@ -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

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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))

View file

@ -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 );