From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/signal_arm64.c | 48 +++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 5f2be543ae1..54361eae892 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -184,6 +184,18 @@ struct syscall_frame C_ASSERT( sizeof( struct syscall_frame ) == 0x330 ); +#define ESR_ELx_EC(esr) (((DWORD64)(esr) >> 26) & 0x3f) +#define ESR_ELx_EC_IABT_LOW 0x20 +#define ESR_ELx_EC_IABT_CUR 0x21 +#define ESR_ELx_EC_PC_ALIGN 0x22 +#define ESR_ELx_EC_DABT_LOW 0x24 +#define ESR_ELx_EC_DABT_CUR 0x25 +#define ESR_ELx_EC_SOFTSTP_LOW 0x32 +#define ESR_ELx_EC_SOFTSTP_CUR 0x33 +#define ESR_ELx_EC_BRK64 0x3c +#define ESR_ELx_ISS_DABT_WNR(esr) (((esr) >> 6) & 0x01) +#define ESR_ELx_ISS_BRK_COMMENT(esr) ((esr) & 0xffff) + static DWORD64 make_esr( ULONG ec, ULONG info ) { return ((DWORD64)ec << 26) | (info & 0xffff); @@ -1069,11 +1081,26 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *_sigcontext ) EXCEPTION_RECORD rec = { .ExceptionAddress = (void *)PC_sig(sigcontext) }; DWORD64 esr = get_fault_esr( sigcontext ); - rec.NumberParameters = 2; - if ((esr & 0xf0000000) == 0x80000000) rec.ExceptionInformation[0] = EXCEPTION_EXECUTE_FAULT; - else if (esr & 0x40) rec.ExceptionInformation[0] = EXCEPTION_WRITE_FAULT; - else rec.ExceptionInformation[0] = EXCEPTION_READ_FAULT; + switch (ESR_ELx_EC(esr)) + { + case ESR_ELx_EC_IABT_LOW: + case ESR_ELx_EC_IABT_CUR: + case ESR_ELx_EC_PC_ALIGN: + rec.ExceptionInformation[0] = EXCEPTION_EXECUTE_FAULT; + break; + case ESR_ELx_EC_DABT_LOW: + case ESR_ELx_EC_DABT_CUR: + if (ESR_ELx_ISS_DABT_WNR(esr)) + rec.ExceptionInformation[0] = EXCEPTION_WRITE_FAULT; + else + rec.ExceptionInformation[0] = EXCEPTION_READ_FAULT; + break; + default: + rec.ExceptionInformation[0] = EXCEPTION_READ_FAULT; + break; + } rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; + rec.NumberParameters = 2; if (!virtual_handle_fault( data, &rec, (void *)SP_sig(sigcontext) )) return; if (handle_syscall_fault( data, sigcontext, &rec )) return; @@ -1154,25 +1181,26 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *_sigcontext ) switch (siginfo->si_code) { case TRAP_TRACE: - esr = make_esr( 0x33, 0 ); + esr = make_esr( ESR_ELx_EC_SOFTSTP_CUR, 0 ); break; case TRAP_BRKPT: if (!(PSTATE_sig( sigcontext ) & 0x10) && /* AArch64 (not WoW) */ !(PC_sig( sigcontext ) & 3)) - esr = make_esr( 0x3c, *(ULONG *)PC_sig( sigcontext ) >> 5 ); + esr = make_esr( ESR_ELx_EC_BRK64, *(ULONG *)PC_sig( sigcontext ) >> 5 ); break; } #else esr = get_fault_esr( sigcontext ); #endif - switch ((esr >> 26) & 0x3c) + switch (ESR_ELx_EC(esr)) { - case 0x30: /* software step */ + case ESR_ELx_EC_SOFTSTP_LOW: + case ESR_ELx_EC_SOFTSTP_CUR: rec.ExceptionCode = EXCEPTION_SINGLE_STEP; break; - case 0x3c: /* bkpt */ - switch (esr & 0xffff) + case ESR_ELx_EC_BRK64: /* bkpt */ + switch (ESR_ELx_ISS_BRK_COMMENT(esr)) { case 0xf000: context.Pc += 4; /* skip the brk instruction */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10899