wow64: Use a .seh handler for the simulation loop.

This commit is contained in:
Alexandre Julliard 2024-02-27 16:20:55 +01:00
parent 259b92d13e
commit 89336772f8

View file

@ -940,25 +940,75 @@ NTSTATUS WINAPI Wow64SystemServiceEx( UINT num, UINT *args )
/**********************************************************************
* simulate_filter
* cpu_simulate
*/
#ifdef __aarch64__
extern void DECLSPEC_NORETURN cpu_simulate( void (*func)(void) );
__ASM_GLOBAL_FUNC( cpu_simulate,
"stp x29, x30, [sp, #-32]!\n\t"
".seh_save_fplr_x 32\n\t"
".seh_endprologue\n\t"
".seh_handler cpu_simulate_handler, @except\n\t"
"str x0, [sp, #16]\n"
".Lcpu_simulate_loop:\n\t"
"ldr x0, [sp, #16]\n\t"
"blr x0\n\t"
"b .Lcpu_simulate_loop" )
__ASM_GLOBAL_FUNC( cpu_simulate_handler,
"stp x29, x30, [sp, #-32]!\n\t"
".seh_save_fplr_x 32\n\t"
".seh_endprologue\n\t"
"mov x19, x0\n\t" /* record */
"mov x20, x1\n\t" /* frame */
"stp x0, x2, [sp, #16]\n\t" /* record, context */
"add x0, sp, #16\n\t"
"bl Wow64PassExceptionToGuest\n\t"
"mov x20, x0\n\t" /* frame */
"adr x1, .Lcpu_simulate_loop\n\t" /* target */
"mov x19, x2\n\t" /* record */
"bl RtlUnwind\n\t"
"brk #1" )
#elif defined __WINE_PE_BUILD
extern void DECLSPEC_NORETURN cpu_simulate( void (*func)(void) );
__ASM_GLOBAL_FUNC( cpu_simulate,
"subq $0x28, %rsp\n\t"
".seh_stackalloc 0x28\n\t"
".seh_endprologue\n\t"
".seh_handler cpu_simulate_handler, @except\n\t"
"movq %rcx,0x20(%rsp)\n"
".Lcpu_simulate_loop:\n\t"
"call *0x20(%rsp)\n\t"
"jmp .Lcpu_simulate_loop" )
__ASM_GLOBAL_FUNC( cpu_simulate_handler,
"subq $0x38, %rsp\n\t"
".seh_stackalloc 0x38\n\t"
".seh_endprologue\n\t"
"movq %rcx,%rsi\n\t" /* record */
"movq %rcx,0x20(%rsp)\n\t"
"movq %rdx,%rdi\n\t" /* frame */
"movq %r8,0x28(%rsp)\n\t" /* context */
"leaq 0x20(%rsp),%rcx\n\t"
"call Wow64PassExceptionToGuest\n\t"
"movq %rdi,%rcx\n\t" /* frame */
"leaq .Lcpu_simulate_loop(%rip), %rdx\n\t" /* target */
"movq %rsi,%r8\n\t" /* record */
"call RtlUnwind\n\t"
"int3" )
#else
static LONG CALLBACK simulate_filter( EXCEPTION_POINTERS *ptrs )
{
Wow64PassExceptionToGuest( ptrs );
return EXCEPTION_EXECUTE_HANDLER;
}
/**********************************************************************
* cpu_simulate
*/
static void cpu_simulate(void)
static void cpu_simulate( void (*func)(void) )
{
for (;;)
{
__TRY
{
pBTCpuSimulate();
func();
}
__EXCEPT( simulate_filter )
{
@ -967,6 +1017,7 @@ static void cpu_simulate(void)
__ENDTRY
}
}
#endif
/**********************************************************************
@ -1039,7 +1090,7 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON
ctx.Eip = pLdrSystemDllInitBlock->pKiUserApcDispatcher;
frame.wow_context = &stack->context;
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx );
cpu_simulate();
cpu_simulate( pBTCpuSimulate );
}
break;
@ -1065,7 +1116,7 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON
ctx.R3 = arg3;
frame.wow_context = &stack->context;
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx );
cpu_simulate();
cpu_simulate( pBTCpuSimulate );
}
break;
}
@ -1128,7 +1179,7 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len,
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx );
if (!__wine_setjmpex( &frame.jmpbuf, NULL ))
cpu_simulate();
cpu_simulate( pBTCpuSimulate );
else
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &orig_ctx );
}
@ -1153,7 +1204,7 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len,
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx );
if (!__wine_setjmpex( &frame.jmpbuf, NULL ))
cpu_simulate();
cpu_simulate( pBTCpuSimulate );
else
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &orig_ctx );
}
@ -1177,7 +1228,7 @@ void WINAPI Wow64LdrpInitialize( CONTEXT *context )
RtlRunOnceExecuteOnce( &init_done, process_init, NULL, NULL );
thread_init();
cpu_simulate();
cpu_simulate( pBTCpuSimulate );
}