From f63bc569fab1450def4c817f100e580dddb425c5 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 11 Sep 2023 13:33:27 +0200 Subject: [PATCH] Windows/ARM64: Fix exception unwinding. Thanks to Peter Cawley. #593 --- src/host/buildvm_peobj.c | 14 +++++++------- src/lj_err.c | 10 ++++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c index fc3ef71a..cdbb79b6 100644 --- a/src/host/buildvm_peobj.c +++ b/src/host/buildvm_peobj.c @@ -354,7 +354,7 @@ void emit_peobj(BuildCtx *ctx) #define CBE16(x) (*p = ((x) >> 8) & 0xff, p[1] = (x) & 0xff, p += 2) #define CALLOC_S(s) (*p++ = ((s) >> 4)) /* s < 512 */ #define CSAVE_FPLR(o) (*p++ = 0x40 | ((o) >> 3)) /* o <= 504 */ -#define CSAVE_REGP(r,o) CBE16(0xc800 | (((r)-19)<< 6) | ((o) >> 3)) +#define CSAVE_REGP(r,o) CBE16(0xc800 | (((r) - 19) << 6) | ((o) >> 3)) #define CSAVE_REGS(r1,r2,o1) do { \ int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_REGP(r, o); \ } while (0) @@ -362,6 +362,7 @@ void emit_peobj(BuildCtx *ctx) #define CSAVE_FREGS(r1,r2,o1) do { \ int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_FREGP(r, o); \ } while (0) +#define CSAVE_REG(r,o) CBE16(0xd000 | (((r) - 19) << 6) | (~(o) >> 3)) #define CSAVE_REGX(r,o) CBE16(0xd400 | (((r) - 19) << 5) | (~(o) >> 3)) #define CADD_FP(s) CBE16(0xe200 | ((s) >> 3)) /* s < 8*256 */ #define CODE_NOP 0xe3 @@ -373,12 +374,11 @@ void emit_peobj(BuildCtx *ctx) /* Unwind codes for .text section with handler. */ p = uwc; - CALLOC_S(208); /* +1 */ - CSAVE_FPLR(192); /* +1 */ - CADD_FP(192); /* +2 */ CSAVE_REGS(19, 28, 184); /* +5*2 */ CSAVE_FREGS(8, 15, 104); /* +4*2 */ - CEND_ALIGN; /* +1 +1 -> 24 */ + CSAVE_FPLR(192); /* +1 */ + CALLOC_S(208); /* +1 */ + CEND_ALIGN; /* +1 +3 -> 24 */ u32 = ((24u >> 2) << 27) | (1u << 20) | (fcofs >> 2); owrite(ctx, &u32, 4); @@ -389,9 +389,9 @@ void emit_peobj(BuildCtx *ctx) /* Unwind codes for vm_ffi_call without handler. */ p = uwc; - CSAVE_FPLR(16); /* +1 */ CADD_FP(16); /* +2 */ - CSAVE_REGX(19, -24); /* +2 */ + CSAVE_FPLR(16); /* +1 */ + CSAVE_REG(19, 8); /* +2 */ CSAVE_REGX(20, -32); /* +2 */ CEND_ALIGN; /* +1 +0 -> 8 */ diff --git a/src/lj_err.c b/src/lj_err.c index 6e50cbee..8ef51bf2 100644 --- a/src/lj_err.c +++ b/src/lj_err.c @@ -261,6 +261,8 @@ LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, { #if LJ_TARGET_X86 void *cf = (char *)f - CFRAME_OFS_SEH; +#elif LJ_TARGET_ARM64 + void *cf = (char *)f - CFRAME_SIZE; #else void *cf = f; #endif @@ -297,11 +299,11 @@ LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, #else /* Unwind the stack and call all handlers for all lower C frames ** (including ourselves) again with EH_UNWINDING set. Then set - ** stack pointer = cf, result = errcode and jump to the specified target. + ** stack pointer = f, result = errcode and jump to the specified target. */ - RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? - lj_vm_unwind_ff_eh : - lj_vm_unwind_c_eh), + RtlUnwindEx(f, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? + lj_vm_unwind_ff_eh : + lj_vm_unwind_c_eh), rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); /* RtlUnwindEx should never return. */ #endif