diff options
Diffstat (limited to 'src/lj_err.c')
-rw-r--r-- | src/lj_err.c | 399 |
1 files changed, 273 insertions, 126 deletions
diff --git a/src/lj_err.c b/src/lj_err.c index ebc9ad12..b2e7f5f8 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
@@ -20,6 +20,63 @@ | |||
20 | #include "lj_trace.h" | 20 | #include "lj_trace.h" |
21 | #include "lj_vm.h" | 21 | #include "lj_vm.h" |
22 | 22 | ||
23 | /* | ||
24 | ** LuaJIT can either use internal or external frame unwinding: | ||
25 | ** | ||
26 | ** - Internal frame unwinding (INT) is free-standing and doesn't require | ||
27 | ** any OS or library support. | ||
28 | ** | ||
29 | ** - External frame unwinding (EXT) uses the system-provided unwind handler. | ||
30 | ** | ||
31 | ** Pros and Cons: | ||
32 | ** | ||
33 | ** - EXT requires unwind tables for *all* functions on the C stack between | ||
34 | ** the pcall/catch and the error/throw. This is the default on x64, | ||
35 | ** but needs to be manually enabled on x86 for non-C++ code. | ||
36 | ** | ||
37 | ** - INT is faster when actually throwing errors (but this happens rarely). | ||
38 | ** Setting up error handlers is zero-cost in any case. | ||
39 | ** | ||
40 | ** - EXT provides full interoperability with C++ exceptions. You can throw | ||
41 | ** Lua errors or C++ exceptions through a mix of Lua frames and C++ frames. | ||
42 | ** C++ destructors are called as needed. C++ exceptions caught by pcall | ||
43 | ** are converted to the string "C++ exception". Lua errors can be caught | ||
44 | ** with catch (...) in C++. | ||
45 | ** | ||
46 | ** - INT has only limited support for automatically catching C++ exceptions | ||
47 | ** on POSIX systems using DWARF2 stack unwinding. Other systems may use | ||
48 | ** the wrapper function feature. Lua errors thrown through C++ frames | ||
49 | ** cannot be caught by C++ code and C++ destructors are not run. | ||
50 | ** | ||
51 | ** INT is the default on x86 systems, EXT is the default on x64 systems. | ||
52 | ** | ||
53 | ** EXT can only be manually enabled on POSIX/x86 systems using DWARF2 stack | ||
54 | ** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled | ||
55 | ** with -funwind-tables (or -fexceptions). This includes LuaJIT itself (set | ||
56 | ** TARGET_CFLAGS), all of your C/Lua binding code, all loadable C modules | ||
57 | ** and all C libraries that have callbacks which may be used to call back | ||
58 | ** into Lua. C++ code must *not* be compiled with -fno-exceptions. | ||
59 | ** | ||
60 | ** EXT cannot be enabled on WIN32 since system exceptions use code-driven SEH. | ||
61 | ** EXT is mandatory on WIN64 since the calling convention has an abundance | ||
62 | ** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). | ||
63 | ** EXT is mandatory on POSIX/x64 since the interpreter doesn't save r12/r13. | ||
64 | */ | ||
65 | |||
66 | #if defined(__ELF__) || defined(__MACH__) | ||
67 | #if LJ_TARGET_X86 | ||
68 | #ifdef LUAJIT_UNWIND_EXTERNAL | ||
69 | #define LJ_UNWIND_EXT 1 | ||
70 | #endif | ||
71 | #elif LJ_TARGET_X64 | ||
72 | #define LJ_UNWIND_EXT 1 | ||
73 | #endif | ||
74 | #elif defined(LUA_USE_WIN) | ||
75 | #if LJ_TARGET_X64 | ||
76 | #define LJ_UNWIND_EXT 1 | ||
77 | #endif | ||
78 | #endif | ||
79 | |||
23 | /* -- Error messages ------------------------------------------------------ */ | 80 | /* -- Error messages ------------------------------------------------------ */ |
24 | 81 | ||
25 | /* Error message strings. */ | 82 | /* Error message strings. */ |
@@ -374,117 +431,249 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar) | |||
374 | } | 431 | } |
375 | } | 432 | } |
376 | 433 | ||
377 | /* -- Error handling ------------------------------------------------------ */ | 434 | /* -- Internal frame unwinding -------------------------------------------- */ |
378 | |||
379 | /* Return string object for error message. */ | ||
380 | LJ_NOINLINE GCstr *lj_err_str(lua_State *L, ErrMsg em) | ||
381 | { | ||
382 | return lj_str_newz(L, err2msg(em)); | ||
383 | } | ||
384 | 435 | ||
385 | /* Unwind Lua stack and add error message on top. */ | 436 | /* Unwind Lua stack and move error message to new top. */ |
386 | LJ_NOINLINE static void unwindstack(lua_State *L, TValue *top, int errcode) | 437 | LJ_NOINLINE static void unwindstack(lua_State *L, TValue *top) |
387 | { | 438 | { |
388 | lj_func_closeuv(L, top); | 439 | lj_func_closeuv(L, top); |
389 | switch (errcode) { | 440 | if (top < L->top-1) { |
390 | case LUA_ERRMEM: | 441 | copyTV(L, top, L->top-1); |
391 | setstrV(L, top, lj_err_str(L, LJ_ERR_ERRMEM)); | 442 | L->top = top+1; |
392 | break; | ||
393 | case LUA_ERRERR: | ||
394 | setstrV(L, top, lj_err_str(L, LJ_ERR_ERRERR)); | ||
395 | break; | ||
396 | case LUA_ERRSYNTAX: | ||
397 | case LUA_ERRRUN: | ||
398 | copyTV(L, top, L->top - 1); | ||
399 | break; | ||
400 | default: | ||
401 | lua_assert(0); | ||
402 | break; | ||
403 | } | 443 | } |
404 | L->top = top+1; | ||
405 | lj_state_relimitstack(L); | 444 | lj_state_relimitstack(L); |
406 | } | 445 | } |
407 | 446 | ||
408 | /* Throw error. Find catch frame, unwind stack and continue. */ | 447 | /* Unwind until stop frame. Optionally cleanup frames. */ |
409 | LJ_NOINLINE void lj_err_throw(lua_State *L, int errcode) | 448 | static void *err_unwind(lua_State *L, void *stopcf, int errcode) |
410 | { | 449 | { |
411 | TValue *frame = L->base-1; | 450 | TValue *frame = L->base-1; |
412 | void *cf = L->cframe; | 451 | void *cf = L->cframe; |
413 | global_State *g = G(L); | ||
414 | if (L->status == LUA_ERRERR+1) { /* Don't touch the stack during lua_open. */ | ||
415 | lj_vm_unwind_c(cf, errcode); | ||
416 | goto uncaught; /* unreachable */ | ||
417 | } | ||
418 | lj_trace_abort(g); | ||
419 | setgcrefnull(g->jit_L); | ||
420 | L->status = 0; | ||
421 | while (cf) { | 452 | while (cf) { |
422 | if (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ | 453 | int32_t nres = cframe_nres(cframe_raw(cf)); |
423 | TValue *top = restorestack(L, -cframe_nres(cf)); | 454 | if (nres < 0) { /* C frame without Lua frame? */ |
424 | if (frame < top) { | 455 | TValue *top = restorestack(L, -nres); |
425 | L->cframe = cframe_prev(cf); | 456 | if (frame < top) { /* Frame reached? */ |
426 | L->base = frame+1; | 457 | if (errcode) { |
427 | unwindstack(L, top, errcode); | 458 | L->cframe = cframe_prev(cf); |
428 | lj_vm_unwind_c(cf, errcode); | 459 | L->base = frame+1; |
429 | goto uncaught; /* unreachable */ | 460 | unwindstack(L, top); |
461 | } | ||
462 | return cf; | ||
430 | } | 463 | } |
431 | } | 464 | } |
432 | if (frame <= L->stack) | 465 | if (frame <= L->stack) |
433 | break; | 466 | break; |
434 | switch (frame_typep(frame)) { | 467 | switch (frame_typep(frame)) { |
435 | case FRAME_LUA: | 468 | case FRAME_LUA: /* Lua frame. */ |
436 | case FRAME_LUAP: | 469 | case FRAME_LUAP: |
437 | frame = frame_prevl(frame); | 470 | frame = frame_prevl(frame); |
438 | break; | 471 | break; |
439 | case FRAME_C: | 472 | case FRAME_C: /* C frame. */ |
440 | if (cframe_canyield(cf)) goto uncaught; | 473 | #if LJ_UNWIND_EXT |
474 | if (errcode) { | ||
475 | L->cframe = cframe_prev(cf); | ||
476 | L->base = frame_prevd(frame) + 1; | ||
477 | unwindstack(L, frame); | ||
478 | } else if (cf != stopcf) { | ||
479 | cf = cframe_prev(cf); | ||
480 | frame = frame_prevd(frame); | ||
481 | break; | ||
482 | } | ||
483 | return NULL; /* Continue unwinding. */ | ||
484 | #else | ||
485 | UNUSED(stopcf); | ||
441 | cf = cframe_prev(cf); | 486 | cf = cframe_prev(cf); |
442 | /* fallthrough */ | ||
443 | case FRAME_CONT: | ||
444 | case FRAME_VARG: | ||
445 | frame = frame_prevd(frame); | 487 | frame = frame_prevd(frame); |
446 | break; | 488 | break; |
447 | case FRAME_CP: | 489 | #endif |
448 | L->cframe = cframe_prev(cf); | 490 | case FRAME_CP: /* Protected C frame. */ |
449 | L->base = frame_prevd(frame) + 1; | 491 | if (cframe_canyield(cf)) { /* Resume? */ |
450 | unwindstack(L, frame, errcode); | 492 | if (errcode) { |
451 | lj_vm_unwind_c(cf, errcode); | 493 | L->cframe = NULL; |
452 | goto uncaught; /* unreachable */ | 494 | L->status = cast_byte(errcode); |
453 | case FRAME_PCALL: | 495 | } |
454 | hook_leave(g); | 496 | return cframe_raw(cf); |
497 | } | ||
498 | if (errcode) { | ||
499 | L->cframe = cframe_prev(cf); | ||
500 | L->base = frame_prevd(frame) + 1; | ||
501 | unwindstack(L, frame); | ||
502 | } | ||
503 | return cf; | ||
504 | case FRAME_CONT: /* Continuation frame. */ | ||
505 | case FRAME_VARG: /* Vararg frame. */ | ||
506 | frame = frame_prevd(frame); | ||
507 | break; | ||
508 | case FRAME_PCALL: /* FF pcall() frame. */ | ||
509 | if (errcode) | ||
510 | hook_leave(G(L)); | ||
455 | /* fallthrough */ | 511 | /* fallthrough */ |
456 | case FRAME_PCALLH: | 512 | case FRAME_PCALLH: /* FF pcall() frame inside hook. */ |
457 | L->cframe = cf; | 513 | if (errcode) { |
458 | L->base = frame_prevd(frame) + 1; | 514 | L->cframe = cf; |
459 | unwindstack(L, L->base, errcode); | 515 | L->base = frame_prevd(frame) + 1; |
460 | lj_vm_unwind_ff(cf); | 516 | unwindstack(L, L->base); |
461 | goto uncaught; /* unreachable */ | 517 | return NULL; /* Call special handler. */ |
462 | default: | 518 | } |
463 | lua_assert(0); | 519 | return cf; |
464 | goto uncaught; | ||
465 | } | 520 | } |
466 | } | 521 | } |
467 | /* No catch frame found. Must be a resume or an unprotected error. */ | 522 | /* No C frame. */ |
468 | uncaught: | 523 | if (errcode) { |
469 | L->status = cast_byte(errcode); | 524 | L->cframe = NULL; |
470 | L->cframe = NULL; | 525 | L->base = L->stack+1; |
471 | if (cframe_canyield(cf)) { /* Resume? */ | 526 | unwindstack(L, L->base); |
472 | unwindstack(L, L->top, errcode); | 527 | if (G(L)->panic) |
473 | lj_vm_unwind_c(cframe_raw(cf), errcode); | 528 | G(L)->panic(L); |
529 | exit(EXIT_FAILURE); | ||
474 | } | 530 | } |
475 | /* Better rethrow on main thread than panic. */ | 531 | return L; /* Anything not-NULL will do. */ |
476 | { | 532 | } |
477 | if (L != mainthread(g)) | 533 | |
478 | lj_err_throw(mainthread(g), errcode); | 534 | /* -- External frame unwinding -------------------------------------------- */ |
479 | if (g->panic) { | 535 | |
480 | L->base = L->stack+1; | 536 | #if defined(__ELF__) || defined(__MACH__) |
481 | unwindstack(L, L->base, errcode); | 537 | |
482 | g->panic(L); | 538 | #include <unwind.h> |
539 | |||
540 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
541 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (_Unwind_Exception_Class)(c)) | ||
542 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
543 | #define LJ_UEXCLASS_ERRCODE(cl) (cast_int((cl) & 0xff)) | ||
544 | |||
545 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ | ||
546 | LJ_FUNCA int lj_err_unwind_dwarf(int version, _Unwind_Action actions, | ||
547 | _Unwind_Exception_Class uexclass, struct _Unwind_Exception *uex, | ||
548 | struct _Unwind_Context *ctx) | ||
549 | { | ||
550 | void *cf; | ||
551 | lua_State *L; | ||
552 | if (version != 1) | ||
553 | return _URC_FATAL_PHASE1_ERROR; | ||
554 | UNUSED(uexclass); | ||
555 | cf = (void *)_Unwind_GetCFA(ctx); | ||
556 | L = cframe_L(cf); | ||
557 | if ((actions & _UA_SEARCH_PHASE)) { | ||
558 | #if LJ_UNWIND_EXT | ||
559 | if (err_unwind(L, cf, 0) == NULL) | ||
560 | return _URC_CONTINUE_UNWIND; | ||
561 | #endif | ||
562 | if (!LJ_UEXCLASS_CHECK(uexclass)) { | ||
563 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | ||
564 | } | ||
565 | return _URC_HANDLER_FOUND; | ||
566 | } | ||
567 | if ((actions & _UA_CLEANUP_PHASE)) { | ||
568 | int errcode; | ||
569 | if (LJ_UEXCLASS_CHECK(uexclass)) { | ||
570 | errcode = LJ_UEXCLASS_ERRCODE(uexclass); | ||
571 | } else { | ||
572 | if ((actions & _UA_HANDLER_FRAME)) | ||
573 | _Unwind_DeleteException(uex); | ||
574 | errcode = LUA_ERRRUN; | ||
575 | } | ||
576 | #if LJ_UNWIND_EXT | ||
577 | if (err_unwind(L, cf, errcode)) { | ||
578 | _Unwind_SetGR(ctx, 0, errcode); | ||
579 | _Unwind_SetIP(ctx, (_Unwind_Ptr)lj_vm_unwind_c_eh); | ||
580 | return _URC_INSTALL_CONTEXT; | ||
581 | } else if ((actions & _UA_HANDLER_FRAME)) { | ||
582 | _Unwind_SetIP(ctx, (_Unwind_Ptr)lj_vm_unwind_ff_eh); | ||
583 | return _URC_INSTALL_CONTEXT; | ||
483 | } | 584 | } |
585 | #else | ||
586 | /* This is not the proper way to escape from the unwinder. We get away | ||
587 | ** with it on x86 because the interpreter restores all callee-saved regs. | ||
588 | */ | ||
589 | lj_err_throw(L, errcode); | ||
590 | #endif | ||
591 | } | ||
592 | return _URC_CONTINUE_UNWIND; | ||
593 | } | ||
594 | |||
595 | #if LJ_UNWIND_EXT | ||
596 | /* NYI: this is not thread-safe. */ | ||
597 | static struct _Unwind_Exception static_uex; | ||
598 | |||
599 | /* Raise DWARF2 exception. */ | ||
600 | static void err_raise_ext(int errcode) | ||
601 | { | ||
602 | static_uex.exception_class = LJ_UEXCLASS_MAKE(errcode); | ||
603 | static_uex.exception_cleanup = NULL; | ||
604 | _Unwind_RaiseException(&static_uex); | ||
605 | } | ||
606 | #endif | ||
607 | |||
608 | #elif defined(_WIN64) | ||
609 | |||
610 | #define WIN32_LEAN_AND_MEAN | ||
611 | #include <windows.h> | ||
612 | |||
613 | #define LJ_EXCODE ((DWORD)0x024c4a00) | ||
614 | #define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) | ||
615 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | ||
616 | #define LJ_EXCODE_ERRCODE(cl) (cast_int((cl) & 0xff)) | ||
617 | |||
618 | /* NYI: Win64 exception handler for interpreter frame. */ | ||
619 | |||
620 | /* Raise Windows exception. */ | ||
621 | static void err_raise_ext(int errcode) | ||
622 | { | ||
623 | RaiseException(LJ_EXCODE_MAKE(errcode), 0, 0, NULL); | ||
624 | } | ||
625 | |||
626 | #endif | ||
627 | |||
628 | /* -- Error handling ------------------------------------------------------ */ | ||
629 | |||
630 | /* Throw error. Find catch frame, unwind stack and continue. */ | ||
631 | LJ_NOINLINE void lj_err_throw(lua_State *L, int errcode) | ||
632 | { | ||
633 | global_State *g = G(L); | ||
634 | lj_trace_abort(g); | ||
635 | setgcrefnull(g->jit_L); | ||
636 | L->status = 0; | ||
637 | #if LJ_UNWIND_EXT | ||
638 | err_raise_ext(errcode); | ||
639 | /* | ||
640 | ** A return from this function signals a corrupt C stack that cannot be | ||
641 | ** unwound. We have no choice but to call the panic function and exit. | ||
642 | ** | ||
643 | ** Usually this is caused by a C function without unwind information. | ||
644 | ** This should never happen on x64, but may happen on x86 if you've | ||
645 | ** manually enabled LUAJIT_UNWIND_EXTERNAL and forgot to recompile *every* | ||
646 | ** non-C++ file with -funwind-tables. | ||
647 | */ | ||
648 | if (G(L)->panic) | ||
649 | G(L)->panic(L); | ||
650 | #else | ||
651 | { | ||
652 | void *cf = err_unwind(L, NULL, errcode); | ||
653 | if (cf) | ||
654 | lj_vm_unwind_c(cf, errcode); | ||
655 | else | ||
656 | lj_vm_unwind_ff(cframe_raw(L->cframe)); | ||
484 | } | 657 | } |
658 | #endif | ||
485 | exit(EXIT_FAILURE); | 659 | exit(EXIT_FAILURE); |
486 | } | 660 | } |
487 | 661 | ||
662 | /* Return string object for error message. */ | ||
663 | LJ_NOINLINE GCstr *lj_err_str(lua_State *L, ErrMsg em) | ||
664 | { | ||
665 | return lj_str_newz(L, err2msg(em)); | ||
666 | } | ||
667 | |||
668 | /* Out-of-memory error. */ | ||
669 | LJ_NOINLINE void lj_err_mem(lua_State *L) | ||
670 | { | ||
671 | if (L->status == LUA_ERRERR+1) /* Don't touch the stack during lua_open. */ | ||
672 | lj_vm_unwind_c(L->cframe, LUA_ERRMEM); | ||
673 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM)); | ||
674 | lj_err_throw(L, LUA_ERRMEM); | ||
675 | } | ||
676 | |||
488 | /* Find error function for runtime errors. Requires an extra stack traversal. */ | 677 | /* Find error function for runtime errors. Requires an extra stack traversal. */ |
489 | static ptrdiff_t finderrfunc(lua_State *L) | 678 | static ptrdiff_t finderrfunc(lua_State *L) |
490 | { | 679 | { |
@@ -507,7 +696,6 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
507 | frame = frame_prevl(frame); | 696 | frame = frame_prevl(frame); |
508 | break; | 697 | break; |
509 | case FRAME_C: | 698 | case FRAME_C: |
510 | if (cframe_canyield(cf)) return 0; | ||
511 | cf = cframe_prev(cf); | 699 | cf = cframe_prev(cf); |
512 | /* fallthrough */ | 700 | /* fallthrough */ |
513 | case FRAME_CONT: | 701 | case FRAME_CONT: |
@@ -515,6 +703,7 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
515 | frame = frame_prevd(frame); | 703 | frame = frame_prevd(frame); |
516 | break; | 704 | break; |
517 | case FRAME_CP: | 705 | case FRAME_CP: |
706 | if (cframe_canyield(cf)) return 0; | ||
518 | if (cframe_errfunc(cf) >= 0) | 707 | if (cframe_errfunc(cf) >= 0) |
519 | return cframe_errfunc(cf); | 708 | return cframe_errfunc(cf); |
520 | frame = frame_prevd(frame); | 709 | frame = frame_prevd(frame); |
@@ -540,8 +729,10 @@ LJ_NOINLINE void lj_err_run(lua_State *L) | |||
540 | TValue *errfunc = restorestack(L, ef); | 729 | TValue *errfunc = restorestack(L, ef); |
541 | TValue *top = L->top; | 730 | TValue *top = L->top; |
542 | lj_trace_abort(G(L)); | 731 | lj_trace_abort(G(L)); |
543 | if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) | 732 | if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) { |
733 | setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR)); | ||
544 | lj_err_throw(L, LUA_ERRERR); | 734 | lj_err_throw(L, LUA_ERRERR); |
735 | } | ||
545 | L->status = LUA_ERRERR; | 736 | L->status = LUA_ERRERR; |
546 | copyTV(L, top, top-1); | 737 | copyTV(L, top, top-1); |
547 | copyTV(L, top-1, errfunc); | 738 | copyTV(L, top-1, errfunc); |
@@ -763,47 +954,3 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) | |||
763 | return 0; /* unreachable */ | 954 | return 0; /* unreachable */ |
764 | } | 955 | } |
765 | 956 | ||
766 | /* -- C++ exception support ----------------------------------------------- */ | ||
767 | |||
768 | #if defined(__ELF__) || defined(__MACH__) | ||
769 | typedef enum | ||
770 | { | ||
771 | _URC_NO_REASON, | ||
772 | _URC_FOREIGN_EXCEPTION_CAUGHT, | ||
773 | _URC_FATAL_PHASE2_ERROR, | ||
774 | _URC_FATAL_PHASE1_ERROR, | ||
775 | _URC_NORMAL_STOP, | ||
776 | _URC_END_OF_STACK, | ||
777 | _URC_HANDLER_FOUND, | ||
778 | _URC_INSTALL_CONTEXT, | ||
779 | _URC_CONTINUE_UNWIND | ||
780 | } _Unwind_Reason_Code; | ||
781 | |||
782 | #define _UA_SEARCH_PHASE 1 | ||
783 | #define _UA_CLEANUP_PHASE 2 | ||
784 | #define _UA_HANDLER_FRAME 4 | ||
785 | #define _UA_FORCE_UNWIND 8 | ||
786 | #define _UA_END_OF_STACK 16 | ||
787 | |||
788 | extern void *_Unwind_GetCFA(void *ctx); | ||
789 | extern void _Unwind_DeleteException(void *uex); | ||
790 | |||
791 | /* DWARF2 personality handler referenced from .eh_frame. */ | ||
792 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, uint64_t uexclass, | ||
793 | void *uex, void *ctx) | ||
794 | { | ||
795 | if (version != 1) | ||
796 | return _URC_FATAL_PHASE1_ERROR; | ||
797 | UNUSED(uexclass); | ||
798 | if ((actions & _UA_SEARCH_PHASE)) | ||
799 | return _URC_HANDLER_FOUND; | ||
800 | if ((actions & _UA_HANDLER_FRAME)) { | ||
801 | void *cf = _Unwind_GetCFA(ctx); | ||
802 | lua_State *L = cframe_L(cf); | ||
803 | _Unwind_DeleteException(uex); | ||
804 | lj_err_msg(L, LJ_ERR_ERRCPP); | ||
805 | } | ||
806 | return _URC_CONTINUE_UNWIND; | ||
807 | } | ||
808 | #endif | ||
809 | |||