From: Billy Laws blaws05@gmail.com
This is used starting from around build 27686. --- dlls/ntdll/signal_arm64.c | 4 ++-- dlls/ntdll/signal_arm64ec.c | 4 ++-- dlls/ntdll/tests/exception.c | 31 ++++++++++++++++++++++------ dlls/ntdll/unix/signal_arm64.c | 37 +++++++++++++++++++++++++++++----- 4 files changed, 61 insertions(+), 15 deletions(-)
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 0531083ba4e..8a53bcc46bb 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -311,10 +311,10 @@ __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher, "adrp x16, pWow64PrepareForException\n\t" "ldr x16, [x16, #:lo12:pWow64PrepareForException]\n\t" "cbz x16, 1f\n\t" - "add x0, sp, #0x390\n\t" /* rec (context + 1) */ + "add x0, sp, #0x3b0\n\t" /* rec */ "mov x1, sp\n\t" /* context */ "blr x16\n" - "1:\tadd x0, sp, #0x390\n\t" /* rec (context + 1) */ + "1:\tadd x0, sp, #0x3b0\n\t" /* rec */ "mov x1, sp\n\t" /* context */ "bl dispatch_exception\n\t" "brk #1" ) diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 5001057c4c7..aa950f42bd4 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -1149,11 +1149,11 @@ void __attribute__((naked)) KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CO "sub sp, sp, #0x4d0\n\t" /* sizeof(ARM64EC_NT_CONTEXT) */ ".seh_stackalloc 0x4d0\n\t" ".seh_endprologue\n\t" - "add x0, sp, #0x390+0x4d0\n\t" /* rec (arm_ctx + 1) */ + "add x0, sp, #0x3b0+0x4d0\n\t" /* rec */ "mov x1, sp\n\t" /* context */ "add x2, sp, #0x4d0\n\t" /* arm_ctx (context + 1) */ "bl "#prepare_exception_arm64ec"\n\t" - "add x0, sp, #0x390+0x4d0\n\t" /* rec */ + "add x0, sp, #0x3b0+0x4d0\n\t" /* rec */ "mov x1, sp\n\t" /* context */ "bl #dispatch_exception\n\t" "brk #1\n\t" diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index acf6946736e..c656f7a0b49 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -7083,16 +7083,35 @@ static LONG WINAPI dbg_except_continue_vectored_handler(struct _EXCEPTION_POINTE
static void * WINAPI hook_KiUserExceptionDispatcher(void *stack) { - CONTEXT *context = stack; - EXCEPTION_RECORD *rec = (EXCEPTION_RECORD *)(context + 1); + struct + { + CONTEXT context; /* 000 */ + CONTEXT_EX context_ex; /* 390 */ + EXCEPTION_RECORD rec; /* 3b0 */ + ULONG64 align; /* 448 */ + ULONG64 sp; /* 450 */ + ULONG64 pc; /* 458 */ + } *args = stack; + EXCEPTION_RECORD *old_rec = (EXCEPTION_RECORD *)&args->context_ex;
- trace( "rec %p context %p pc %#Ix sp %#Ix flags %#lx\n", - rec, context, context->Pc, context->Sp, context->ContextFlags ); + trace("stack %p context->Pc %#Ix, context->Sp %#Ix, ContextFlags %#lx.\n", + stack, args->context.Pc, args->context.Sp, args->context.ContextFlags);
+ hook_called = TRUE; ok( !((ULONG_PTR)stack & 15), "unaligned stack %p\n", stack ); - ok( rec->ExceptionCode == 0x80000003, "Got unexpected ExceptionCode %#lx.\n", rec->ExceptionCode );
- hook_called = TRUE; + if (!broken( old_rec->ExceptionCode == 0x80000003 )) /* Windows 11 versions prior to 27686 */ + { + ok( args->rec.ExceptionCode == 0x80000003, "Got unexpected ExceptionCode %#lx.\n", args->rec.ExceptionCode ); + + ok( args->context_ex.All.Offset == -sizeof(CONTEXT), "wrong All.Offset %lx\n", args->context_ex.All.Offset ); + ok( args->context_ex.All.Length >= sizeof(CONTEXT) + offsetof(CONTEXT_EX, align), "wrong All.Length %lx\n", args->context_ex.All.Length ); + ok( args->context_ex.Legacy.Offset == -sizeof(CONTEXT), "wrong Legacy.Offset %lx\n", args->context_ex.All.Offset ); + ok( args->context_ex.Legacy.Length == sizeof(CONTEXT), "wrong Legacy.Length %lx\n", args->context_ex.All.Length ); + ok( args->sp == args->context.Sp, "wrong sp %Ix / %Ix\n", args->sp, args->context.Sp ); + ok( args->pc == args->context.Pc, "wrong pc %Ix / %Ix\n", args->pc, args->context.Pc ); + } + memcpy(pKiUserExceptionDispatcher, saved_code, sizeof(saved_code)); FlushInstructionCache( GetCurrentProcess(), pKiUserExceptionDispatcher, sizeof(saved_code)); return pKiUserExceptionDispatcher; diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index b54fa30a318..b1c6e5246c0 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -128,12 +128,15 @@ static DWORD64 get_fault_esr( ucontext_t *sigcontext ) struct exc_stack_layout { CONTEXT context; /* 000 */ - EXCEPTION_RECORD rec; /* 390 */ - ULONG64 align; /* 428 */ - ULONG64 redzone[2]; /* 430 */ + CONTEXT_EX context_ex; /* 390 */ + EXCEPTION_RECORD rec; /* 3b0 */ + ULONG64 align; /* 448 */ + ULONG64 sp; /* 450 */ + ULONG64 pc; /* 458 */ + ULONG64 redzone[2]; /* 460 */ }; -C_ASSERT( offsetof(struct exc_stack_layout, rec) == 0x390 ); -C_ASSERT( sizeof(struct exc_stack_layout) == 0x440 ); +C_ASSERT( offsetof(struct exc_stack_layout, rec) == 0x3b0 ); +C_ASSERT( sizeof(struct exc_stack_layout) == 0x470 );
/* stack layout when calling KiUserApcDispatcher */ struct apc_stack_layout @@ -203,6 +206,23 @@ static BOOL is_inside_syscall( ucontext_t *sigcontext ) (char *)SP_sig(sigcontext) <= (char *)arm64_thread_data()->syscall_frame); }
+/*********************************************************************** + * context_init_empty_xstate + * + * Initializes a context's CONTEXT_EX structure to point to an empty xstate buffer + */ +static inline void context_init_empty_xstate( CONTEXT *context, void *xstate_buffer ) +{ + CONTEXT_EX *xctx; + + xctx = (CONTEXT_EX *)(context + 1); + xctx->Legacy.Length = sizeof(CONTEXT); + xctx->Legacy.Offset = -(LONG)sizeof(CONTEXT); + xctx->XState.Length = 0; + xctx->XState.Offset = (BYTE *)xstate_buffer - (BYTE *)xctx; + xctx->All.Length = sizeof(CONTEXT); + xctx->All.Offset = -(LONG)sizeof(CONTEXT); +}
/*********************************************************************** * unwind_builtin_dll @@ -723,6 +743,9 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec ); stack->rec = *rec; stack->context = *context; + context_init_empty_xstate( &stack->context, stack->redzone ); + stack->sp = context->Sp; + stack->pc = context->Pc;
SP_sig(sigcontext) = (ULONG_PTR)stack; PC_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; @@ -804,6 +827,10 @@ NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context stack = (struct exc_stack_layout *)(context->Sp & ~15) - 1; memmove( &stack->context, context, sizeof(*context) ); memmove( &stack->rec, rec, sizeof(*rec) ); + context_init_empty_xstate( &stack->context, stack->redzone ); + stack->sp = context->Sp; + stack->pc = context->Pc; + frame->pc = (ULONG64)pKiUserExceptionDispatcher; frame->sp = (ULONG64)stack; frame->restore_flags |= CONTEXT_CONTROL;