Synchronize syscall_frame to match the actual state on syscall return.
This is required for a follow-up patch that addresses incorrect behaviour of __wine_syscall_dispatcher, specifically unconditional clobbering of X16 and X17 registers, while minimizing the performance impact. (Hence the "fastpath")
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/ntdll/unix/signal_arm64.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index fa402a7a83e..da5739b6f1c 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -324,6 +324,17 @@ NTSTATUS CDECL unwind_builtin_dll( ULONG type, DISPATCHER_CONTEXT *dispatch, CON }
+/*********************************************************************** + * syscall_frame_fixup_for_fastpath + * + * Clobbers the frame's X16 and X17 register values. + */ +static void syscall_frame_fixup_for_fastpath( struct syscall_frame *frame ) +{ + frame->x[16] = frame->pc; + frame->x[17] = frame->sp; +} + /*********************************************************************** * save_context * @@ -686,6 +697,7 @@ NTSTATUS call_user_apc_dispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR a frame->x[3] = arg3; frame->x[4] = (ULONG64)func; frame->restore_flags |= CONTEXT_CONTROL | CONTEXT_INTEGER; + syscall_frame_fixup_for_fastpath( frame ); return status; }
@@ -718,6 +730,7 @@ NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context frame->lr = lr; frame->sp = sp; frame->restore_flags |= CONTEXT_INTEGER | CONTEXT_CONTROL; + syscall_frame_fixup_for_fastpath( frame ); return status; }
@@ -757,6 +770,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void callback_frame.frame.restore_flags = CONTEXT_INTEGER; callback_frame.frame.syscall_table = frame->syscall_table; callback_frame.frame.prev_frame = frame; + syscall_frame_fixup_for_fastpath( &callback_frame.frame ); arm64_thread_data()->syscall_frame = &callback_frame.frame;
__wine_syscall_dispatcher_return( &callback_frame.frame, 0 ); @@ -1187,6 +1201,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B frame->prev_frame = NULL; frame->restore_flags |= CONTEXT_INTEGER; frame->syscall_table = KeServiceDescriptorTable; + syscall_frame_fixup_for_fastpath( frame );
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); __wine_syscall_dispatcher_return( frame, 0 );