Module: wine Branch: master Commit: 982e323070d5fb8dffbc68b75fb30c4be5f84e67 URL: https://gitlab.winehq.org/wine/wine/-/commit/982e323070d5fb8dffbc68b75fb30c4...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Jan 30 15:45:48 2024 +0100
ntdll: Report the correct address for breakpoint exception on ARM platforms.
---
dlls/ntdll/unix/signal_arm.c | 52 +++++++++++++++++++++++++++--------------- dlls/ntdll/unix/signal_arm64.c | 45 ++++++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 35 deletions(-)
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 2a375e6f15f..9ca0569bd62 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -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 ); }
diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 3b05f556e8e..bc5b8f0b88a 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -688,33 +688,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) & ~15); - 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 -= 4; + if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Pc -= 4;
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec ); stack->rec = *rec; - stack->context = context; + stack->context = *context;
SP_sig(sigcontext) = (ULONG_PTR)stack; PC_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; @@ -722,6 +716,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 */ @@ -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 ); }