Commit 0a5f7a71 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Switch to the user stack before restoring the %fs register.

Based on a patch by Rémi Bernon.
parent b5564cc1
......@@ -1596,14 +1596,14 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback,
"movl %r14d,0xb0(%rsp)\n\t" /* frame->syscall_flags */
"movq %r10,0xa0(%rsp)\n\t" /* frame->prev_frame */
"movq %rsp,0x328(%r8)\n\t" /* amd64_thread_data()->syscall_frame */
/* switch to user stack */
"movq %rdi,%rsp\n\t" /* user_rsp */
#ifdef __linux__
"testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
"jz 1f\n\t"
"movw 0x338(%r8),%fs\n" /* amd64_thread_data()->fs */
"1:\n\t"
#endif
/* switch to user stack */
"movq %rdi,%rsp\n\t" /* user_rsp */
"jmpq *%rcx" ) /* func */
......@@ -2733,12 +2733,6 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
"leaq -0x98(%rbp),%rcx\n\t"
__ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") ":\n\t"
"movl 0xb4(%rcx),%edx\n\t" /* frame->restore_flags */
#ifdef __linux__
"testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
"jz 1f\n\t"
"movw %gs:0x338,%fs\n" /* amd64_thread_data()->fs */
"1:\n\t"
#endif
"testl $0x48,%edx\n\t" /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
"jnz 2f\n\t"
"movaps 0x1c0(%rcx),%xmm6\n\t"
......@@ -2764,25 +2758,30 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
"3:\tfxrstor64 0xc0(%rcx)\n"
"4:\tmovq 0x98(%rcx),%rbp\n\t"
/* push rbp-based kernel stack cfi */
__ASM_CFI("\t.cfi_remember_state\n")
__ASM_CFI(".cfi_remember_state\n\t")
__ASM_CFI_CFA_IS_AT2(rcx, 0xa8, 0x01) /* frame->syscall_cfa */
"movq 0x68(%rcx),%r15\n\t"
"movq 0x60(%rcx),%r14\n\t"
"movq 0x58(%rcx),%r13\n\t"
"movq 0x50(%rcx),%r12\n\t"
"movq 0x80(%rcx),%r11\n\t" /* frame->eflags */
"movq 0x28(%rcx),%rdi\n\t"
"movq 0x20(%rcx),%rsi\n\t"
"movq 0x08(%rcx),%rbx\n\t"
"leaq 0x70(%rcx),%rsp\n\t" /* %rsp > frame means no longer inside syscall */
#ifdef __linux__
"testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
"jz 1f\n\t"
"movw %gs:0x338,%fs\n" /* amd64_thread_data()->fs */
"1:\n\t"
#endif
"movq 0x60(%rcx),%r14\n\t"
"testl $0x3,%edx\n\t" /* CONTEXT_CONTROL | CONTEXT_INTEGER */
"jnz 1f\n\t"
"movq 0x80(%rcx),%r11\n\t" /* frame->eflags */
"pushq %r11\n\t"
"popfq\n\t"
/* switch to user stack */
"movq 0x88(%rcx),%rsp\n\t"
/* push rcx-based kernel stack cfi */
__ASM_CFI("\t.cfi_remember_state\n")
__ASM_CFI(".cfi_remember_state\n\t")
__ASM_CFI(".cfi_def_cfa %rsp, 0\n\t")
__ASM_CFI_REG_IS_AT2(rip, rcx, 0xf0, 0x00)
__ASM_CFI(".cfi_same_value %rbp\n\t")
......@@ -2795,16 +2794,18 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
__ASM_CFI(".cfi_same_value %rsi\n\t")
"movq 0x70(%rcx),%rcx\n\t" /* frame->rip */
__ASM_CFI(".cfi_register rip, rcx\n\t")
"pushq %r11\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
"popfq\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
"pushq %rcx\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
"ret\n\t"
/* pop rcx-based kernel stack cfi */
__ASM_CFI("\t.cfi_restore_state\n")
__ASM_CFI(".cfi_restore_state\n")
"1:\tleaq 0x70(%rcx),%rsp\n\t"
"testl $0x2,%edx\n\t" /* CONTEXT_INTEGER */
"1:\ttestl $0x2,%edx\n\t" /* CONTEXT_INTEGER */
"jnz 1f\n\t"
"movq 0x10(%rsp),%r11\n\t" /* frame->eflags */
"movq (%rsp),%rcx\n\t" /* frame->rip */
"iretq\n"
"1:\tmovq 0x00(%rcx),%rax\n\t"
......@@ -2813,7 +2814,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
"movq 0x38(%rcx),%r9\n\t"
"movq 0x40(%rcx),%r10\n\t"
"movq 0x48(%rcx),%r11\n\t"
"movq 0x10(%rcx),%rcx\n"
"movq 0x10(%rcx),%rcx\n\t"
"iretq\n"
/* pop rbp-based kernel stack cfi */
......@@ -2877,6 +2878,7 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher,
/* switch to kernel stack */
"movq %rcx,%rsp\n\t"
/* we're now on the kernel stack, stitch unwind info with previous frame */
__ASM_CFI(".cfi_remember_state\n\t")
__ASM_CFI_CFA_IS_AT2(rsp, 0xa8, 0x01) /* frame->syscall_cfa */
__ASM_CFI(".cfi_offset %rip,-0x08\n\t")
__ASM_CFI(".cfi_offset %rbp,-0x10\n\t")
......@@ -2915,6 +2917,9 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher,
"movdqa 0x250(%rcx),%xmm15\n\t"
"testl $0xffff,0xb4(%rcx)\n\t" /* frame->restore_flags */
"jnz " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
/* switch to user stack */
"movq 0x88(%rcx),%rsp\n\t"
__ASM_CFI(".cfi_restore_state\n\t")
#ifdef __linux__
"testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
"jz 1f\n\t"
......@@ -2924,20 +2929,7 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher,
"movq 0x60(%rcx),%r14\n\t"
"movq 0x28(%rcx),%rdi\n\t"
"movq 0x20(%rcx),%rsi\n\t"
/* switch to user stack */
"movq 0x88(%rcx),%rsp\n\t"
__ASM_CFI(".cfi_def_cfa %rsp, 0\n\t")
__ASM_CFI_REG_IS_AT2(rip, rcx, 0x70, 0x00)
__ASM_CFI(".cfi_undefined %rbp\n\t")
__ASM_CFI(".cfi_undefined %rbx\n\t")
__ASM_CFI(".cfi_undefined %r12\n\t")
__ASM_CFI(".cfi_undefined %r13\n\t")
__ASM_CFI(".cfi_same_value %r14\n\t")
__ASM_CFI(".cfi_undefined %r15\n\t")
__ASM_CFI(".cfi_same_value %rdi\n\t")
__ASM_CFI(".cfi_same_value %rsi\n\t")
"pushq 0x70(%rcx)\n\t" /* frame->rip */
__ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
"ret" )
asm( ".data\n\t"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment