ntdll: Send first chance debug event while on signal stack on ARM64.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-09-19 19:41:42 +02:00
parent afe8467110
commit 82c753a273
1 changed files with 69 additions and 64 deletions

View File

@ -483,52 +483,6 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
} }
/***********************************************************************
* setup_exception
*
* Setup the exception record and context on the thread stack.
*/
static struct stack_layout *setup_exception( ucontext_t *sigcontext )
{
struct stack_layout *stack;
DWORD exception_code = 0;
/* push the stack_layout structure */
stack = (struct stack_layout *)((SP_sig(sigcontext) - sizeof(*stack)) & ~15);
stack->rec.ExceptionRecord = NULL;
stack->rec.ExceptionCode = exception_code;
stack->rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
stack->rec.ExceptionAddress = (LPVOID)PC_sig(sigcontext);
stack->rec.NumberParameters = 0;
save_context( &stack->context, sigcontext );
save_fpu( &stack->context, sigcontext );
return stack;
}
/**********************************************************************
* raise_generic_exception
*/
static void WINAPI raise_generic_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status = NtRaiseException( rec, context, TRUE );
raise_status( status, rec );
}
/***********************************************************************
* setup_raise_exception
*
* Modify the signal context to call the exception raise function.
*/
static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *stack )
{
SP_sig(sigcontext) = (ULONG_PTR)stack;
PC_sig(sigcontext) = (ULONG_PTR)raise_generic_exception;
REGn_sig(0, sigcontext) = (ULONG_PTR)&stack->rec; /* first arg for raise_generic_exception */
REGn_sig(1, sigcontext) = (ULONG_PTR)&stack->context; /* second arg for raise_generic_exception */
}
/*********************************************************************** /***********************************************************************
* libunwind_virtual_unwind * libunwind_virtual_unwind
* *
@ -852,6 +806,7 @@ static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_con
dispatch.TargetPc = 0; dispatch.TargetPc = 0;
dispatch.ContextRecord = &context; dispatch.ContextRecord = &context;
dispatch.HistoryTable = &table; dispatch.HistoryTable = &table;
dispatch.NonVolatileRegisters = (BYTE *)&context.u.s.X19;
for (;;) for (;;)
{ {
status = virtual_unwind( UNW_FLAG_EHANDLER, &dispatch, &context ); status = virtual_unwind( UNW_FLAG_EHANDLER, &dispatch, &context );
@ -979,19 +934,12 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
context->u.s.X24, context->u.s.X25, context->u.s.X26, context->u.s.X27 ); context->u.s.X24, context->u.s.X25, context->u.s.X26, context->u.s.X27 );
TRACE(" x28=%016lx fp=%016lx lr=%016lx sp=%016lx\n", TRACE(" x28=%016lx fp=%016lx lr=%016lx sp=%016lx\n",
context->u.s.X28, context->u.s.Fp, context->u.s.Lr, context->Sp ); context->u.s.X28, context->u.s.Fp, context->u.s.Lr, context->Sp );
TRACE(" pc=%016lx\n",
context->Pc );
} }
status = send_debug_event( rec, TRUE, context ); if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION) goto done;
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
return STATUS_SUCCESS;
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION) if ((status = call_function_handlers( rec, context )) == STATUS_SUCCESS) goto done;
return STATUS_SUCCESS; if (status != STATUS_UNHANDLED_EXCEPTION) return status;
if ((status = call_function_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
return status;
} }
/* last chance exception */ /* last chance exception */
@ -1008,7 +956,62 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress ); rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode ); NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode );
} }
return STATUS_SUCCESS; done:
return NtSetContextThread( GetCurrentThread(), context );
}
/***********************************************************************
* setup_exception
*
* Setup the exception record and context on the thread stack.
*/
static struct stack_layout *setup_exception( ucontext_t *sigcontext )
{
struct stack_layout *stack;
DWORD exception_code = 0;
/* push the stack_layout structure */
stack = (struct stack_layout *)((SP_sig(sigcontext) - sizeof(*stack)) & ~15);
stack->rec.ExceptionRecord = NULL;
stack->rec.ExceptionCode = exception_code;
stack->rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
stack->rec.ExceptionAddress = (LPVOID)PC_sig(sigcontext);
stack->rec.NumberParameters = 0;
save_context( &stack->context, sigcontext );
save_fpu( &stack->context, sigcontext );
return stack;
}
/**********************************************************************
* raise_generic_exception
*/
static void WINAPI raise_generic_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status = raise_exception( rec, context, TRUE );
raise_status( status, rec );
}
/***********************************************************************
* setup_raise_exception
*
* Modify the signal context to call the exception raise function.
*/
static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *stack )
{
NTSTATUS status = send_debug_event( &stack->rec, TRUE, &stack->context );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
{
restore_context( &stack->context, sigcontext );
return;
}
SP_sig(sigcontext) = (ULONG_PTR)stack;
PC_sig(sigcontext) = (ULONG_PTR)raise_generic_exception;
REGn_sig(0, sigcontext) = (ULONG_PTR)&stack->rec; /* first arg for raise_generic_exception */
REGn_sig(1, sigcontext) = (ULONG_PTR)&stack->context; /* second arg for raise_generic_exception */
REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb();
} }
/********************************************************************** /**********************************************************************
@ -1790,10 +1793,10 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
TRACE(" x28=%016lx fp=%016lx lr=%016lx sp=%016lx\n", TRACE(" x28=%016lx fp=%016lx lr=%016lx sp=%016lx\n",
context->u.s.X28, context->u.s.Fp, context->u.s.Lr, context->Sp ); context->u.s.X28, context->u.s.Fp, context->u.s.Lr, context->Sp );
dispatch.EstablisherFrame = context->Sp;
dispatch.TargetPc = (ULONG64)target_ip; dispatch.TargetPc = (ULONG64)target_ip;
dispatch.ContextRecord = context; dispatch.ContextRecord = context;
dispatch.HistoryTable = table; dispatch.HistoryTable = table;
dispatch.NonVolatileRegisters = (BYTE *)&context->u.s.X19;
for (;;) for (;;)
{ {
@ -1891,9 +1894,13 @@ void WINAPI RtlUnwind( void *frame, void *target_ip, EXCEPTION_RECORD *rec, void
*/ */
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
{ {
NTSTATUS status = raise_exception( rec, context, first_chance ); if (first_chance)
if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context ); {
return status; NTSTATUS status = send_debug_event( rec, TRUE, context );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
NtSetContextThread( GetCurrentThread(), context );
}
return raise_exception( rec, context, first_chance );
} }
/*********************************************************************** /***********************************************************************
@ -1902,12 +1909,10 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL
void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec ) void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec )
{ {
CONTEXT context; CONTEXT context;
NTSTATUS status;
RtlCaptureContext( &context ); RtlCaptureContext( &context );
rec->ExceptionAddress = (LPVOID)context.Pc; rec->ExceptionAddress = (LPVOID)context.Pc;
status = raise_exception( rec, &context, TRUE ); RtlRaiseStatus( NtRaiseException( rec, &context, TRUE ));
if (status) raise_status( status, rec );
} }
/************************************************************************* /*************************************************************************