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