[PATCH 1/2] ntdll: Explicitly clobber X16/X17 registers on ARM64 syscall return.

Jinoh Kang jinoh.kang.kr at gmail.com
Mon Nov 8 09:41:17 CST 2021


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 at 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 );
-- 
2.33.1




More information about the wine-devel mailing list