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

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


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

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

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

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

---

 dlls/ntdll/unix/signal_arm.c | 31 +++++++++++++++++++++
 tools/winebuild/import.c     | 66 ++++++++++++++++++++++++++++++--------------
 2 files changed, 77 insertions(+), 20 deletions(-)

diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index 30f2302045..19a952b03f 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -172,6 +172,37 @@ enum arm_trap_code
     TRAP_ARM_ALIGNFLT   = 17,  /* Alignment check exception */
 };
 
+struct syscall_frame
+{
+    struct syscall_frame *prev_frame;
+    DWORD                 cpsr;
+    DWORD                 r5;
+    DWORD                 r6;
+    DWORD                 r7;
+    DWORD                 r8;
+    DWORD                 r9;
+    DWORD                 r10;
+    DWORD                 r11;
+    DWORD                 thunk_addr;
+    DWORD                 r4;
+    DWORD                 ret_addr;
+};
+
+struct arm_thread_data
+{
+    void                 *exit_frame;    /* 1d4 exit frame pointer */
+    struct syscall_frame *syscall_frame; /* 1d8 frame pointer on syscall entry */
+};
+
+C_ASSERT( sizeof(struct arm_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) );
+C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm_thread_data, exit_frame ) == 0x1d4 );
+C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm_thread_data, syscall_frame ) == 0x1d8 );
+
+static inline struct arm_thread_data *arm_thread_data(void)
+{
+    return (struct arm_thread_data *)ntdll_get_thread_data()->cpu_data;
+}
+
 
 /***********************************************************************
  *           unwind_builtin_dll
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 09cb320b5d..3819225c7c 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1561,20 +1561,45 @@ void output_syscalls( DLLSPEC *spec )
             output( "\tjmp 3b\n" );
             break;
         case CPU_ARM:
-            output( "\tldr r1, 4f\n" );
-            output( "\tcmp r0, r1\n" );
-            output( "\tbcs 2f\n" );
-            output( "\tldr r1, 3f\n");
-            output( "\tadd r1, pc\n");
-            output( "\tldr ip, [r1, r0, lsl #2]\n");
-            output( "1:\tpop {r0-r1}\n" );
-            output( "\tbx ip\n");
-            output( "2:\tpop {r0-r1}\n" );
-            output( "\tldr r0,5f\n" );
-            output( "bx lr\n" );
-            output( "3:\t.long .Lsyscall_table-1b\n" );
-            output( "4:\t.long %u\n", count );
-            output( "5:\t.long 0x%x\n", invalid_param );
+            output( "\tpush {r5-r11,lr}\n" );
+            output( "\tadd r6, sp, #40\n" );  /* stack parameters */
+            output( "\tldr r5, 8f\n" );
+            output( "\tcmp r4, r5\n" );
+            output( "\tbcs 5f\n" );
+            output( "\tsub sp, sp, #8\n" );
+            output( "\tpush {r0-r3}\n" );
+            output( "\tbl %s\n", asm_name("NtCurrentTeb") );
+            output( "\tadd r7, r0, #0x1d8\n" );  /* arm_thread_data()->syscall_frame */
+            output( "\tpop {r0-r3}\n" );
+            output( "\tldr r8, [r7]\n" );
+            output( "\tstr r8, [sp]\n" );  /* prev frame */
+            output( "\tstr sp, [r7]\n" );  /* syscall frame */
+            output( "\tmrs ip, CPSR\n" );
+            output( "\tstr ip, [sp, #4]\n" );
+            output( "\tldr r5, 7f\n");
+            output( "\tadd r5, pc\n");
+            output( "\tldrb r5, [r5, r4]\n" );  /* syscall args */
+            output( "1:\tsubs r5, #16\n" );   /* first 4 args are in registers */
+            output( "\tble 3f\n" );
+            output( "\tsub sp, r5\n" );
+            output( "\tand sp, #~7\n" );
+            output( "2:\tsubs r5, r5, #4\n" );
+            output( "\tldr ip, [r6, r5]\n" );
+            output( "\tstr ip, [sp, r5]\n" );
+            output( "\tbgt 2b\n" );
+            output( "3:\tldr r5, 6f\n");
+            output( "\tadd r5, pc\n");
+            output( "\tldr ip, [r5, r4, lsl #2]\n");  /* syscall table */
+            output( "4:\tblx ip\n");
+            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( "\tpop {r5-r11,pc}\n" );
+            output( "6:\t.long .Lsyscall_table-4b\n" );
+            output( "7:\t.long .Lsyscall_args-1b\n" );
+            output( "8:\t.long %u\n", count );
+            output( "9:\t.long 0x%x\n", invalid_param );
             break;
         case CPU_ARM64:
             output( "\tcmp x8, %u\n", count );
@@ -1658,12 +1683,13 @@ void output_syscalls( DLLSPEC *spec )
             output( "\tret\n" );
             break;
         case CPU_ARM:
-            output( "\tpush {r0-r1}\n" );
-            output( "\tldr r0, 3f\n");
-            output( "\tldr r1, 2f\n");
-            output( "\tadd r1, pc\n");
-            output( "\tldr ip, [r1]\n");
-            output( "1:\tbx ip\n");
+            output( "\tpush {r4,lr}\n" );
+            output( "\tldr r4, 3f\n");
+            output( "\tldr ip, 2f\n");
+            output( "\tadd ip, pc\n");
+            output( "\tldr ip, [ip]\n");
+            output( "1:\tblx ip\n");
+            output( "\tpop {r4,pc}\n" );
             output( "2:\t.long %s-1b\n", asm_name("__wine_syscall_dispatcher") );
             output( "3:\t.long %u\n", i );
             break;




More information about the wine-cvs mailing list