Module: wine Branch: master Commit: 887332f9c7bf0d75f53f88a9739b77b12463d636 URL: https://source.winehq.org/git/wine.git/?a=commit;h=887332f9c7bf0d75f53f88a97...
Author: Paul Gofman pgofman@codeweavers.com Date: Tue Jun 30 23:34:34 2020 +0300
ntdll: Fix KiUserExceptionDispatcher ABI on x86_64.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49436 Signed-off-by: Paul Gofman pgofman@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/signal_x86_64.c | 27 ++++++++++++++++++---- dlls/ntdll/unix/signal_arm.c | 4 ++++ dlls/ntdll/unix/signal_arm64.c | 5 ++++ dlls/ntdll/unix/signal_i386.c | 4 ++++ dlls/ntdll/unix/signal_x86_64.c | 51 +++++++++++++++++++++++++---------------- dlls/ntdll/unix/thread.c | 2 +- dlls/ntdll/unix/unix_private.h | 2 ++ 7 files changed, 70 insertions(+), 25 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 3f3c449d52..b575d63857 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -530,10 +530,7 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex }
-/******************************************************************* - * KiUserExceptionDispatcher (NTDLL.@) - */ -NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ) +NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) { NTSTATUS status; DWORD c; @@ -581,6 +578,28 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte }
+/******************************************************************* + * KiUserExceptionDispatcher (NTDLL.@) + */ +__ASM_GLOBAL_FUNC( KiUserExceptionDispatcher, + "mov 0x98(%rsp),%rcx\n\t" /* context->Rsp */ + "mov 0xf8(%rsp),%rdx\n\t" /* context->Rip */ + "mov %rdx,-0x8(%rcx)\n\t" + "mov %rbp,-0x10(%rcx)\n\t" + "mov %rdi,-0x18(%rcx)\n\t" + "mov %rsi,-0x20(%rcx)\n\t" + "mov %rcx,%rbp\n\t" + "mov %rsp,%rdx\n\t" /* context */ + "lea 0x4f0(%rsp),%rcx\n\t" /* rec */ + __ASM_CFI(".cfi_signal_frame\n\t") + __ASM_CFI(".cfi_def_cfa %rbp,0\n\t") + __ASM_CFI(".cfi_rel_offset %rip,-0x8\n\t") + __ASM_CFI(".cfi_rel_offset %rbp,-0x10\n\t") + __ASM_CFI(".cfi_rel_offset %rdi,-0x18\n\t") + __ASM_CFI(".cfi_rel_offset %rsi,-0x20\n\t") + "call " __ASM_NAME("dispatch_exception") "\n\t" + "int3") + static ULONG64 get_int_reg( CONTEXT *context, int reg ) { return *(&context->Rax + reg); diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 265836499d..611d1ab819 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -531,6 +531,10 @@ static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func fun return &stack->rec; }
+void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + pKiUserExceptionDispatcher( rec, context ); +}
/********************************************************************** * raise_segv_exception diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index b15f64110d..47b52f0131 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -602,6 +602,11 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb(); }
+void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + pKiUserExceptionDispatcher( rec, context ); +} + /********************************************************************** * segv_handler * diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index ea9bfbeb3b..730d0b1cb3 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1588,6 +1588,10 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * stack->context_ptr = &stack->context; }
+void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + pKiUserExceptionDispatcher( rec, context ); +}
/********************************************************************** * get_fpu_code diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 47f3650b42..5334a4d7cc 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -233,6 +233,7 @@ typedef void (*raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context ); struct stack_layout { CONTEXT context; + ULONG64 unknown[4]; EXCEPTION_RECORD rec; ULONG64 rsi; ULONG64 rdi; @@ -241,6 +242,8 @@ struct stack_layout ULONG64 red_zone[16]; };
+C_ASSERT( sizeof(struct stack_layout) == 0x630 ); /* Should match the size in call_user_exception_dispatcher(). */ + struct amd64_thread_data { DWORD_PTR dr0; /* debug registers */ @@ -1843,16 +1846,10 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) }
-extern void CDECL raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func ); +extern void CDECL raise_func_trampoline( raise_func func ); + __ASM_GLOBAL_FUNC( raise_func_trampoline, - __ASM_CFI(".cfi_signal_frame\n\t") - __ASM_CFI(".cfi_def_cfa %rbp,160\n\t") /* red zone + rip + rbp + rdi + rsi */ - __ASM_CFI(".cfi_rel_offset %rip,24\n\t") - __ASM_CFI(".cfi_rel_offset %rbp,16\n\t") - __ASM_CFI(".cfi_rel_offset %rdi,8\n\t") - __ASM_CFI(".cfi_rel_offset %rsi,0\n\t") - "call *%r8\n\t" - "int $3") + "jmpq *%r8\n\t")
/*********************************************************************** * setup_exception @@ -1934,7 +1931,6 @@ static struct stack_layout *setup_exception( ucontext_t *sigcontext )
static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *stack ) { - ULONG64 *rsp_ptr; NTSTATUS status;
if (stack->rec.ExceptionCode == EXCEPTION_SINGLE_STEP) @@ -1962,24 +1958,39 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * return; }
- /* store return address and %rbp without aligning, so that the offset is fixed */ - rsp_ptr = (ULONG64 *)RSP_sig(sigcontext) - 16; - *(--rsp_ptr) = stack->context.Rip; - *(--rsp_ptr) = stack->context.Rbp; - *(--rsp_ptr) = stack->context.Rdi; - *(--rsp_ptr) = stack->context.Rsi; - /* now modify the sigcontext to return to the raise function */ RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; - RCX_sig(sigcontext) = (ULONG_PTR)&stack->rec; - RDX_sig(sigcontext) = (ULONG_PTR)&stack->context; R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; - RBP_sig(sigcontext) = (ULONG_PTR)rsp_ptr; RSP_sig(sigcontext) = (ULONG_PTR)stack; /* clear single-step, direction, and align check flag */ EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000); }
+extern void WINAPI user_exception_dispatcher_trampoline( struct stack_layout *stack, + void *pKiUserExceptionDispatcher ); + +__ASM_GLOBAL_FUNC( user_exception_dispatcher_trampoline, + "movq %rcx,%rsp\n\t" + "movq 0x98(%rsp),%rcx\n\t" /* context->Rsp */ + "movq 0xa0(%rsp),%rbp\n\t" + "movq 0xa8(%rsp),%rsi\n\t" + "movq 0xb0(%rsp),%rdi\n\t" + "jmpq *%rdx") + +void WINAPI do_call_user_exception_dispatcher(EXCEPTION_RECORD *rec, CONTEXT *context, struct stack_layout *stack) +{ + memcpy(&stack->context, context, sizeof(*context)); + memcpy(&stack->rec, rec, sizeof(*rec)); + + user_exception_dispatcher_trampoline( stack, pKiUserExceptionDispatcher ); +} + +__ASM_GLOBAL_FUNC( call_user_exception_dispatcher, + "movq 0x98(%rdx),%rsp\n\t" /* context->Rsp */ + "and $~0xf,%rsp\n\t" + "sub $0x630,%rsp\n\t" /* sizeof(struct stack_layout) */ + "movq %rsp,%r8\n\t" + "jmp " __ASM_NAME("do_call_user_exception_dispatcher") "\n\t")
/*********************************************************************** * is_privileged_instr diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 5f6841b0e8..686d3991b7 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -415,7 +415,7 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) NtSetContextThread( GetCurrentThread(), context );
- if (first_chance) pKiUserExceptionDispatcher( rec, context ); + if (first_chance) call_user_exception_dispatcher( rec, context );
if (rec->ExceptionFlags & EH_STACK_INVALID) ERR("Exception frame is not in stack limits => unable to dispatch exception.\n"); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 4f93aa2c54..e6c8d5764e 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -241,6 +241,8 @@ extern void init_cpu_info(void) DECLSPEC_HIDDEN;
extern void dbg_init(void) DECLSPEC_HIDDEN;
+extern void WINAPI call_user_exception_dispatcher(EXCEPTION_RECORD *rec, CONTEXT *context) DECLSPEC_HIDDEN; + #define TICKSPERSEC 10000000 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)