Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/tests/exception.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index aac5df531a0..43c4859e005 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -6690,12 +6690,14 @@ static void test_extended_context(void)
length = 0xdeadbeef; ret = pRtlGetExtendedContextLength2(flags, &length, 0); - ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), + ok((!ret && length == expected_length_xstate - sizeof(YMMCONTEXT)) + || broken(!ret && length == expected_length_xstate) /* win10pro */, "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
length = 0xdeadbeef; ret = pRtlGetExtendedContextLength2(flags, &length, 3); - ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), + ok((!ret && length == expected_length_xstate - sizeof(YMMCONTEXT)) + || broken(!ret && length == expected_length_xstate) /* win10pro */, "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
length = 0xdeadbeef; @@ -6877,7 +6879,9 @@ static void test_extended_context(void)
length2 = 0xdeadbeef; p = pRtlLocateExtendedFeature(context_ex, 2, &length2); - ok(!p && length2 == sizeof(YMMCONTEXT), "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags); + ok((!p && length2 == sizeof(YMMCONTEXT)) + || broken(p && length2 == sizeof(YMMCONTEXT)) /* win10pro */, + "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
length2 = 0xdeadbeef; p = pLocateXStateFeature(context, 2, &length2); @@ -6899,7 +6903,8 @@ static void test_extended_context(void) - context_arch[test].context_length; ok(context_ex->XState.Offset == expected_offset, "Got unexpected Offset %d, flags %#x.\n", context_ex->XState.Offset, flags); - ok(context_ex->XState.Length == sizeof(XSTATE) - sizeof(YMMCONTEXT), + ok(context_ex->XState.Length == sizeof(XSTATE) - sizeof(YMMCONTEXT) + || broken(context_ex->XState.Length == sizeof(XSTATE)) /* win10pro */, "Got unexpected Length %#x, flags %#x.\n", context_ex->XState.Length, flags);
ok(context_ex->All.Offset == -(int)context_arch[test].context_length, @@ -6995,7 +7000,8 @@ static void test_extended_context(void) context->ContextFlags); expected_compaction = compaction_enabled ? (ULONG64)1 << 63 : 0;
- ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask)); + ok(!xs->Mask || broken(xs->Mask == 4) /* win10pro */, + "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask)); ok(xs->CompactionMask == expected_compaction, "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(xs->CompactionMask));
@@ -7003,7 +7009,7 @@ static void test_extended_context(void) ok(data[i] == test_extended_context_data[i], "Got unexpected data %#x, i %u.\n", data[i], i);
for (i = 0; i < 4; ++i) - ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc, + ok(((ULONG *)&xs->YmmContext)[i] == (xs->Mask == 4 ? test_extended_context_data[i + 4] : 0xcccccccc), "Got unexpected data %#x, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
expected_compaction = compaction_enabled ? ((ULONG64)1 << 63) | 4 : 0; @@ -7020,7 +7026,8 @@ static void test_extended_context(void) ok(xs->CompactionMask == 4, "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(xs->CompactionMask)); for (i = 0; i < 4; ++i) - ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc, + ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc + || broken(((ULONG *)&xs->YmmContext)[i] == test_extended_context_data[i + 4]) /* win10pro */, "Got unexpected data %#x, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
xs->CompactionMask = 4; @@ -7035,7 +7042,8 @@ static void test_extended_context(void) ok(xs->CompactionMask == expected_compaction, "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(xs->CompactionMask)); for (i = 0; i < 4; ++i) - ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc, + ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc + || broken(((ULONG *)&xs->YmmContext)[i] == test_extended_context_data[i + 4]) /* win10pro */, "Got unexpected data %#x, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
context_ex->XState.Length = sizeof(XSTATE);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/tests/virtual.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 47eb784cbbc..7049f234a9f 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -612,7 +612,9 @@ static void test_user_shared_data(void)
for (i = 0; i < ARRAY_SIZE(feature_sizes); ++i) { - ok(xstate.AllFeatures[i] == feature_sizes[i], "Got unexpected AllFeatures[%u] %u, expected %u.\n", i, + ok(xstate.AllFeatures[i] == feature_sizes[i] + || broken(!xstate.AllFeatures[i]) /* win10pro */, + "Got unexpected AllFeatures[%u] %u, expected %u.\n", i, xstate.AllFeatures[i], feature_sizes[i]); ok(xstate.Features[i].Size == feature_sizes[i], "Got unexpected Features[%u].Size %u, expected %u.\n", i, xstate.Features[i].Size, feature_sizes[i]);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v2: - fix saving unwind return address.
dlls/ntdll/tests/exception.c | 43 +++++++++++++++++++++++++++++++++ dlls/ntdll/thread.c | 28 ++++++++++++++++++++- dlls/ntdll/unix/signal_x86_64.c | 27 ++++++++++++++++++--- 3 files changed, 93 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 43c4859e005..d35f31f5fe3 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*); @@ -3953,6 +3955,45 @@ 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(pass == 3, "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) @@ -7511,6 +7552,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); @@ -7672,6 +7714,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 0f31fe18a7d..6fae8771107 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -77,13 +77,39 @@ int __cdecl __wine_dbg_output( const char *str ) /******************************************************************* * KiUserApcDispatcher (NTDLL.@) */ -void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2, +#ifdef __x86_64__ +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") +#else +void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2, + PNTAPCFUNC func ) +{ + func( ctx, arg1, arg2 ); + NtContinue( context, TRUE ); +} +#endif
/*********************************************************************** * RtlExitUserThread (NTDLL.@) diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 9d480f3ae28..5660cbc1dc8 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1551,6 +1551,23 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon }
+/*********************************************************************** + * set_nonvolatile_regs + */ +extern void WINAPI set_nonvolatile_regs( const CONTEXT *context ); +__ASM_GLOBAL_FUNC( set_nonvolatile_regs, + "movq 0x90(%rcx),%rbx\n\t" /* context->Rbx */ + "movq 0xa0(%rcx),%rbp\n\t" /* context->Rbp */ + "movq 0xa8(%rcx),%rsi\n\t" /* context->Rsi */ + "movq 0xb0(%rcx),%rdi\n\t" /* context->Rdi */ + "movq 0xd8(%rcx),%r12\n\t" /* context->R12 */ + "movq 0xe0(%rcx),%r13\n\t" /* context->R13 */ + "movq 0xe8(%rcx),%r14\n\t" /* context->R14 */ + "movq 0xf0(%rcx),%r15\n\t" /* context->R15 */ + "fxrstor 0x100(%rcx)\n\t" /* context->FltSave */ + "ret" ); + + /*********************************************************************** * set_full_cpu_context * @@ -2014,14 +2031,15 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ) */ __ASM_GLOBAL_FUNC( call_user_apc_dispatcher, "movq 0x28(%rsp),%rsi\n\t" /* func */ - "movq 0x30(%rsp),%rdi\n\t" /* dispatcher */ + "movq 0x30(%rsp),%r10\n\t" /* dispatcher */ "movq %gs:0x30,%rbx\n\t" "jrcxz 1f\n\t" "movq 0x98(%rcx),%rax\n\t" /* context_ptr->Rsp */ - "leaq -0x5c0(%rax),%rsp\n\t" /* sizeof(CONTEXT) + offsetof(frame,ret_addr) */ + "leaq -0x5e0(%rax),%rsp\n\t" /* 0x20 (unwind regs space ) + * + sizeof(CONTEXT) + offsetof(frame,ret_addr) */ "jmp 2f\n" "1:\tmovq 0x328(%rbx),%rax\n\t" /* amd64_thread_data()->syscall_frame */ - "leaq -0x4d0(%rax),%rsp\n\t" + "leaq -0x4f0(%rax),%rsp\n\t" /* 0x20 (unwind regs space ) + sizeof(CONTEXT) */ "andq $~15,%rsp\n\t" "movq %rdx,%r12\n\t" /* ctx */ "movq %r8,%r13\n\t" /* arg1 */ @@ -2039,7 +2057,8 @@ __ASM_GLOBAL_FUNC( call_user_apc_dispatcher, "movq %rsi,0x20(%rsp)\n\t" /* func */ "movq 0xa0(%rcx),%rbp\n\t" /* context.Rbp */ "pushq 0xf8(%rcx)\n\t" /* context.Rip */ - "jmp *%rdi" ) + "call " __ASM_NAME("set_nonvolatile_regs") "\n\t" + "jmp *%r10" )
/***********************************************************************