Commit 71a43335 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Save unwind information in KiUserApcDispatcher() on x64.

parent c72f52d7
......@@ -175,6 +175,17 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
}
/*******************************************************************
* KiUserApcDispatcher (NTDLL.@)
*/
void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2,
PNTAPCFUNC func )
{
func( ctx, arg1, arg2 );
NtContinue( context, TRUE );
}
/***********************************************************************
* RtlUnwind (NTDLL.@)
*/
......
......@@ -523,6 +523,18 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
return NtRaiseException( rec, context, FALSE );
}
/*******************************************************************
* KiUserApcDispatcher (NTDLL.@)
*/
void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2,
PNTAPCFUNC func )
{
func( ctx, arg1, arg2 );
NtContinue( context, TRUE );
}
/***********************************************************************
* Definitions for Win32 unwind tables
*/
......
......@@ -218,6 +218,18 @@ __ASM_STDCALL_FUNC( KiUserExceptionDispatcher, 8,
"call " __ASM_STDCALL("dispatch_exception", 8) "\n\t"
"int3" )
/*******************************************************************
* KiUserApcDispatcher (NTDLL.@)
*/
void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2,
PNTAPCFUNC func )
{
func( ctx, arg1, arg2 );
NtContinue( context, TRUE );
}
/***********************************************************************
* save_fpu
*
......
......@@ -590,6 +590,36 @@ __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher,
"call " __ASM_NAME("dispatch_exception") "\n\t"
"int3")
/*******************************************************************
* KiUserApcDispatcher (NTDLL.@)
*/
void WINAPI dispatch_apc( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2,
PNTAPCFUNC func )
{
func( ctx, arg1, arg2 );
NtContinue( context, TRUE );
}
__ASM_GLOBAL_FUNC( KiUserApcDispatcher,
"addq $0x8,%rsp\n\t"
"mov 0x98(%rcx),%r10\n\t" /* context->Rsp */
"mov 0xf8(%rcx),%r11\n\t" /* context->Rip */
"mov %r11,-0x8(%r10)\n\t"
"mov %rbp,-0x10(%r10)\n\t"
"lea -0x10(%r10),%rbp\n\t"
__ASM_SEH(".seh_pushreg %rbp\n\t")
__ASM_SEH(".seh_setframe %rbp,0\n\t")
__ASM_SEH(".seh_endprologue\n\t")
__ASM_CFI(".cfi_signal_frame\n\t")
__ASM_CFI(".cfi_adjust_cfa_offset 0x10\n\t")
__ASM_CFI(".cfi_def_cfa %rbp,0x10\n\t")
__ASM_CFI(".cfi_rel_offset %rip,0x8\n\t")
__ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
"call " __ASM_NAME("dispatch_apc") "\n\t"
"int3")
static ULONG64 get_int_reg( CONTEXT *context, int reg )
{
return *(&context->Rax + reg);
......
......@@ -37,6 +37,8 @@ static void *code_mem;
static NTSTATUS (WINAPI *pNtGetContextThread)(HANDLE,CONTEXT*);
static NTSTATUS (WINAPI *pNtSetContextThread)(HANDLE,CONTEXT*);
static NTSTATUS (WINAPI *pNtQueueApcThread)(HANDLE handle, PNTAPCFUNC func,
ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3);
static NTSTATUS (WINAPI *pRtlRaiseException)(EXCEPTION_RECORD *rec);
static PVOID (WINAPI *pRtlUnwind)(PVOID, PVOID, PEXCEPTION_RECORD, PVOID);
static VOID (WINAPI *pRtlCaptureContext)(CONTEXT*);
......@@ -4061,6 +4063,55 @@ static void test_nested_exception(void)
ok(got_prev_frame_exception, "Did not get nested exception in the previous frame.\n");
}
static CONTEXT test_unwind_apc_context;
static BOOL test_unwind_apc_called;
static void CALLBACK test_unwind_apc(ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3)
{
EXCEPTION_RECORD rec;
test_unwind_apc_called = TRUE;
memset(&rec, 0, sizeof(rec));
pRtlUnwind((void *)test_unwind_apc_context.Rsp, (void *)test_unwind_apc_context.Rip, &rec, (void *)0xdeadbeef);
ok(0, "Should not get here.\n");
}
static void test_unwind_from_apc(void)
{
NTSTATUS status;
int pass;
if (!pNtQueueApcThread)
{
win_skip("NtQueueApcThread is not available.\n");
return;
}
pass = 0;
InterlockedIncrement(&pass);
RtlCaptureContext(&test_unwind_apc_context);
InterlockedIncrement(&pass);
if (pass == 2)
{
test_unwind_apc_called = FALSE;
status = pNtQueueApcThread(GetCurrentThread(), test_unwind_apc, 0, 0, 0);
ok(!status, "Got unexpected status %#x.\n", status);
SleepEx(0, TRUE);
ok(0, "Should not get here.\n");
}
if (pass == 3)
{
ok(test_unwind_apc_called, "Test user APC was not called.\n");
test_unwind_apc_called = FALSE;
status = pNtQueueApcThread(GetCurrentThread(), test_unwind_apc, 0, 0, 0);
ok(!status, "Got unexpected status %#x.\n", status);
NtContinue(&test_unwind_apc_context, TRUE );
ok(0, "Should not get here.\n");
}
ok(pass == 4, "Got unexpected pass %d.\n", pass);
ok(test_unwind_apc_called, "Test user APC was not called.\n");
}
#elif defined(__arm__)
static void test_thread_context(void)
......@@ -8073,6 +8124,7 @@ START_TEST(exception)
#define X(f) p##f = (void*)GetProcAddress(hntdll, #f)
X(NtGetContextThread);
X(NtSetContextThread);
X(NtQueueApcThread);
X(NtReadVirtualMemory);
X(NtClose);
X(RtlUnwind);
......@@ -8241,6 +8293,7 @@ START_TEST(exception)
skip( "Dynamic unwind functions not found\n" );
test_extended_context();
test_copy_context();
test_unwind_from_apc();
#elif defined(__aarch64__)
......
......@@ -75,17 +75,6 @@ int __cdecl __wine_dbg_output( const char *str )
}
/*******************************************************************
* KiUserApcDispatcher (NTDLL.@)
*/
void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2,
PNTAPCFUNC func )
{
func( ctx, arg1, arg2 );
NtContinue( context, TRUE );
}
/***********************************************************************
* RtlExitUserThread (NTDLL.@)
*/
......
......@@ -2073,9 +2073,28 @@ __ASM_GLOBAL_FUNC( call_user_apc_dispatcher,
"movq %r14,%r9\n" /* arg2 */
"movq $0,0x328(%rbx)\n\t" /* amd64_thread_data()->syscall_frame */
"movq %rsi,0x20(%rsp)\n\t" /* func */
"movq 0xa0(%rcx),%rbp\n\t" /* context.Rbp */
"movq %rdi,%r10\n\t"
/* Set nonvolatile regs from context. */
"movq 0xa0(%rcx),%rbp\n\t"
"movq 0x90(%rcx),%rbx\n\t"
"movq 0xa8(%rcx),%rsi\n\t"
"movq 0xb0(%rcx),%rdi\n\t"
"movq 0xd8(%rcx),%r12\n\t"
"movq 0xe0(%rcx),%r13\n\t"
"movq 0xe8(%rcx),%r14\n\t"
"movq 0xf0(%rcx),%r15\n\t"
"movdqa 0x200(%rcx),%xmm6\n\t"
"movdqa 0x210(%rcx),%xmm7\n\t"
"movdqa 0x220(%rcx),%xmm8\n\t"
"movdqa 0x230(%rcx),%xmm9\n\t"
"movdqa 0x240(%rcx),%xmm10\n\t"
"movdqa 0x250(%rcx),%xmm11\n\t"
"movdqa 0x260(%rcx),%xmm12\n\t"
"movdqa 0x270(%rcx),%xmm13\n\t"
"movdqa 0x280(%rcx),%xmm14\n\t"
"movdqa 0x290(%rcx),%xmm15\n\t"
"pushq 0xf8(%rcx)\n\t" /* context.Rip */
"jmp *%rdi" )
"jmp *%r10" )
/***********************************************************************
......
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