Commit 887332f9 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Fix KiUserExceptionDispatcher ABI on x86_64.

parent 21f1fa82
...@@ -530,10 +530,7 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex ...@@ -530,10 +530,7 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
} }
/******************************************************************* NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
* KiUserExceptionDispatcher (NTDLL.@)
*/
NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
{ {
NTSTATUS status; NTSTATUS status;
DWORD c; DWORD c;
...@@ -581,6 +578,28 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte ...@@ -581,6 +578,28 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
} }
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
__ASM_GLOBAL_FUNC( KiUserExceptionDispatcher,
"mov 0x98(%rsp),%rcx\n\t" /* context->Rsp */
"mov 0xf8(%rsp),%rdx\n\t" /* context->Rip */
"mov %rdx,-0x8(%rcx)\n\t"
"mov %rbp,-0x10(%rcx)\n\t"
"mov %rdi,-0x18(%rcx)\n\t"
"mov %rsi,-0x20(%rcx)\n\t"
"mov %rcx,%rbp\n\t"
"mov %rsp,%rdx\n\t" /* context */
"lea 0x4f0(%rsp),%rcx\n\t" /* rec */
__ASM_CFI(".cfi_signal_frame\n\t")
__ASM_CFI(".cfi_def_cfa %rbp,0\n\t")
__ASM_CFI(".cfi_rel_offset %rip,-0x8\n\t")
__ASM_CFI(".cfi_rel_offset %rbp,-0x10\n\t")
__ASM_CFI(".cfi_rel_offset %rdi,-0x18\n\t")
__ASM_CFI(".cfi_rel_offset %rsi,-0x20\n\t")
"call " __ASM_NAME("dispatch_exception") "\n\t"
"int3")
static ULONG64 get_int_reg( CONTEXT *context, int reg ) static ULONG64 get_int_reg( CONTEXT *context, int reg )
{ {
return *(&context->Rax + reg); return *(&context->Rax + reg);
......
...@@ -531,6 +531,10 @@ static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func fun ...@@ -531,6 +531,10 @@ static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func fun
return &stack->rec; return &stack->rec;
} }
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
{
pKiUserExceptionDispatcher( rec, context );
}
/********************************************************************** /**********************************************************************
* raise_segv_exception * raise_segv_exception
......
...@@ -602,6 +602,11 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * ...@@ -602,6 +602,11 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb(); REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb();
} }
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
{
pKiUserExceptionDispatcher( rec, context );
}
/********************************************************************** /**********************************************************************
* segv_handler * segv_handler
* *
......
...@@ -1588,6 +1588,10 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * ...@@ -1588,6 +1588,10 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
stack->context_ptr = &stack->context; stack->context_ptr = &stack->context;
} }
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
{
pKiUserExceptionDispatcher( rec, context );
}
/********************************************************************** /**********************************************************************
* get_fpu_code * get_fpu_code
......
...@@ -233,6 +233,7 @@ typedef void (*raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context ); ...@@ -233,6 +233,7 @@ typedef void (*raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context );
struct stack_layout struct stack_layout
{ {
CONTEXT context; CONTEXT context;
ULONG64 unknown[4];
EXCEPTION_RECORD rec; EXCEPTION_RECORD rec;
ULONG64 rsi; ULONG64 rsi;
ULONG64 rdi; ULONG64 rdi;
...@@ -241,6 +242,8 @@ struct stack_layout ...@@ -241,6 +242,8 @@ struct stack_layout
ULONG64 red_zone[16]; ULONG64 red_zone[16];
}; };
C_ASSERT( sizeof(struct stack_layout) == 0x630 ); /* Should match the size in call_user_exception_dispatcher(). */
struct amd64_thread_data struct amd64_thread_data
{ {
DWORD_PTR dr0; /* debug registers */ DWORD_PTR dr0; /* debug registers */
...@@ -1843,16 +1846,10 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) ...@@ -1843,16 +1846,10 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
} }
extern void CDECL raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func ); extern void CDECL raise_func_trampoline( raise_func func );
__ASM_GLOBAL_FUNC( raise_func_trampoline, __ASM_GLOBAL_FUNC( raise_func_trampoline,
__ASM_CFI(".cfi_signal_frame\n\t") "jmpq *%r8\n\t")
__ASM_CFI(".cfi_def_cfa %rbp,160\n\t") /* red zone + rip + rbp + rdi + rsi */
__ASM_CFI(".cfi_rel_offset %rip,24\n\t")
__ASM_CFI(".cfi_rel_offset %rbp,16\n\t")
__ASM_CFI(".cfi_rel_offset %rdi,8\n\t")
__ASM_CFI(".cfi_rel_offset %rsi,0\n\t")
"call *%r8\n\t"
"int $3")
/*********************************************************************** /***********************************************************************
* setup_exception * setup_exception
...@@ -1934,7 +1931,6 @@ static struct stack_layout *setup_exception( ucontext_t *sigcontext ) ...@@ -1934,7 +1931,6 @@ static struct stack_layout *setup_exception( ucontext_t *sigcontext )
static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *stack ) static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *stack )
{ {
ULONG64 *rsp_ptr;
NTSTATUS status; NTSTATUS status;
if (stack->rec.ExceptionCode == EXCEPTION_SINGLE_STEP) if (stack->rec.ExceptionCode == EXCEPTION_SINGLE_STEP)
...@@ -1962,24 +1958,39 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * ...@@ -1962,24 +1958,39 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
return; return;
} }
/* store return address and %rbp without aligning, so that the offset is fixed */
rsp_ptr = (ULONG64 *)RSP_sig(sigcontext) - 16;
*(--rsp_ptr) = stack->context.Rip;
*(--rsp_ptr) = stack->context.Rbp;
*(--rsp_ptr) = stack->context.Rdi;
*(--rsp_ptr) = stack->context.Rsi;
/* now modify the sigcontext to return to the raise function */ /* now modify the sigcontext to return to the raise function */
RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline;
RCX_sig(sigcontext) = (ULONG_PTR)&stack->rec;
RDX_sig(sigcontext) = (ULONG_PTR)&stack->context;
R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher;
RBP_sig(sigcontext) = (ULONG_PTR)rsp_ptr;
RSP_sig(sigcontext) = (ULONG_PTR)stack; RSP_sig(sigcontext) = (ULONG_PTR)stack;
/* clear single-step, direction, and align check flag */ /* clear single-step, direction, and align check flag */
EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000); EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000);
} }
extern void WINAPI user_exception_dispatcher_trampoline( struct stack_layout *stack,
void *pKiUserExceptionDispatcher );
__ASM_GLOBAL_FUNC( user_exception_dispatcher_trampoline,
"movq %rcx,%rsp\n\t"
"movq 0x98(%rsp),%rcx\n\t" /* context->Rsp */
"movq 0xa0(%rsp),%rbp\n\t"
"movq 0xa8(%rsp),%rsi\n\t"
"movq 0xb0(%rsp),%rdi\n\t"
"jmpq *%rdx")
void WINAPI do_call_user_exception_dispatcher(EXCEPTION_RECORD *rec, CONTEXT *context, struct stack_layout *stack)
{
memcpy(&stack->context, context, sizeof(*context));
memcpy(&stack->rec, rec, sizeof(*rec));
user_exception_dispatcher_trampoline( stack, pKiUserExceptionDispatcher );
}
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
"movq 0x98(%rdx),%rsp\n\t" /* context->Rsp */
"and $~0xf,%rsp\n\t"
"sub $0x630,%rsp\n\t" /* sizeof(struct stack_layout) */
"movq %rsp,%r8\n\t"
"jmp " __ASM_NAME("do_call_user_exception_dispatcher") "\n\t")
/*********************************************************************** /***********************************************************************
* is_privileged_instr * is_privileged_instr
......
...@@ -415,7 +415,7 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL ...@@ -415,7 +415,7 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
NtSetContextThread( GetCurrentThread(), context ); NtSetContextThread( GetCurrentThread(), context );
if (first_chance) pKiUserExceptionDispatcher( rec, context ); if (first_chance) call_user_exception_dispatcher( rec, context );
if (rec->ExceptionFlags & EH_STACK_INVALID) if (rec->ExceptionFlags & EH_STACK_INVALID)
ERR("Exception frame is not in stack limits => unable to dispatch exception.\n"); ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
......
...@@ -241,6 +241,8 @@ extern void init_cpu_info(void) DECLSPEC_HIDDEN; ...@@ -241,6 +241,8 @@ extern void init_cpu_info(void) DECLSPEC_HIDDEN;
extern void dbg_init(void) DECLSPEC_HIDDEN; extern void dbg_init(void) DECLSPEC_HIDDEN;
extern void WINAPI call_user_exception_dispatcher(EXCEPTION_RECORD *rec, CONTEXT *context) DECLSPEC_HIDDEN;
#define TICKSPERSEC 10000000 #define TICKSPERSEC 10000000
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400)
#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
......
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