Commit a686759f authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Unwind the syscall frame when calling KiUserApcDispatcher().

parent 53e0bf2f
......@@ -354,13 +354,13 @@ static void invoke_apc( CONTEXT *context, const user_apc_t *apc )
switch( apc->type )
{
case APC_USER:
call_user_apc( context, apc->user.args[0], apc->user.args[1], apc->user.args[2],
wine_server_get_ptr( apc->user.func ));
call_user_apc_dispatcher( context, apc->user.args[0], apc->user.args[1], apc->user.args[2],
wine_server_get_ptr( apc->user.func ), pKiUserApcDispatcher );
break;
case APC_TIMER:
call_user_apc( context, (ULONG_PTR)wine_server_get_ptr( apc->user.args[1] ),
(DWORD)apc->timer.time, (DWORD)(apc->timer.time >> 32),
wine_server_get_ptr( apc->user.func ));
call_user_apc_dispatcher( context, (ULONG_PTR)wine_server_get_ptr( apc->user.args[1] ),
(DWORD)apc->timer.time, (DWORD)(apc->timer.time >> 32),
wine_server_get_ptr( apc->user.func ), pKiUserApcDispatcher );
break;
default:
server_protocol_error( "get_apc_request: bad type %d\n", apc->type );
......
......@@ -578,22 +578,46 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
/***********************************************************************
* call_user_apc
*/
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
ULONG_PTR arg2, PNTAPCFUNC func )
{
CONTEXT context;
if (!context_ptr)
{
context.ContextFlags = CONTEXT_FULL;
NtGetContextThread( GetCurrentThread(), &context );
context.R0 = STATUS_USER_APC;
context_ptr = &context;
}
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
}
* call_user_apc_dispatcher
*/
__ASM_GLOBAL_FUNC( call_user_apc_dispatcher,
"mov r4, r0\n\t" /* context_ptr */
"mov r5, r1\n\t" /* ctx */
"mov r6, r2\n\t" /* arg1 */
"mov r7, r3\n\t" /* arg2 */
"ldr r8, [sp]\n\t" /* func */
"ldr r9, [sp, #4]\n\t" /* dispatcher */
"bl " __ASM_NAME("NtCurrentTeb") "\n\t"
"add r10, r0, #0x1d8\n\t" /* arm_thread_data()->syscall_frame */
"ldr r12, [r10]\n\t"
"movs r0, r4\n\t"
"beq 1f\n\t"
"ldr r0, [r0, #0x38]\n\t" /* context_ptr->Sp */
"sub r0, r0, #0x1c8\n\t" /* sizeof(CONTEXT) + offsetof(frame,r4) */
"ldr r12, [r12]\n\t" /* frame->prev_frame */
"str r12, [r10]\n\t"
"mov sp, r0\n\t"
"b 2f\n"
"1:\tsub r11, r12, #0x1a0\n\t"
"cmp r11, sp\n\t"
"movlo sp, r11\n\t"
"mov r0, #3\n\t"
"movt r0, #32\n\t"
"str r0, [r11]\n\t" /* context.ContextFlags = CONTEXT_FULL */
"mov r1, r11\n\t"
"mov r0, #~1\n\t"
"bl " __ASM_NAME("NtGetContextThread") "\n\t"
"mov r0, #0xc0\n\t"
"str r0, [r11, #4]\n\t" /* context.R0 = STATUS_USER_APC */
"mov r0, r11\n\t"
"ldr r12, [r12]\n\t" /* frame->prev_frame */
"str r12, [r10]\n"
"2:\tmov r1, r5\n\t" /* ctx */
"mov r2, r6\n\t" /* arg1 */
"mov r3, r7\n\t" /* arg2 */
"push {r8, r9}\n\t" /* func */
"ldr lr, [r0, #0x3c]\n\t" /* context.Lr */
"bx r9" )
/***********************************************************************
......
......@@ -637,22 +637,47 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
/***********************************************************************
* call_user_apc
* call_user_apc_dispatcher
*/
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
ULONG_PTR arg2, PNTAPCFUNC func )
{
CONTEXT context;
if (!context_ptr)
{
context.ContextFlags = CONTEXT_FULL;
NtGetContextThread( GetCurrentThread(), &context );
context.u.s.X0 = STATUS_USER_APC;
context_ptr = &context;
}
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
}
__ASM_GLOBAL_FUNC( call_user_apc_dispatcher,
"mov x19, x0\n\t" /* context */
"mov x20, x1\n\t" /* ctx */
"mov x21, x2\n\t" /* arg1 */
"mov x22, x3\n\t" /* arg2 */
"mov x23, x4\n\t" /* func */
"mov x24, x5\n\t" /* dispatcher */
"bl " __ASM_NAME("NtCurrentTeb") "\n\t"
"add x25, x0, #0x2f8\n\t" /* arm64_thread_data()->syscall_frame */
"ldr x26, [x25]\n\t"
"cbz x19, 1f\n\t"
"ldr x0, [x19, #0x100]\n\t" /* context.Sp */
"sub x0, x0, #0x440\n\t" /* sizeof(CONTEXT) + offsetof(frame,thunk_x29) */
"ldr x6, [x26, #88]\n\t" /* frame->prev_frame */
"str x6, [x25]\n\t"
"mov sp, x0\n\t"
"b 2f\n"
"1:\tsub x19, x26, #0x390\n\t"
"mov x0, sp\n\t"
"cmp x19, x0\n\t"
"csel x0, x19, x0, lo\n\t"
"mov sp, x0\n\t"
"mov w2, #0x400000\n\t" /* context.ContextFlags = CONTEXT_FULL */
"movk w2, #3\n\t"
"mov x1, x19\n\t"
"str w2, [x19]\n\t"
"mov x0, #~1\n\t"
"bl " __ASM_NAME("NtGetContextThread") "\n\t"
"mov w2, #0xc0\n\t" /* context.X0 = STATUS_USER_APC */
"str x2, [x19, #8]\n\t"
"ldr x6, [x26, #88]\n\t" /* frame->prev_frame */
"str x6, [x25]\n\t"
"mov x0, x19\n" /* context */
"2:\tldr lr, [x0, #0xf8]\n\t" /* context.Lr */
"mov x1, x20\n\t" /* ctx */
"mov x2, x21\n\t" /* arg1 */
"mov x3, x22\n\t" /* arg2 */
"mov x4, x23\n\t" /* func */
"br x24" )
/***********************************************************************
......
......@@ -1537,22 +1537,45 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
/***********************************************************************
* call_user_apc
* call_user_apc_dispatcher
*/
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
ULONG_PTR arg2, PNTAPCFUNC func )
{
CONTEXT context;
if (!context_ptr)
{
context.ContextFlags = CONTEXT_FULL;
NtGetContextThread( GetCurrentThread(), &context );
context.Eax = STATUS_USER_APC;
context_ptr = &context;
}
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
}
__ASM_GLOBAL_FUNC( call_user_apc_dispatcher,
"movl 4(%esp),%esi\n\t" /* context_ptr */
"movl 24(%esp),%edi\n\t" /* dispatcher */
"movl %fs:0x1f8,%ebx\n\t" /* x86_thread_data()->syscall_frame */
"test %esi,%esi\n\t"
"jz 1f\n\t"
"movl 0xc4(%esi),%eax\n\t" /* context_ptr->Rsp */
"leal -0x2fc(%eax),%eax\n\t" /* sizeof(CONTEXT) + offsetof(frame,ret_addr) + params */
"movl %esi,4(%eax)\n\t"
"movl 8(%esp),%ecx\n\t" /* ctx */
"movl %ecx,8(%eax)\n\t"
"movl 12(%esp),%ecx\n\t" /* arg1 */
"movl %ecx,12(%eax)\n\t"
"movl 16(%esp),%ecx\n\t" /* arg2 */
"movl %ecx,16(%eax)\n\t"
"movl 20(%esp),%ecx\n\t" /* func */
"movl %ecx,20(%eax)\n\t"
"leal 4(%eax),%esp\n\t"
"jmp 2f\n\t"
"1:\tleal -0x2cc(%ebx),%esi\n\t"
"movl %esp,%ecx\n\t"
"cmpl %esp,%esi\n\t"
"cmovbl %esi,%esp\n\t"
"pushl 20(%ecx)\n\t" /* func */
"pushl 16(%ecx)\n\t" /* arg2 */
"pushl 12(%ecx)\n\t" /* arg1 */
"pushl 8(%ecx)\n\t" /* ctx */
"pushl %esi\n\t" /* context */
"movl $0x00010007,(%esi)\n\t" /* context.ContextFlags = CONTEXT_FULL */
"pushl %esi\n\t" /* context */
"pushl $0xfffffffe\n\t"
"call " __ASM_STDCALL("NtGetContextThread",8) "\n\t"
"movl $0xc0,0xb0(%esi)\n" /* context.Eax = STATUS_USER_APC */
"2:\tmovl (%ebx),%edx\n\t" /* frame->prev_frame */
"movl %edx,%fs:0x1f8\n\t"
"pushl $0xdeaddead\n\t"
"jmp *%edi\n" )
/***********************************************************************
......
......@@ -1873,22 +1873,40 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
/***********************************************************************
* call_user_apc
* call_user_apc_dispatcher
*/
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
ULONG_PTR arg2, PNTAPCFUNC func )
{
CONTEXT context;
if (!context_ptr)
{
context.ContextFlags = CONTEXT_FULL;
NtGetContextThread( GetCurrentThread(), &context );
context.Rax = STATUS_USER_APC;
context_ptr = &context;
}
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
}
__ASM_GLOBAL_FUNC( call_user_apc_dispatcher,
"movq 0x28(%rsp),%rsi\n\t" /* func */
"movq 0x30(%rsp),%rdi\n\t" /* dispatcher */
"movq %gs:0x30,%rbx\n\t"
"jrcxz 1f\n\t"
"movq 0x98(%rcx),%rax\n\t" /* context_ptr->Rsp */
"leaq -0x5d0(%rax),%rsp\n\t" /* sizeof(CONTEXT) + offsetof(frame,ret_addr) */
"jmp 2f\n"
"1:\tmovq 0x328(%rbx),%rax\n\t" /* amd64_thread_data()->syscall_frame */
"leaq -0x4d0(%rax),%r10\n\t"
"movq %rdx,%r12\n\t" /* ctx */
"movq %r8,%r13\n\t" /* arg1 */
"movq %r9,%r14\n\t" /* arg2 */
"cmpq %rsp,%r10\n\t"
"cmovbq %r10,%rsp\n\t"
"andq $~15,%rsp\n\t"
"movq %rsp,%rdx\n\t" /* context */
"movl $0x10000b,0x30(%rdx)\n\t" /* context.ContextFlags */
"movq $~1,%rcx\n\t"
"call " __ASM_NAME("NtGetContextThread") "\n\t"
"movq %rsp,%rcx\n\t" /* context */
"movl $0xc0,%eax\n\t"
"movq %rax,0x78(%rcx)\n\t" /* context.Rax = STATUS_USER_APC */
"movq %r12,%rdx\n\t" /* ctx */
"movq %r13,%r8\n\t" /* arg1 */
"movq %r14,%r9\n" /* arg2 */
"2:\tmovq 0x328(%rbx),%rax\n\t" /* amd64_thread_data()->syscall_frame */
"movq (%rax),%rax\n\t" /* frame->prev_frame */
"movq %rax,0x328(%rbx)\n\t"
"movq %rsi,0x20(%rsp)\n\t" /* func */
"leaq -8(%rsp),%rsp\n\t"
"jmp *%rdi" )
/***********************************************************************
......@@ -1899,7 +1917,7 @@ __ASM_GLOBAL_FUNC( call_raise_user_exception_dispatcher,
"movq 0x328(%rdx),%rax\n\t" /* amd64_thread_data()->syscall_frame */
"pushq (%rax)\n\t" /* frame->prev_frame */
"popq 0x328(%rdx)\n\t"
"movdqu 0x10(%rax),%xmm6\n\t" /* frame->xmm[0..19 */
"movdqu 0x10(%rax),%xmm6\n\t" /* frame->xmm[0..19] */
"movdqu 0x20(%rax),%xmm7\n\t"
"movdqu 0x30(%rax),%xmm8\n\t"
"movdqu 0x40(%rax),%xmm9\n\t"
......
......@@ -258,8 +258,10 @@ extern void init_cpu_info(void) DECLSPEC_HIDDEN;
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 DECLSPEC_NORETURN call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR ctx,
ULONG_PTR arg1, ULONG_PTR arg2,
PNTAPCFUNC func,
void (WINAPI *dispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULONG_PTR,PNTAPCFUNC) ) DECLSPEC_HIDDEN;
extern void WINAPI DECLSPEC_NORETURN call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) ) DECLSPEC_HIDDEN;
extern void WINAPI DECLSPEC_NORETURN call_raise_user_exception_dispatcher( NTSTATUS (WINAPI *dispatcher)(void) ) DECLSPEC_HIDDEN;
......
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