aboutsummaryrefslogtreecommitdiff
path: root/src/lj_err.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_err.c')
-rw-r--r--src/lj_err.c98
1 files changed, 83 insertions, 15 deletions
diff --git a/src/lj_err.c b/src/lj_err.c
index b2e7f5f8..b8070250 100644
--- a/src/lj_err.c
+++ b/src/lj_err.c
@@ -493,7 +493,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
493 L->cframe = NULL; 493 L->cframe = NULL;
494 L->status = cast_byte(errcode); 494 L->status = cast_byte(errcode);
495 } 495 }
496 return cframe_raw(cf); 496 return cf;
497 } 497 }
498 if (errcode) { 498 if (errcode) {
499 L->cframe = cframe_prev(cf); 499 L->cframe = cframe_prev(cf);
@@ -514,9 +514,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
514 L->cframe = cf; 514 L->cframe = cf;
515 L->base = frame_prevd(frame) + 1; 515 L->base = frame_prevd(frame) + 1;
516 unwindstack(L, L->base); 516 unwindstack(L, L->base);
517 return NULL; /* Call special handler. */
518 } 517 }
519 return cf; 518 return (void *)((intptr_t)cf | CFRAME_UNWIND_FF);
520 } 519 }
521 } 520 }
522 /* No C frame. */ 521 /* No C frame. */
@@ -528,7 +527,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
528 G(L)->panic(L); 527 G(L)->panic(L);
529 exit(EXIT_FAILURE); 528 exit(EXIT_FAILURE);
530 } 529 }
531 return L; /* Anything not-NULL will do. */ 530 return L; /* Anything non-NULL will do. */
532} 531}
533 532
534/* -- External frame unwinding -------------------------------------------- */ 533/* -- External frame unwinding -------------------------------------------- */
@@ -574,12 +573,12 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, _Unwind_Action actions,
574 errcode = LUA_ERRRUN; 573 errcode = LUA_ERRRUN;
575 } 574 }
576#if LJ_UNWIND_EXT 575#if LJ_UNWIND_EXT
577 if (err_unwind(L, cf, errcode)) { 576 cf = err_unwind(L, cf, errcode);
577 if (cf) {
578 _Unwind_SetGR(ctx, 0, errcode); 578 _Unwind_SetGR(ctx, 0, errcode);
579 _Unwind_SetIP(ctx, (_Unwind_Ptr)lj_vm_unwind_c_eh); 579 _Unwind_SetIP(ctx, (_Unwind_Ptr)(cframe_unwind_ff(cf) ?
580 return _URC_INSTALL_CONTEXT; 580 lj_vm_unwind_ff_eh :
581 } else if ((actions & _UA_HANDLER_FRAME)) { 581 lj_vm_unwind_c_eh));
582 _Unwind_SetIP(ctx, (_Unwind_Ptr)lj_vm_unwind_ff_eh);
583 return _URC_INSTALL_CONTEXT; 582 return _URC_INSTALL_CONTEXT;
584 } 583 }
585#else 584#else
@@ -607,20 +606,89 @@ static void err_raise_ext(int errcode)
607 606
608#elif defined(_WIN64) 607#elif defined(_WIN64)
609 608
609/*
610** Someone in Redmond owes me several days of my life. A lot of this is
611** undocumented or just plain wrong on MSDN. Some of it can be gathered
612** from 3rd party docs or must be found by trial-and-error. They really
613** don't want you to write your own language-specific exception handler
614** or to interact gracefully with MSVC. :-(
615**
616** Apparently MSVC doesn't call C++ destructors for foreign exceptions
617** unless you compile your C++ code with /EHa. Unfortunately this means
618** catch (...) also catches things like access violations. The use of
619** _set_se_translator doesn't really help, because it requires /EHa, too.
620*/
621
610#define WIN32_LEAN_AND_MEAN 622#define WIN32_LEAN_AND_MEAN
611#include <windows.h> 623#include <windows.h>
612 624
613#define LJ_EXCODE ((DWORD)0x024c4a00) 625/* Taken from: http://www.nynaeve.net/?p=99 */
626typedef struct UndocumentedDispatcherContext {
627 ULONG64 ControlPc;
628 ULONG64 ImageBase;
629 PRUNTIME_FUNCTION FunctionEntry;
630 ULONG64 EstablisherFrame;
631 ULONG64 TargetIp;
632 PCONTEXT ContextRecord;
633 PEXCEPTION_ROUTINE LanguageHandler;
634 PVOID HandlerData;
635 PUNWIND_HISTORY_TABLE HistoryTable;
636 ULONG ScopeIndex;
637 ULONG Fill0;
638} UndocumentedDispatcherContext;
639
640#ifdef _MSC_VER
641/* Another wild guess. */
642extern __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
643#endif
644
645#define LJ_MSVC_EXCODE ((DWORD)0xe06d7363)
646
647#define LJ_EXCODE ((DWORD)0xe24c4a00)
614#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) 648#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c))
615#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) 649#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
616#define LJ_EXCODE_ERRCODE(cl) (cast_int((cl) & 0xff)) 650#define LJ_EXCODE_ERRCODE(cl) (cast_int((cl) & 0xff))
617 651
618/* NYI: Win64 exception handler for interpreter frame. */ 652/* Win64 exception handler for interpreter frame. */
653LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
654 void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
655{
656 lua_State *L = cframe_L(cf);
657 if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */
658 err_unwind(L, cf, 1); /* Unwind internal frames. */
659 } else {
660 void *cf2 = err_unwind(L, cf, 0);
661 if (cf2) { /* We catch it, so start unwinding the upper frames. */
662 int errcode;
663 if (LJ_EXCODE_CHECK(rec->ExceptionCode)) {
664 errcode = LJ_EXCODE_ERRCODE(rec->ExceptionCode);
665 } else if (rec->ExceptionCode == LJ_MSVC_EXCODE) {
666#ifdef _MSC_VER
667 __DestructExceptionObject(rec, 1);
668#endif
669 setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
670 errcode = LUA_ERRRUN;
671 } else { /* Don't catch access violations etc. */
672 return ExceptionContinueSearch;
673 }
674 /* Unwind the stack and call all handlers for all lower C frames
675 ** (including ourselves) again with EH_UNWINDING set. Then set
676 ** rsp = cf, rax = errcode and jump to the specified target.
677 */
678 RtlUnwindEx(cf, (void *)(cframe_unwind_ff(cf2) ?
679 lj_vm_unwind_ff_eh :
680 lj_vm_unwind_c_eh),
681 rec, (void *)errcode, ctx, dispatch->HistoryTable);
682 /* RtlUnwindEx should never return. */
683 }
684 }
685 return ExceptionContinueSearch;
686}
619 687
620/* Raise Windows exception. */ 688/* Raise Windows exception. */
621static void err_raise_ext(int errcode) 689static void err_raise_ext(int errcode)
622{ 690{
623 RaiseException(LJ_EXCODE_MAKE(errcode), 0, 0, NULL); 691 RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL);
624} 692}
625 693
626#endif 694#endif
@@ -650,10 +718,10 @@ LJ_NOINLINE void lj_err_throw(lua_State *L, int errcode)
650#else 718#else
651 { 719 {
652 void *cf = err_unwind(L, NULL, errcode); 720 void *cf = err_unwind(L, NULL, errcode);
653 if (cf) 721 if (cframe_unwind_ff(cf))
654 lj_vm_unwind_c(cf, errcode); 722 lj_vm_unwind_ff(cframe_raw(cf));
655 else 723 else
656 lj_vm_unwind_ff(cframe_raw(L->cframe)); 724 lj_vm_unwind_c(cframe_raw(cf), errcode);
657 } 725 }
658#endif 726#endif
659 exit(EXIT_FAILURE); 727 exit(EXIT_FAILURE);