Commit 334f54c2 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Call Wow64PrepareForException directly from KiUserExceptionDispatcher.

This requires moving the stack switch to Wow64PrepareForException. Based on a patch by Paul Gofman.
parent ae32b2f4
...@@ -546,8 +546,6 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) ...@@ -546,8 +546,6 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
NTSTATUS status; NTSTATUS status;
DWORD c; DWORD c;
if (pWow64PrepareForException) pWow64PrepareForException( rec, context );
TRACE_(seh)( "code=%lx flags=%lx addr=%p ip=%Ix\n", TRACE_(seh)( "code=%lx flags=%lx addr=%p ip=%Ix\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, context->Rip ); rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, context->Rip );
for (c = 0; c < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); c++) for (c = 0; c < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); c++)
...@@ -610,34 +608,20 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) ...@@ -610,34 +608,20 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
} }
NTSTATUS WINAPI dispatch_wow_exception( EXCEPTION_RECORD *rec_ptr, CONTEXT *context_ptr )
{
char buffer[sizeof(CONTEXT) + sizeof(CONTEXT_EX) + sizeof(XSTATE) + 128];
CONTEXT *context;
CONTEXT_EX *context_ex;
EXCEPTION_RECORD rec = *rec_ptr;
RtlInitializeExtendedContext( buffer, context_ptr->ContextFlags, &context_ex );
context = RtlLocateLegacyContext( context_ex, NULL );
RtlCopyContext( context, context_ptr->ContextFlags, context_ptr );
return dispatch_exception( &rec, context );
}
/******************************************************************* /*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@) * KiUserExceptionDispatcher (NTDLL.@)
*/ */
__ASM_GLOBAL_FUNC( KiUserExceptionDispatcher, __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher,
"mov 0x98(%rsp),%rcx\n\t" /* context->Rsp */ "cld\n\t"
"movw %cs,%ax\n\t" /* some anticheats need this exact instruction here */
"cmpw %ax,0x38(%rsp)\n\t" /* context->SegCs */ "mov " __ASM_NAME("pWow64PrepareForException") "(%rip),%rax\n\t"
"je 1f\n\t" "test %rax,%rax\n\t"
"jz 1f\n\t"
"mov %rsp,%rdx\n\t" /* context */ "mov %rsp,%rdx\n\t" /* context */
"lea 0x4f0(%rsp),%rcx\n\t" /* rec */ "lea 0x4f0(%rsp),%rcx\n\t" /* rec */
"movq %r14,%rsp\n\t" /* switch to 64-bit stack */ "call *%rax\n"
"call " __ASM_NAME("dispatch_wow_exception") "\n\t"
"int3\n"
"1:\tmov 0xf8(%rsp),%rdx\n\t" /* context->Rip */ "1:\tmov 0xf8(%rsp),%rdx\n\t" /* context->Rip */
"mov 0x98(%rsp),%rcx\n\t" /* context->Rsp */
"mov %rdx,-0x8(%rcx)\n\t" "mov %rdx,-0x8(%rcx)\n\t"
"mov %rbp,-0x10(%rcx)\n\t" "mov %rbp,-0x10(%rcx)\n\t"
"mov %rdi,-0x18(%rcx)\n\t" "mov %rdi,-0x18(%rcx)\n\t"
......
...@@ -35,6 +35,7 @@ static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE,WOW64_CONTEXT*); ...@@ -35,6 +35,7 @@ static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE,WOW64_CONTEXT*);
static NTSTATUS (WINAPI *pRtlWow64IsWowGuestMachineSupported)(USHORT,BOOLEAN*); static NTSTATUS (WINAPI *pRtlWow64IsWowGuestMachineSupported)(USHORT,BOOLEAN*);
static NTSTATUS (WINAPI *pNtMapViewOfSectionEx)(HANDLE,HANDLE,PVOID*,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,MEM_EXTENDED_PARAMETER*,ULONG); static NTSTATUS (WINAPI *pNtMapViewOfSectionEx)(HANDLE,HANDLE,PVOID*,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,MEM_EXTENDED_PARAMETER*,ULONG);
#ifdef _WIN64 #ifdef _WIN64
static NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*);
static NTSTATUS (WINAPI *pRtlWow64GetCpuAreaInfo)(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*); static NTSTATUS (WINAPI *pRtlWow64GetCpuAreaInfo)(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*);
static NTSTATUS (WINAPI *pRtlWow64GetThreadSelectorEntry)(HANDLE,THREAD_DESCRIPTOR_INFORMATION*,ULONG,ULONG*); static NTSTATUS (WINAPI *pRtlWow64GetThreadSelectorEntry)(HANDLE,THREAD_DESCRIPTOR_INFORMATION*,ULONG,ULONG*);
static CROSS_PROCESS_WORK_ENTRY * (WINAPI *pRtlWow64PopAllCrossProcessWorkFromWorkList)(CROSS_PROCESS_WORK_HDR*,BOOLEAN*); static CROSS_PROCESS_WORK_ENTRY * (WINAPI *pRtlWow64PopAllCrossProcessWorkFromWorkList)(CROSS_PROCESS_WORK_HDR*,BOOLEAN*);
...@@ -100,6 +101,7 @@ static void init(void) ...@@ -100,6 +101,7 @@ static void init(void)
GET_PROC( RtlWow64GetThreadContext ); GET_PROC( RtlWow64GetThreadContext );
GET_PROC( RtlWow64IsWowGuestMachineSupported ); GET_PROC( RtlWow64IsWowGuestMachineSupported );
#ifdef _WIN64 #ifdef _WIN64
GET_PROC( KiUserExceptionDispatcher );
GET_PROC( RtlWow64GetCpuAreaInfo ); GET_PROC( RtlWow64GetCpuAreaInfo );
GET_PROC( RtlWow64GetThreadSelectorEntry ); GET_PROC( RtlWow64GetThreadSelectorEntry );
GET_PROC( RtlWow64PopAllCrossProcessWorkFromWorkList ); GET_PROC( RtlWow64PopAllCrossProcessWorkFromWorkList );
...@@ -909,6 +911,7 @@ static void test_peb_teb(void) ...@@ -909,6 +911,7 @@ static void test_peb_teb(void)
static void test_selectors(void) static void test_selectors(void)
{ {
#ifndef __arm__
THREAD_DESCRIPTOR_INFORMATION info; THREAD_DESCRIPTOR_INFORMATION info;
NTSTATUS status; NTSTATUS status;
ULONG base, limit, sel, retlen; ULONG base, limit, sel, retlen;
...@@ -1043,6 +1046,7 @@ static void test_selectors(void) ...@@ -1043,6 +1046,7 @@ static void test_selectors(void)
} }
} }
#undef GET_ENTRY #undef GET_ENTRY
#endif /* __arm__ */
} }
static void test_image_mappings(void) static void test_image_mappings(void)
...@@ -1384,6 +1388,20 @@ static void test_cpu_area(void) ...@@ -1384,6 +1388,20 @@ static void test_cpu_area(void)
else win_skip( "RtlWow64GetCpuAreaInfo not supported\n" ); else win_skip( "RtlWow64GetCpuAreaInfo not supported\n" );
} }
static void test_exception_dispatcher(void)
{
#ifdef __x86_64__
BYTE *code = (BYTE *)pKiUserExceptionDispatcher;
void **hook;
/* cld; mov xxx(%rip),%rax */
ok( code[0] == 0xfc && code[1] == 0x48 && code[2] == 0x8b && code[3] == 0x05,
"wrong opcodes %02x %02x %02x %02x\n", code[0], code[1], code[2], code[3] );
hook = (void **)(code + 8 + *(int *)(code + 4));
ok( !*hook, "hook %p set to %p\n", hook, *hook );
#endif
}
#else /* _WIN64 */ #else /* _WIN64 */
static const BYTE call_func64_code[] = static const BYTE call_func64_code[] =
...@@ -2122,6 +2140,40 @@ static void test_cpu_area(void) ...@@ -2122,6 +2140,40 @@ static void test_cpu_area(void)
} }
static void test_exception_dispatcher(void)
{
ULONG64 ptr, hook_ptr, hook, expect, res;
NTSTATUS status;
BYTE code[8];
if (!is_wow64) return;
if (!code_mem) return;
if (!ntdll_module) return;
ptr = get_proc_address64( ntdll_module, "KiUserExceptionDispatcher" );
ok( ptr, "KiUserExceptionDispatcher not found\n" );
if (pNtWow64ReadVirtualMemory64)
{
HANDLE process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
ok( process != 0, "failed to open current process %lu\n", GetLastError() );
status = pNtWow64ReadVirtualMemory64( process, ptr, &code, sizeof(code), &res );
ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
/* cld; mov xxx(%rip),%rax */
ok( code[0] == 0xfc && code[1] == 0x48 && code[2] == 0x8b && code[3] == 0x05,
"wrong opcodes %02x %02x %02x %02x\n", code[0], code[1], code[2], code[3] );
hook_ptr = ptr + 8 + *(int *)(code + 4);
status = pNtWow64ReadVirtualMemory64( process, hook_ptr, &hook, sizeof(hook), &res );
ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
expect = get_proc_address64( wow64_module, "Wow64PrepareForException" );
ok( hook == expect, "hook %I64x set to %I64x / %I64x\n", hook_ptr, hook, expect );
NtClose( process );
}
}
#endif /* _WIN64 */ #endif /* _WIN64 */
...@@ -2142,4 +2194,5 @@ START_TEST(wow64) ...@@ -2142,4 +2194,5 @@ START_TEST(wow64)
test_syscalls(); test_syscalls();
#endif #endif
test_cpu_area(); test_cpu_area();
test_exception_dispatcher();
} }
...@@ -101,7 +101,6 @@ static void (WINAPI *pBTCpuProcessInit)(void); ...@@ -101,7 +101,6 @@ static void (WINAPI *pBTCpuProcessInit)(void);
static NTSTATUS (WINAPI *pBTCpuSetContext)(HANDLE,HANDLE,void *,void *); static NTSTATUS (WINAPI *pBTCpuSetContext)(HANDLE,HANDLE,void *,void *);
static void (WINAPI *pBTCpuThreadInit)(void); static void (WINAPI *pBTCpuThreadInit)(void);
static void (WINAPI *pBTCpuSimulate)(void); static void (WINAPI *pBTCpuSimulate)(void);
static NTSTATUS (WINAPI *pBTCpuResetToConsistentState)( EXCEPTION_POINTERS * );
static void * (WINAPI *p__wine_get_unix_opcode)(void); static void * (WINAPI *p__wine_get_unix_opcode)(void);
static void * (WINAPI *pKiRaiseUserExceptionDispatcher)(void); static void * (WINAPI *pKiRaiseUserExceptionDispatcher)(void);
void (WINAPI *pBTCpuNotifyFlushInstructionCache2)( const void *, SIZE_T ) = NULL; void (WINAPI *pBTCpuNotifyFlushInstructionCache2)( const void *, SIZE_T ) = NULL;
...@@ -111,6 +110,7 @@ void (WINAPI *pBTCpuNotifyMemoryDirty)( void *, SIZE_T ) = NULL; ...@@ -111,6 +110,7 @@ void (WINAPI *pBTCpuNotifyMemoryDirty)( void *, SIZE_T ) = NULL;
void (WINAPI *pBTCpuNotifyMemoryFree)( void *, SIZE_T, ULONG ) = NULL; void (WINAPI *pBTCpuNotifyMemoryFree)( void *, SIZE_T, ULONG ) = NULL;
void (WINAPI *pBTCpuNotifyMemoryProtect)( void *, SIZE_T, ULONG ) = NULL; void (WINAPI *pBTCpuNotifyMemoryProtect)( void *, SIZE_T, ULONG ) = NULL;
void (WINAPI *pBTCpuNotifyUnmapViewOfSection)( void * ) = NULL; void (WINAPI *pBTCpuNotifyUnmapViewOfSection)( void * ) = NULL;
NTSTATUS (WINAPI *pBTCpuResetToConsistentState)( EXCEPTION_POINTERS * ) = NULL;
void (WINAPI *pBTCpuUpdateProcessorInformation)( SYSTEM_CPU_INFORMATION * ) = NULL; void (WINAPI *pBTCpuUpdateProcessorInformation)( SYSTEM_CPU_INFORMATION * ) = NULL;
void (WINAPI *pBTCpuThreadTerm)( HANDLE ) = NULL; void (WINAPI *pBTCpuThreadTerm)( HANDLE ) = NULL;
...@@ -1154,12 +1154,45 @@ void WINAPI Wow64LdrpInitialize( CONTEXT *context ) ...@@ -1154,12 +1154,45 @@ void WINAPI Wow64LdrpInitialize( CONTEXT *context )
/********************************************************************** /**********************************************************************
* Wow64PrepareForException (wow64.@) * Wow64PrepareForException (wow64.@)
*/ */
#ifdef __x86_64__
__ASM_GLOBAL_FUNC( Wow64PrepareForException,
"sub $0x38,%rsp\n\t"
"mov %rcx,%r10\n\t" /* rec */
"movw %cs,%ax\n\t"
"cmpw %ax,0x38(%rdx)\n\t" /* context->SegCs */
"je 1f\n\t" /* already in 64-bit mode? */
/* copy arguments to 64-bit stack */
"mov %rsp,%rsi\n\t"
"mov 0x98(%rdx),%rcx\n\t" /* context->Rsp */
"sub %rsi,%rcx\n\t" /* stack size */
"sub %rcx,%r14\n\t" /* reserve same size on 64-bit stack */
"and $~0x0f,%r14\n\t"
"mov %r14,%rdi\n\t"
"shr $3,%rcx\n\t"
"rep; movsq\n\t"
/* update arguments to point to the new stack */
"mov %r14,%rax\n\t"
"sub %rsp,%rax\n\t"
"add %rax,%r10\n\t" /* rec */
"add %rax,%rdx\n\t" /* context */
/* switch to 64-bit stack */
"mov %r14,%rsp\n"
/* build EXCEPTION_POINTERS structure and call BTCpuResetToConsistentState */
"1:\tlea 0x20(%rsp),%rcx\n\t" /* pointers */
"mov %r10,(%rcx)\n\t" /* rec */
"mov %rdx,8(%rcx)\n\t" /* context */
"mov " __ASM_NAME("pBTCpuResetToConsistentState") "(%rip),%rax\n\t"
"call *%rax\n\t"
"add $0x38,%rsp\n\t"
"ret" )
#else
void WINAPI Wow64PrepareForException( EXCEPTION_RECORD *rec, CONTEXT *context ) void WINAPI Wow64PrepareForException( EXCEPTION_RECORD *rec, CONTEXT *context )
{ {
EXCEPTION_POINTERS ptrs = { rec, context }; EXCEPTION_POINTERS ptrs = { rec, context };
pBTCpuResetToConsistentState( &ptrs ); pBTCpuResetToConsistentState( &ptrs );
} }
#endif
/********************************************************************** /**********************************************************************
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
@ stub Wow64NotifyUnsimulateComplete @ stub Wow64NotifyUnsimulateComplete
@ stdcall Wow64PassExceptionToGuest(ptr) @ stdcall Wow64PassExceptionToGuest(ptr)
@ stub Wow64PrepareForDebuggerAttach @ stub Wow64PrepareForDebuggerAttach
@ stdcall Wow64PrepareForException(ptr ptr) @ stdcall -norelay Wow64PrepareForException(ptr ptr)
@ stdcall Wow64ProcessPendingCrossProcessItems() @ stdcall Wow64ProcessPendingCrossProcessItems()
@ stdcall Wow64RaiseException(long ptr) @ stdcall Wow64RaiseException(long ptr)
@ stub Wow64ShallowThunkAllocObjectAttributes32TO64_FNC @ stub Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment