diff options
| author | Mike Pall <mike> | 2023-09-11 13:33:27 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2023-09-11 13:33:27 +0200 |
| commit | f63bc569fab1450def4c817f100e580dddb425c5 (patch) | |
| tree | e3cabaf5b138f9affe4e004f741b48467c2f27f4 | |
| parent | 836ab4227a1b024321731fe5a5059368c9f0dff7 (diff) | |
| download | luajit-f63bc569fab1450def4c817f100e580dddb425c5.tar.gz luajit-f63bc569fab1450def4c817f100e580dddb425c5.tar.bz2 luajit-f63bc569fab1450def4c817f100e580dddb425c5.zip | |
Windows/ARM64: Fix exception unwinding.
Thanks to Peter Cawley. #593
| -rw-r--r-- | src/host/buildvm_peobj.c | 14 | ||||
| -rw-r--r-- | 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) | |||
| 354 | #define CBE16(x) (*p = ((x) >> 8) & 0xff, p[1] = (x) & 0xff, p += 2) | 354 | #define CBE16(x) (*p = ((x) >> 8) & 0xff, p[1] = (x) & 0xff, p += 2) |
| 355 | #define CALLOC_S(s) (*p++ = ((s) >> 4)) /* s < 512 */ | 355 | #define CALLOC_S(s) (*p++ = ((s) >> 4)) /* s < 512 */ |
| 356 | #define CSAVE_FPLR(o) (*p++ = 0x40 | ((o) >> 3)) /* o <= 504 */ | 356 | #define CSAVE_FPLR(o) (*p++ = 0x40 | ((o) >> 3)) /* o <= 504 */ |
| 357 | #define CSAVE_REGP(r,o) CBE16(0xc800 | (((r)-19)<< 6) | ((o) >> 3)) | 357 | #define CSAVE_REGP(r,o) CBE16(0xc800 | (((r) - 19) << 6) | ((o) >> 3)) |
| 358 | #define CSAVE_REGS(r1,r2,o1) do { \ | 358 | #define CSAVE_REGS(r1,r2,o1) do { \ |
| 359 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_REGP(r, o); \ | 359 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_REGP(r, o); \ |
| 360 | } while (0) | 360 | } while (0) |
| @@ -362,6 +362,7 @@ void emit_peobj(BuildCtx *ctx) | |||
| 362 | #define CSAVE_FREGS(r1,r2,o1) do { \ | 362 | #define CSAVE_FREGS(r1,r2,o1) do { \ |
| 363 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_FREGP(r, o); \ | 363 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_FREGP(r, o); \ |
| 364 | } while (0) | 364 | } while (0) |
| 365 | #define CSAVE_REG(r,o) CBE16(0xd000 | (((r) - 19) << 6) | (~(o) >> 3)) | ||
| 365 | #define CSAVE_REGX(r,o) CBE16(0xd400 | (((r) - 19) << 5) | (~(o) >> 3)) | 366 | #define CSAVE_REGX(r,o) CBE16(0xd400 | (((r) - 19) << 5) | (~(o) >> 3)) |
| 366 | #define CADD_FP(s) CBE16(0xe200 | ((s) >> 3)) /* s < 8*256 */ | 367 | #define CADD_FP(s) CBE16(0xe200 | ((s) >> 3)) /* s < 8*256 */ |
| 367 | #define CODE_NOP 0xe3 | 368 | #define CODE_NOP 0xe3 |
| @@ -373,12 +374,11 @@ void emit_peobj(BuildCtx *ctx) | |||
| 373 | 374 | ||
| 374 | /* Unwind codes for .text section with handler. */ | 375 | /* Unwind codes for .text section with handler. */ |
| 375 | p = uwc; | 376 | p = uwc; |
| 376 | CALLOC_S(208); /* +1 */ | ||
| 377 | CSAVE_FPLR(192); /* +1 */ | ||
| 378 | CADD_FP(192); /* +2 */ | ||
| 379 | CSAVE_REGS(19, 28, 184); /* +5*2 */ | 377 | CSAVE_REGS(19, 28, 184); /* +5*2 */ |
| 380 | CSAVE_FREGS(8, 15, 104); /* +4*2 */ | 378 | CSAVE_FREGS(8, 15, 104); /* +4*2 */ |
| 381 | CEND_ALIGN; /* +1 +1 -> 24 */ | 379 | CSAVE_FPLR(192); /* +1 */ |
| 380 | CALLOC_S(208); /* +1 */ | ||
| 381 | CEND_ALIGN; /* +1 +3 -> 24 */ | ||
| 382 | 382 | ||
| 383 | u32 = ((24u >> 2) << 27) | (1u << 20) | (fcofs >> 2); | 383 | u32 = ((24u >> 2) << 27) | (1u << 20) | (fcofs >> 2); |
| 384 | owrite(ctx, &u32, 4); | 384 | owrite(ctx, &u32, 4); |
| @@ -389,9 +389,9 @@ void emit_peobj(BuildCtx *ctx) | |||
| 389 | 389 | ||
| 390 | /* Unwind codes for vm_ffi_call without handler. */ | 390 | /* Unwind codes for vm_ffi_call without handler. */ |
| 391 | p = uwc; | 391 | p = uwc; |
| 392 | CSAVE_FPLR(16); /* +1 */ | ||
| 393 | CADD_FP(16); /* +2 */ | 392 | CADD_FP(16); /* +2 */ |
| 394 | CSAVE_REGX(19, -24); /* +2 */ | 393 | CSAVE_FPLR(16); /* +1 */ |
| 394 | CSAVE_REG(19, 8); /* +2 */ | ||
| 395 | CSAVE_REGX(20, -32); /* +2 */ | 395 | CSAVE_REGX(20, -32); /* +2 */ |
| 396 | CEND_ALIGN; /* +1 +0 -> 8 */ | 396 | CEND_ALIGN; /* +1 +0 -> 8 */ |
| 397 | 397 | ||
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, | |||
| 261 | { | 261 | { |
| 262 | #if LJ_TARGET_X86 | 262 | #if LJ_TARGET_X86 |
| 263 | void *cf = (char *)f - CFRAME_OFS_SEH; | 263 | void *cf = (char *)f - CFRAME_OFS_SEH; |
| 264 | #elif LJ_TARGET_ARM64 | ||
| 265 | void *cf = (char *)f - CFRAME_SIZE; | ||
| 264 | #else | 266 | #else |
| 265 | void *cf = f; | 267 | void *cf = f; |
| 266 | #endif | 268 | #endif |
| @@ -297,11 +299,11 @@ LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, | |||
| 297 | #else | 299 | #else |
| 298 | /* Unwind the stack and call all handlers for all lower C frames | 300 | /* Unwind the stack and call all handlers for all lower C frames |
| 299 | ** (including ourselves) again with EH_UNWINDING set. Then set | 301 | ** (including ourselves) again with EH_UNWINDING set. Then set |
| 300 | ** stack pointer = cf, result = errcode and jump to the specified target. | 302 | ** stack pointer = f, result = errcode and jump to the specified target. |
| 301 | */ | 303 | */ |
| 302 | RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | 304 | RtlUnwindEx(f, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? |
| 303 | lj_vm_unwind_ff_eh : | 305 | lj_vm_unwind_ff_eh : |
| 304 | lj_vm_unwind_c_eh), | 306 | lj_vm_unwind_c_eh), |
| 305 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); | 307 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); |
| 306 | /* RtlUnwindEx should never return. */ | 308 | /* RtlUnwindEx should never return. */ |
| 307 | #endif | 309 | #endif |
