Alexandre Julliard : winebuild: Store the syscall frame in the thread data on ARM64.

Alexandre Julliard julliard at winehq.org
Tue Jul 28 15:53:31 CDT 2020


Module: wine
Branch: master
Commit: 15b3584603205b93e6e6a0bace6159438ce22ffb
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=15b3584603205b93e6e6a0bace6159438ce22ffb

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Jul 28 13:03:00 2020 +0200

winebuild: Store the syscall frame in the thread data on ARM64.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_arm64.c | 19 +++++++++++---
 tools/winebuild/import.c       | 59 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c
index 2930833908..b8f1176871 100644
--- a/dlls/ntdll/unix/signal_arm64.c
+++ b/dlls/ntdll/unix/signal_arm64.c
@@ -116,18 +116,31 @@ static DWORD64 get_fault_esr( ucontext_t *sigcontext )
 
 static pthread_key_t teb_key;
 
+struct syscall_frame
+{
+    ULONG64 x29;
+    ULONG64 thunk_addr;
+    ULONG64 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    struct syscall_frame *prev_frame;
+    ULONG64 x19, x20, x21, x22, x23, x24, x25, x26, x27, x28;
+    ULONG64 thunk_x29;
+    ULONG64 ret_addr;
+};
+
 struct arm64_thread_data
 {
-    void     *exit_frame;    /* 02f0 exit frame pointer */
-    CONTEXT  *context;       /* 02f8 context to set with SIGUSR2 */
+    void                 *exit_frame;    /* 02f0 exit frame pointer */
+    struct syscall_frame *syscall_frame; /* 02f8 frame pointer on syscall entry */
+    CONTEXT              *context;       /* 0300 context to set with SIGUSR2 */
 };
 
 C_ASSERT( sizeof(struct arm64_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) );
 C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm64_thread_data, exit_frame ) == 0x2f0 );
+C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm64_thread_data, syscall_frame ) == 0x2f8 );
 
 static inline struct arm64_thread_data *arm64_thread_data(void)
 {
-    return (struct x86_thread_data *)ntdll_get_thread_data()->cpu_data;
+    return (struct arm64_thread_data *)ntdll_get_thread_data()->cpu_data;
 }
 
 
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 3819225c7c..34761ea4c5 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1594,7 +1594,7 @@ void output_syscalls( DLLSPEC *spec )
             output( "\tstr r8, [r7]\n" );  /* prev frame */
             output( "\tsub sp, r6, #40\n" );
             output( "\tpop {r5-r11,pc}\n" );
-            output( "5:\tldr r0,9f\n" );
+            output( "5:\tldr r0, 9f\n" );
             output( "\tpop {r5-r11,pc}\n" );
             output( "6:\t.long .Lsyscall_table-4b\n" );
             output( "7:\t.long .Lsyscall_args-1b\n" );
@@ -1603,12 +1603,56 @@ void output_syscalls( DLLSPEC *spec )
             break;
         case CPU_ARM64:
             output( "\tcmp x8, %u\n", count );
-            output( "\tbcs 1f\n" );
-            output( "\tadrp x16, .Lsyscall_table\n" );
+            output( "\tbcs 3f\n" );
+            output( "\tstp x29, x30, [sp,#-176]!\n" );
+            output( "\tmov x29, sp\n" );
+            output( "\tstp x27, x28, [sp, #160]\n" );
+            output( "\tstp x25, x26, [sp, #144]\n" );
+            output( "\tstp x23, x24, [sp, #128]\n" );
+            output( "\tstp x21, x22, [sp, #112]\n" );
+            output( "\tstp x19, x20, [sp, #96]\n" );
+            output( "\tstr x8, [sp, #80]\n" );
+            output( "\tstp x6, x7, [sp, #64]\n" );
+            output( "\tstp x4, x5, [sp, #48]\n" );
+            output( "\tstp x2, x3, [sp, #32]\n" );
+            output( "\tstp x0, x1, [sp, #16]\n" );
+            output( "\tbl %s\n", asm_name("NtCurrentTeb") );
+            output( "\tadd x19, x0, #0x2f8\n" );  /* arm64_thread_data()->syscall_frame */
+            output( "\tldp x0, x1, [sp, #16]\n" );
+            output( "\tldp x2, x3, [sp, #32]\n" );
+            output( "\tldp x4, x5, [sp, #48]\n" );
+            output( "\tldp x6, x7, [sp, #64]\n" );
+            output( "\tldr x8, [sp, #80]\n" );
+            output( "\tldr x20, [x19]\n" );  /* prev frame */
+            output( "\tstr x20, [sp, #88]\n" );
+            output( "\tstr x29, [x19]\n" );  /* syscall frame */
+            output( "\tadrp x16, .Lsyscall_args\n" );
+            output( "\tadd x16, x16, #:lo12:.Lsyscall_args\n" );
+            output( "\tldrb w9, [x16, x8]\n" );
+            output( "\tsubs x9, x9, #64\n" );
+            output( "\tbls 2f\n" );
+            output( "\tadd x11, x29, #192\n" );
+            output( "\tsub sp, sp, x9\n" );
+            output( "\ttbz x9, #3, 1f\n" );
+            output( "\tsub SP, SP, #8\n" );
+            output( "1:\tsub x9, x9, #8\n" );
+            output( "\tldr x10, [x11, x9]\n" );
+            output( "\tstr x10, [sp, x9]\n" );
+            output( "\tcbnz x9, 1b\n" );
+            output( "2:\tadrp x16, .Lsyscall_table\n" );
             output( "\tadd x16, x16, #:lo12:.Lsyscall_table\n" );
             output( "\tldr x16, [x16, x8, lsl 3]\n" );
-            output( "\tbr x16\n" );
-            output( "1:\tmov x0, #0x%x\n", invalid_param & 0xffff0000 );
+            output( "\tblr x16\n" );
+            output( "\tmov sp, x29\n" );
+            output( "\tstr x20, [x19]\n" );  /* prev frame */
+            output( "\tldp x19, x20, [sp, #96]\n" );
+            output( "\tldp x21, x22, [sp, #112]\n" );
+            output( "\tldp x23, x24, [sp, #128]\n" );
+            output( "\tldp x25, x26, [sp, #144]\n" );
+            output( "\tldp x27, x28, [sp, #160]\n" );
+            output( "\tldp x29, x30, [sp], #176\n" );
+            output( "\tret\n" );
+            output( "3:\tmov x0, #0x%x\n", invalid_param & 0xffff0000 );
             output( "\tmovk x0, #0x%x\n", invalid_param & 0x0000ffff );
             output( "\tret\n" );
             break;
@@ -1694,10 +1738,13 @@ void output_syscalls( DLLSPEC *spec )
             output( "3:\t.long %u\n", i );
             break;
         case CPU_ARM64:
+            output( "\tstp x29, x30, [sp,#-16]!\n" );
             output( "\tmov x8, #%u\n", i );
             output( "\tadrp x16, %s\n", asm_name("__wine_syscall_dispatcher") );
             output( "\tldr x16, [x16, #:lo12:%s]\n", asm_name("__wine_syscall_dispatcher") );
-            output( "\tbr x16\n");
+            output( "\tblr x16\n");
+            output( "\tldp x29, x30, [sp], #16\n" );
+            output( "\tret\n" );
             break;
         default:
             assert(0);




More information about the wine-cvs mailing list