Module: wine Branch: master Commit: 1e7e21534e6598782e77c38907573fa0e118e13b URL: https://source.winehq.org/git/wine.git/?a=commit;h=1e7e21534e6598782e77c3890...
Author: Alexandre Julliard julliard@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@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)