1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

ntdll: Report the correct address for breakpoint exception on ARM platforms.

This commit is contained in:
Alexandre Julliard 2024-01-30 15:45:48 +01:00
parent 008f64557d
commit 982e323070
2 changed files with 71 additions and 44 deletions

View file

@ -967,33 +967,27 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size )
/***********************************************************************
* setup_exception
*
* Modify the signal context to call the exception raise function.
* setup_raise_exception
*/
static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, CONTEXT *context )
{
struct exc_stack_layout *stack;
void *stack_ptr = (void *)(SP_sig(sigcontext) & ~7);
CONTEXT context;
NTSTATUS status;
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
save_context( &context, sigcontext );
status = send_debug_event( rec, &context, TRUE );
status = send_debug_event( rec, context, TRUE );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
{
restore_context( &context, sigcontext );
restore_context( context, sigcontext );
return;
}
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context.Pc -= 2;
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Pc -= 2;
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
stack->context = context;
stack->context = *context;
/* now modify the sigcontext to return to the raise function */
SP_sig(sigcontext) = (DWORD)stack;
@ -1003,6 +997,21 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
}
/***********************************************************************
* setup_exception
*
* Modify the signal context to call the exception raise function.
*/
static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
{
CONTEXT context;
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
save_context( &context, sigcontext );
setup_raise_exception( sigcontext, rec, &context );
}
/***********************************************************************
* call_user_apc_dispatcher
*/
@ -1243,6 +1252,10 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = sigcontext;
CONTEXT ctx;
rec.ExceptionAddress = (void *)PC_sig(context);
save_context( &ctx, sigcontext );
switch (get_trap_code(signal, context))
{
@ -1251,10 +1264,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
case 0xfb: /* __fastfail */
{
CONTEXT ctx;
save_context( &ctx, sigcontext );
rec.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
rec.ExceptionAddress = (void *)ctx.Pc;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.NumberParameters = 1;
rec.ExceptionInformation[0] = ctx.R0;
@ -1262,7 +1272,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
return;
}
case 0xfe: /* breakpoint */
PC_sig(context) += 2; /* skip the instruction */
ctx.Pc += 2; /* skip the breakpoint instruction */
rec.ExceptionCode = EXCEPTION_BREAKPOINT;
rec.NumberParameters = 1;
break;
@ -1294,7 +1304,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
break;
}
if (handle_syscall_fault( context, &rec )) return;
setup_exception( context, &rec );
setup_raise_exception( context, &rec, &ctx );
}
@ -1306,6 +1316,11 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = sigcontext;
CONTEXT ctx;
rec.ExceptionAddress = (void *)PC_sig(context);
save_context( &ctx, sigcontext );
switch (siginfo->si_code)
{
@ -1314,11 +1329,12 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
break;
case TRAP_BRKPT:
default:
ctx.Pc += 2; /* skip the breakpoint instruction */
rec.ExceptionCode = EXCEPTION_BREAKPOINT;
rec.NumberParameters = 1;
break;
}
setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, &rec, &ctx );
}

View file

@ -687,6 +687,35 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size )
}
/***********************************************************************
* setup_raise_exception
*/
static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, CONTEXT *context )
{
struct exc_stack_layout *stack;
void *stack_ptr = (void *)(SP_sig(sigcontext) & ~15);
NTSTATUS status;
status = send_debug_event( rec, context, TRUE );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
{
restore_context( context, sigcontext );
return;
}
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Pc -= 4;
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
stack->context = *context;
SP_sig(sigcontext) = (ULONG_PTR)stack;
PC_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher;
REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb();
}
/***********************************************************************
* setup_exception
*
@ -694,31 +723,11 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size )
*/
static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
{
struct exc_stack_layout *stack;
void *stack_ptr = (void *)(SP_sig(sigcontext) & ~15);
CONTEXT context;
NTSTATUS status;
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
save_context( &context, sigcontext );
status = send_debug_event( rec, &context, TRUE );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
{
restore_context( &context, sigcontext );
return;
}
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context.Pc -= 4;
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
stack->context = context;
SP_sig(sigcontext) = (ULONG_PTR)stack;
PC_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher;
REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb();
setup_raise_exception( sigcontext, rec, &context );
}
@ -1069,6 +1078,10 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = sigcontext;
CONTEXT ctx;
rec.ExceptionAddress = (void *)PC_sig(context);
save_context( &ctx, sigcontext );
switch (siginfo->si_code)
{
@ -1082,22 +1095,20 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
!(PC_sig( context ) & 3) &&
*(ULONG *)PC_sig( context ) == 0xd43e0060UL) /* brk #0xf003 -> __fastfail */
{
CONTEXT ctx;
save_context( &ctx, sigcontext );
rec.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
rec.ExceptionAddress = (void *)ctx.Pc;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.NumberParameters = 1;
rec.ExceptionInformation[0] = ctx.X[0];
NtRaiseException( &rec, &ctx, FALSE );
return;
}
PC_sig( context ) += 4; /* skip the brk instruction */
ctx.Pc += 4; /* skip the brk instruction */
rec.ExceptionCode = EXCEPTION_BREAKPOINT;
rec.NumberParameters = 1;
break;
}
setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, &rec, &ctx );
}