[PATCH 0/1] MR10899: ntdll: Add constants/helpers, and be more explicit when parsing the ARM64 ESR.
There shouldn't be any behavior changes here, my goal was to avoid ambiguity and magic numbers in the ARM64 signal handlers when parsing ESR. The EC is an enum, I think it's confusing and ambiguous to match against only certain bits of it. I stuck with the same names for the constants that the Linux kernel uses (see [`arch/arm64/include/asm/esr.h`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch...)), since ARM's [documentation](https://developer.arm.com/documentation/ddi0601/2026-03/AArch64-Registers/ES...) doesn't have names for them. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10899
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
participants (2)
-
Brendan Shanks -
Brendan Shanks (@bshanks)