From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52213 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54346 --- dlls/ntdll/unix/signal_i386.c | 92 ++++++++++++++++++++--------------- dlls/ntdll/unix/thread.c | 2 +- 2 files changed, 55 insertions(+), 39 deletions(-)
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index d62d966f7aa..01dc618f065 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1660,13 +1660,16 @@ NTSTATUS KeUserModeCallback( ULONG id, const void *args, ULONG len, void **ret_p { struct syscall_frame *frame = x86_thread_data()->syscall_frame; void *args_data = (void *)((frame->esp - len) & ~15); + NTSTATUS status;
if ((char *)ntdll_get_thread_data()->kernel_stack + min_kernel_stack > (char *)&frame) return STATUS_STACK_OVERFLOW;
memcpy( args_data, args, len ); - return call_user_mode_callback( id, args_data, len, ret_ptr, ret_len, - pKiUserCallbackDispatcher, NtCurrentTeb() ); + status = call_user_mode_callback( id, args_data, len, ret_ptr, ret_len, + pKiUserCallbackDispatcher, NtCurrentTeb() ); + if (status == STATUS_THREAD_IS_TERMINATING) abort_thread( 0 ); + return status; }
@@ -2061,8 +2064,14 @@ static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext ) */ static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { + struct syscall_frame *frame; + init_handler( sigcontext ); - abort_thread(0); + + if (!is_inside_syscall( sigcontext ) && (frame = x86_thread_data()->syscall_frame)) + NtCallbackReturn( NULL, 0, STATUS_THREAD_IS_TERMINATING ); + + abort_thread( 0 ); }
@@ -2615,6 +2624,14 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "fwait\n" /* switch to kernel stack */ "4:\tmovl %ecx,%esp\n\t" + /* we're now on the kernel stack, stitch unwind info with previous frame */ + __ASM_CFI_CFA_IS_AT2(ebp, 0xcc, 0x06) /* frame->syscall_cfa */ + __ASM_CFI_REG_IS_AT2(esp, ebp, 0xcc, 0x06) + __ASM_CFI(".cfi_offset %eip,-4\n\t") + __ASM_CFI(".cfi_offset %ebp,-8\n\t") + __ASM_CFI(".cfi_offset %ebx,-12\n\t") + __ASM_CFI(".cfi_offset %esi,-16\n\t") + __ASM_CFI(".cfi_offset %edi,-20\n\t") "movl 0x1c(%esp),%edx\n\t" /* frame->eax */ "andl $0xfff,%edx\n\t" /* syscall number */ "cmpl 8(%ebx),%edx\n\t" /* table->ServiceLimit */ @@ -2632,13 +2649,6 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "leal -0x34(%ebp),%esp\n"
__ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") ":\t" - __ASM_CFI_CFA_IS_AT1(esp, 0x0c) - __ASM_CFI_REG_IS_AT1(esp, esp, 0x0c) - __ASM_CFI_REG_IS_AT1(eip, esp, 0x08) - __ASM_CFI_REG_IS_AT1(ebx, esp, 0x20) - __ASM_CFI_REG_IS_AT1(edi, esp, 0x2c) - __ASM_CFI_REG_IS_AT1(esi, esp, 0x30) - __ASM_CFI_REG_IS_AT1(ebp, esp, 0x34) "movl 0(%esp),%ecx\n\t" /* frame->syscall_flags + (frame->restore_flags << 16) */ "testl $0x68 << 16,%ecx\n\t" /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */ "jz 3f\n\t" @@ -2657,40 +2667,47 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "2:\tfrstor 0x40(%esp)\n\t" "fwait\n" "3:\tmovl 0x2c(%esp),%edi\n\t" - __ASM_CFI(".cfi_remember_state\n\t") - __ASM_CFI(".cfi_same_value %edi\n\t") "movl 0x30(%esp),%esi\n\t" - __ASM_CFI(".cfi_same_value %esi\n\t") "movl 0x34(%esp),%ebp\n\t" - __ASM_CFI(".cfi_same_value %ebp\n\t") "testl $0x7 << 16,%ecx\n\t" /* CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER */ "jnz 1f\n\t" "movl 0x20(%esp),%ebx\n\t" - __ASM_CFI(".cfi_remember_state\n\t") - __ASM_CFI(".cfi_same_value %ebx\n\t") "movl 0x08(%esp),%ecx\n\t" /* frame->eip */ - __ASM_CFI(".cfi_register %eip, %ecx\n\t") + /* push kernel stack cfi */ + __ASM_CFI("\t.cfi_remember_state\n") /* switch to user stack */ "movl 0x0c(%esp),%esp\n\t" /* frame->esp */ + __ASM_CFI(".cfi_def_cfa %esp,0\n\t") __ASM_CFI(".cfi_same_value %esp\n\t") + __ASM_CFI(".cfi_register %eip, %ecx\n\t") + __ASM_CFI(".cfi_undefined %ebp\n\t") + __ASM_CFI(".cfi_undefined %ebx\n\t") + __ASM_CFI(".cfi_undefined %esi\n\t") + __ASM_CFI(".cfi_undefined %edi\n\t") "pushl %ecx\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") "ret\n" + /* pop kernel stack cfi */ __ASM_CFI("\t.cfi_restore_state\n") + "1:\ttestl $0x2 << 16,%ecx\n\t" /* CONTEXT_INTEGER */ "jz 1f\n\t" "movl 0x1c(%esp),%eax\n\t" "movl 0x24(%esp),%ecx\n\t" "movl 0x28(%esp),%edx\n" "1:\tmovl 0x0c(%esp),%ebx\n\t" /* frame->esp */ - __ASM_CFI(".cfi_register %esp, %ebx\n\t") "movw 0x12(%esp),%ss\n\t" + /* push kernel stack cfi */ + __ASM_CFI("\t.cfi_remember_state\n") /* switch to user stack */ "xchgl %ebx,%esp\n\t" - __ASM_CFI(".cfi_def_cfa %esp, 0\n\t") + __ASM_CFI(".cfi_def_cfa %esp,0\n\t") __ASM_CFI(".cfi_same_value %esp\n\t") - __ASM_CFI_REG_IS_AT1(eip, ebx, 0x08) - __ASM_CFI_REG_IS_AT1(ebx, ebx, 0x20) + __ASM_CFI(".cfi_register %eip, %ecx\n\t") + __ASM_CFI(".cfi_undefined %ebp\n\t") + __ASM_CFI(".cfi_undefined %ebx\n\t") + __ASM_CFI(".cfi_undefined %esi\n\t") + __ASM_CFI(".cfi_undefined %edi\n\t") "pushl 0x04(%ebx)\n\t" /* frame->eflags */ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") "pushl 0x10(%ebx)\n\t" /* frame->cs */ @@ -2708,23 +2725,16 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "popl %ds\n\t" __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") "iret\n" + /* pop kernel stack cfi */ __ASM_CFI("\t.cfi_restore_state\n") + "6:\tmovl $0xc000000d,%eax\n\t" /* STATUS_INVALID_PARAMETER */ "jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n" __ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t" - __ASM_CFI(".cfi_remember_state\n\t") - __ASM_CFI(".cfi_def_cfa %esp, 4\n\t") - __ASM_CFI(".cfi_restore %esp\n\t") - __ASM_CFI(".cfi_restore %eip\n\t") - __ASM_CFI(".cfi_restore %ebx\n\t") - __ASM_CFI(".cfi_restore %edi\n\t") - __ASM_CFI(".cfi_restore %esi\n\t") - __ASM_CFI(".cfi_restore %ebp\n\t") "movl 8(%esp),%eax\n\t" "movl 4(%esp),%esp\n\t" - __ASM_CFI(".cfi_restore_state\n\t") "jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
@@ -2763,22 +2773,28 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, "movl 8(%esp),%edx\n\t" /* code */ /* switch to kernel stack */ "leal -16(%ecx),%esp\n\t" + /* we're now on the kernel stack, stitch unwind info with previous frame */ + __ASM_CFI_CFA_IS_AT2(esp, 0x90, 0x07) /* frame->syscall_cfa */ + __ASM_CFI_REG_IS_AT2(esp, esp, 0x90, 0x07) + __ASM_CFI(".cfi_offset %eip,-4\n\t") + __ASM_CFI(".cfi_offset %ebp,-8\n\t") + __ASM_CFI(".cfi_offset %ebx,-12\n\t") + __ASM_CFI(".cfi_offset %esi,-16\n\t") + __ASM_CFI(".cfi_offset %edi,-20\n\t") "call *(%eax,%edx,4)\n\t" "leal 16(%esp),%esp\n\t" - __ASM_CFI_CFA_IS_AT1(esp, 0x0c) - __ASM_CFI_REG_IS_AT1(esp, esp, 0x0c) - __ASM_CFI_REG_IS_AT1(eip, esp, 0x08) - __ASM_CFI_REG_IS_AT1(ebx, esp, 0x20) - __ASM_CFI_REG_IS_AT1(edi, esp, 0x2c) - __ASM_CFI_REG_IS_AT1(esi, esp, 0x30) - __ASM_CFI_REG_IS_AT1(ebp, esp, 0x34) "testw $0xffff,2(%esp)\n\t" /* frame->restore_flags */ "jnz " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t" "movl 0x08(%esp),%ecx\n\t" /* frame->eip */ - __ASM_CFI(".cfi_register %eip, %ecx\n\t") /* switch to user stack */ "movl 0x0c(%esp),%esp\n\t" /* frame->esp */ + __ASM_CFI(".cfi_def_cfa %esp,0\n\t") __ASM_CFI(".cfi_same_value %esp\n\t") + __ASM_CFI(".cfi_register %eip, %ecx\n\t") + __ASM_CFI(".cfi_undefined %ebp\n\t") + __ASM_CFI(".cfi_undefined %ebx\n\t") + __ASM_CFI(".cfi_undefined %esi\n\t") + __ASM_CFI(".cfi_undefined %edi\n\t") "pushl %ecx\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") "ret" ) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 04cdcba41ed..195dbfca470 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1405,7 +1405,7 @@ void abort_thread( int status ) pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if (InterlockedDecrement( &nb_threads ) <= 0) abort_process( status );
-#if defined(__x86_64__) +#if defined(__x86_64__) || defined(__i386__) pthread_exit_wrapper( status ); #else signal_exit_thread( status, pthread_exit_wrapper, NtCurrentTeb() );