Paul Gofman : ntdll: Save unwind information in KiUserApcDispatcher() on x64.
Alexandre Julliard
julliard at winehq.org
Thu Dec 17 15:50:26 CST 2020
Module: wine
Branch: master
Commit: 71a43335ab9da84059ff9963b36a92dad48c8cc3
URL: https://source.winehq.org/git/wine.git/?a=commit;h=71a43335ab9da84059ff9963b36a92dad48c8cc3
Author: Paul Gofman <pgofman at codeweavers.com>
Date: Thu Dec 17 02:05:05 2020 +0300
ntdll: Save unwind information in KiUserApcDispatcher() on x64.
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/signal_arm.c | 11 +++++++++
dlls/ntdll/signal_arm64.c | 12 ++++++++++
dlls/ntdll/signal_i386.c | 12 ++++++++++
dlls/ntdll/signal_x86_64.c | 30 +++++++++++++++++++++++
dlls/ntdll/tests/exception.c | 53 +++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/thread.c | 11 ---------
dlls/ntdll/unix/signal_x86_64.c | 23 ++++++++++++++++--
7 files changed, 139 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
index 0e80a35b0c0..512462b7066 100644
--- a/dlls/ntdll/signal_arm.c
+++ b/dlls/ntdll/signal_arm.c
@@ -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.@)
*/
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
index c31eb510382..4c4694959f0 100644
--- a/dlls/ntdll/signal_arm64.c
+++ b/dlls/ntdll/signal_arm64.c
@@ -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
*/
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index ddc2bf6adbd..93e03ae5b8b 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -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
*
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index a3dba815c1f..7e39991ad1a 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -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);
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 5686e39ab9e..3a0a5ac049c 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -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__)
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 578c7a5436c..3dd1c9a5c26 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -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.@)
*/
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 3ae3b4c141e..837cd9ed654 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -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" )
/***********************************************************************
More information about the wine-cvs
mailing list