Alexandre Julliard : ntdll: Unwind the syscall frame when calling KiUserExceptionDispatcher().

Alexandre Julliard julliard at winehq.org
Tue Aug 11 16:26:50 CDT 2020


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Aug 11 14:49:34 2020 +0200

ntdll: Unwind the syscall frame when calling KiUserExceptionDispatcher().

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

---

 dlls/ntdll/unix/signal_arm.c    | 23 ++++++++++++++++++-----
 dlls/ntdll/unix/signal_arm64.c  | 26 +++++++++++++++++++++-----
 dlls/ntdll/unix/signal_i386.c   | 22 ++++++++++++++++------
 dlls/ntdll/unix/signal_x86_64.c | 10 +++++-----
 dlls/ntdll/unix/unix_private.h  |  4 ++--
 5 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index a8d25855a1..30a1f61969 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -599,11 +599,24 @@ void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
 /***********************************************************************
  *           call_user_exception_dispatcher
  */
-void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
-                                            NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) )
-{
-    dispatcher( rec, context );
-}
+__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
+                   "mov r4, r0\n\t"
+                   "mov r5, r1\n\t"
+                   "mov r6, r2\n\t"
+                   "bl " __ASM_NAME("NtCurrentTeb") "\n\t"
+                   "add r7, r0, #0x1d8\n\t"  /* arm_thread_data()->syscall_frame */
+                   "mov r0, r4\n\t"
+                   "mov r1, r5\n\t"
+                   "mov r2, r6\n\t"
+                   "ldr r3, [r7]\n\t"
+                   "ldr r4, [r3]\n\t"        /* frame->prev_frame */
+                   "str r4, [r7]\n\t"
+                   "add r3, r3, #8\n\t"
+                   "ldm r3, {r5-r11}\n\t"
+                   "ldr r4, [r3, #32]\n\t"
+                   "ldr lr, [r3, #36]\n\t"
+                   "add sp, r3, #40\n\t"
+                   "bx r2" )
 
 
 /**********************************************************************
diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c
index 36f6dfe568..b36b75972c 100644
--- a/dlls/ntdll/unix/signal_arm64.c
+++ b/dlls/ntdll/unix/signal_arm64.c
@@ -600,11 +600,27 @@ void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
 /***********************************************************************
  *           call_user_exception_dispatcher
  */
-void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
-                                            NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) )
-{
-    dispatcher( rec, context );
-}
+__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
+                   "mov x19, x0\n\t"
+                   "mov x20, x1\n\t"
+                   "mov x21, x2\n\t"
+                   "bl " __ASM_NAME("NtCurrentTeb") "\n\t"
+                   "add x4, x0, #0x2f8\n\t"        /* arm64_thread_data()->syscall_frame */
+                   "ldr x5, [x4]\n\t"
+                   "ldr x6, [x5, #88]\n\t"         /* frame->prev_frame */
+                   "str x6, [x4]\n\t"
+                   "mov x0, x19\n\t"
+                   "mov x1, x20\n\t"
+                   "mov x2, x21\n\t"
+                   "ldp x19, x20, [x5, #96]\n\t"   /* frame->x19,x20 */
+                   "ldp x21, x22, [x5, #112]\n\t"  /* frame->x21,x22 */
+                   "ldp x23, x24, [x5, #128]\n\t"  /* frame->x23,x24 */
+                   "ldp x25, x26, [x5, #144]\n\t"  /* frame->x25,x26 */
+                   "ldp x27, x28, [x5, #160]\n\t"  /* frame->x27,x28 */
+                   "ldp x29, x30, [x5, #176]\n\t"  /* frame->thunk_x29,ret_addr */
+                   "add sp, x5, #192\n\t"
+                   "br x2" )
+
 
 /**********************************************************************
  *		segv_handler
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index b929ae2990..00bb422c44 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -1559,13 +1559,23 @@ void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
  *           call_user_exception_dispatcher
  */
 __ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
-                   "add $4,%esp\n\t"
-                   "movl (%esp),%eax\n\t" /* rec */
-                   "cmpl $0x80000003,(%eax)\n\t" /* ExceptionCode */
+                   "movl 4(%esp),%edx\n\t"        /* rec */
+                   "movl 8(%esp),%ecx\n\t"        /* context */
+                   "cmpl $0x80000003,(%edx)\n\t"  /* rec->ExceptionCode */
                    "jne 1f\n\t"
-                   "movl 4(%esp),%eax\n\t" /* context */
-                   "decl 0xb8(%eax)\n\t" /* Eip */
-                   "1:\tjmp *8(%esp)")
+                   "decl 0xb8(%ecx)\n"            /* context->Eip */
+                   "1:\tmovl %fs:0x1f8,%eax\n\t"  /* x86_thread_data()->syscall_frame */
+                   "pushl (%eax)\n\t"             /* frame->prev_frame */
+                   "popl %fs:0x1f8\n\t"
+                   "movl 4(%eax),%edi\n\t"        /* frame->edi */
+                   "movl 8(%eax),%esi\n\t"        /* frame->esi */
+                   "movl 12(%eax),%ebx\n\t"       /* frame->ebx */
+                   "movl 16(%eax),%ebp\n\t"       /* frame->ebp */
+                   "movl %edx,16(%eax)\n\t"
+                   "movl %ecx,20(%eax)\n\t"
+                   "movl 12(%esp),%edx\n\t"       /* dispatcher */
+                   "leal 16(%eax),%esp\n\t"
+                   "jmp *%edx" )
 
 /**********************************************************************
  *		get_fpu_code
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 09e82c1b27..a1de881845 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -1926,15 +1926,15 @@ void WINAPI do_call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *c
                                                NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*),
                                                struct stack_layout *stack )
 {
+    struct syscall_frame *frame = amd64_thread_data()->syscall_frame;
+
     memmove(&stack->context, context, sizeof(*context));
     memcpy(&stack->rec, rec, sizeof(*rec));
 
-    if (stack->rec.ExceptionCode == EXCEPTION_BREAKPOINT)
-    {
-        /* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
-        stack->context.Rip--;
-    }
+    /* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
+    if (stack->rec.ExceptionCode == EXCEPTION_BREAKPOINT) stack->context.Rip--;
 
+    amd64_thread_data()->syscall_frame = frame->prev_frame;
     user_exception_dispatcher_trampoline( stack, dispatcher );
 }
 
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 68559269f8..7a6bb3c64a 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -260,8 +260,8 @@ extern void dbg_init(void) DECLSPEC_HIDDEN;
 
 extern void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
                                   ULONG_PTR arg2, PNTAPCFUNC func ) DECLSPEC_HIDDEN;
-extern void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
-                                                   NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) ) DECLSPEC_HIDDEN;
+extern void WINAPI DECLSPEC_NORETURN call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
+                                                                     NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) ) DECLSPEC_HIDDEN;
 
 #define TICKSPERSEC 10000000
 #define SECS_1601_TO_1970  ((369 * 365 + 89) * (ULONGLONG)86400)




More information about the wine-cvs mailing list