Module: wine Branch: master Commit: d91f16a24a95ac6116dd498211d22ca7f48e39d5 URL: https://gitlab.winehq.org/wine/wine/-/commit/d91f16a24a95ac6116dd498211d22ca...
Author: Alexandre Julliard julliard@winehq.org Date: Fri Mar 22 13:05:25 2024 +0100
wow64: Use a .seh handler for system calls.
---
dlls/wow64/syscall.c | 85 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 23 deletions(-)
diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c index 0087a684d47..a1c6fbaac5a 100644 --- a/dlls/wow64/syscall.c +++ b/dlls/wow64/syscall.c @@ -298,7 +298,7 @@ static void __attribute__((used)) call_user_exception_dispatcher( EXCEPTION_RECO /********************************************************************** * call_raise_user_exception_dispatcher */ -static void call_raise_user_exception_dispatcher( ULONG code ) +static void __attribute__((used)) call_raise_user_exception_dispatcher( ULONG code ) { TEB32 *teb32 = (TEB32 *)((char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset);
@@ -927,18 +927,66 @@ static void free_temp_data(void)
/********************************************************************** - * syscall_filter + * wow64_syscall */ -static LONG CALLBACK syscall_filter( EXCEPTION_POINTERS *ptrs ) -{ - switch (ptrs->ExceptionRecord->ExceptionCode) - { - case STATUS_INVALID_HANDLE: - call_raise_user_exception_dispatcher( ptrs->ExceptionRecord->ExceptionCode ); - break; - } - return EXCEPTION_EXECUTE_HANDLER; -} +#ifdef __aarch64__ +NTSTATUS wow64_syscall( UINT *args, ULONG_PTR thunk ); +__ASM_GLOBAL_FUNC( wow64_syscall, + "stp x29, x30, [sp, #-16]!\n\t" + ".seh_save_fplr_x 16\n\t" + ".seh_endprologue\n\t" + ".seh_handler wow64_syscall_handler, @except\n" + "blr x1\n\t" + "b 1f\n" + "wow64_syscall_ret:\n\t" + "eor w1, w0, #0xc0000000\n\t" + "cmp w1, #8\n\t" /* STATUS_INVALID_HANDLE */ + "b.ne 1f\n\t" + "bl call_raise_user_exception_dispatcher\n" + "1:\tldp x29, x30, [sp], #16\n\t" + "ret" ) +__ASM_GLOBAL_FUNC( wow64_syscall_handler, + "stp x29, x30, [sp, #-16]!\n\t" + ".seh_save_fplr_x 16\n\t" + ".seh_endprologue\n\t" + "ldr w4, [x0, #4]\n\t" /* record->ExceptionFlags */ + "tst w4, #6\n\t" /* EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND */ + "b.ne 1f\n\t" + "mov x2, x0\n\t" /* record */ + "mov x0, x1\n\t" /* frame */ + "adr x1, wow64_syscall_ret\n\t" /* target */ + "ldr w3, [x2]\n\t" /* retval = record->ExceptionCode */ + "bl RtlUnwind\n\t" + "1:\tmov w0, #1\n\t" /* ExceptionContinueSearch */ + "ldp x29, x30, [sp], #16\n\t" + "ret" ) +#else +NTSTATUS wow64_syscall( UINT *args, ULONG_PTR thunk ); +__ASM_GLOBAL_FUNC( wow64_syscall, + "subq $0x28, %rsp\n\t" + ".seh_stackalloc 0x28\n\t" + ".seh_endprologue\n\t" + ".seh_handler wow64_syscall_handler, @except\n\t" + "call *%rdx\n\t" + "jmp 1f\n" + "wow64_syscall_ret:\n\t" + "cmpl $0xc0000008,%eax\n\t" /* STATUS_INVALID_HANDLE */ + "jne 1f\n\t" + "movl %eax,%ecx\n\t" + "call call_raise_user_exception_dispatcher\n" + "1:\taddq $0x28, %rsp\n\t" + "ret" ) +__ASM_GLOBAL_FUNC( wow64_syscall_handler, + "subq $0x28,%rsp\n\t" + ".seh_stackalloc 0x28\n\t" + ".seh_endprologue\n\t" + "movl (%rcx),%r9d\n\t" /* retval = rec->ExceptionCode */ + "movq %rcx,%r8\n\t" /* rec */ + "movq %rdx,%rcx\n\t" /* frame */ + "leaq wow64_syscall_ret(%rip),%rdx\n\t" + "call RtlUnwind\n\t" + "int3" ) +#endif
/********************************************************************** @@ -950,21 +998,12 @@ NTSTATUS WINAPI Wow64SystemServiceEx( UINT num, UINT *args ) UINT id = num & 0xfff; const SYSTEM_SERVICE_TABLE *table = &syscall_tables[(num >> 12) & 3];
- if (id >= table->ServiceLimit || !table->ServiceTable[id]) + if (id >= table->ServiceLimit) { ERR( "unsupported syscall %04x\n", num ); return STATUS_INVALID_SYSTEM_SERVICE; } - __TRY - { - syscall_thunk thunk = (syscall_thunk)table->ServiceTable[id]; - status = thunk( args ); - } - __EXCEPT( syscall_filter ) - { - status = GetExceptionCode(); - } - __ENDTRY + status = wow64_syscall( args, table->ServiceTable[id] ); free_temp_data(); return status; }