/* DWARF2 personality handler referenced from interpreter .eh_frame. */ LJ_FUNCA int lj_err_unwind_dwarf(int version, _Unwind_Action actions, uint64_t uexclass, struct _Unwind_Exception *uex, struct _Unwind_Context *ctx) { void *cf; lua_State *L; if (version != 1) return _URC_FATAL_PHASE1_ERROR; UNUSED(uexclass); cf = (void *)_Unwind_GetCFA(ctx); L = cframe_L(cf); if ((actions & _UA_SEARCH_PHASE)) { #if LJ_UNWIND_EXT if (err_unwind(L, cf, 0) == NULL) return _URC_CONTINUE_UNWIND; #endif if (!LJ_UEXCLASS_CHECK(uexclass)) { setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); } return _URC_HANDLER_FOUND; } if ((actions & _UA_CLEANUP_PHASE)) { int errcode; if (LJ_UEXCLASS_CHECK(uexclass)) { errcode = LJ_UEXCLASS_ERRCODE(uexclass); } else { if ((actions & _UA_HANDLER_FRAME)) _Unwind_DeleteException(uex); errcode = LUA_ERRRUN; } #if LJ_UNWIND_EXT cf = err_unwind(L, cf, errcode); if ((actions & _UA_FORCE_UNWIND)) { return _URC_CONTINUE_UNWIND; } else if (cf) { _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode); _Unwind_SetIP(ctx, (uintptr_t)(cframe_unwind_ff(cf) ? lj_vm_unwind_ff_eh : lj_vm_unwind_c_eh)); return _URC_INSTALL_CONTEXT; } #if LJ_TARGET_X86ORX64 else if ((actions & _UA_HANDLER_FRAME)) { /* Workaround for ancient libgcc bug. Still present in RHEL 5.5. :-/ ** Real fix: http://gcc.gnu.org/viewcvs/trunk/gcc/unwind-dw2.c?r1=121165&r2=124837&pathrev=153877&diff_format=h */ _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode); _Unwind_SetIP(ctx, (uintptr_t)lj_vm_unwind_rethrow); return _URC_INSTALL_CONTEXT; } #endif #else /* This is not the proper way to escape from the unwinder. We get away with ** it on x86/PPC because the interpreter restores all callee-saved regs. */ lj_err_throw(L, errcode); #endif } return _URC_CONTINUE_UNWIND; }
/* Win64 exception handler for interpreter frame. */ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) { lua_State *L = cframe_L(cf); int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */ /* Unwind internal frames. */ err_unwind(L, cf, errcode); } else { void *cf2 = err_unwind(L, cf, 0); if (cf2) { /* We catch it, so start unwinding the upper frames. */ if (rec->ExceptionCode == LJ_MSVC_EXCODE) { #ifdef _MSC_VER __DestructExceptionObject(rec, 1); #endif setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { /* Don't catch access violations etc. */ return ExceptionContinueSearch; } /* Unwind the stack and call all handlers for all lower C frames ** (including ourselves) again with EH_UNWINDING set. Then set ** rsp = cf, rax = 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), rec, (void *)errcode, ctx, dispatch->HistoryTable); /* RtlUnwindEx should never return. */ } } return ExceptionContinueSearch; }
/* Out-of-memory error. */ LJ_NOINLINE void lj_err_mem(lua_State *L) { if (L->status == LUA_ERRERR+1) /* Don't touch the stack during lua_open. */ lj_vm_unwind_c(L->cframe, LUA_ERRMEM); setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM)); lj_err_throw(L, LUA_ERRMEM); }
/* Setup lexer state. */ void lj_lex_setup(lua_State *L, LexState *ls) { ls->L = L; ls->fs = NULL; ls->n = 0; ls->p = NULL; ls->vstack = NULL; ls->sizevstack = 0; ls->vtop = 0; ls->bcstack = NULL; ls->sizebcstack = 0; ls->lookahead = TK_eof; /* No look-ahead token. */ ls->linenumber = 1; ls->lastline = 1; lj_str_resizebuf(ls->L, &ls->sb, LJ_MIN_SBUF); next(ls); /* Read-ahead first char. */ if (ls->current == 0xef && ls->n >= 2 && char2int(ls->p[0]) == 0xbb && char2int(ls->p[1]) == 0xbf) { /* Skip UTF-8 BOM (if buffered). */ ls->n -= 2; ls->p += 2; next(ls); } if (ls->current == '#') { /* Skip POSIX #! header line. */ do { next(ls); if (ls->current == END_OF_STREAM) return; } while (!currIsNewline(ls)); inclinenumber(ls); } if (ls->current == LUA_SIGNATURE[0]) { setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XBCLOAD)); lj_err_throw(L, LUA_ERRSYNTAX); } }
/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, _Unwind_Context *ctx) { void *cf = (void *)_Unwind_GetGR(ctx, 13); lua_State *L = cframe_L(cf); int errcode; switch ((state & _US_ACTION_MASK)) { case _US_VIRTUAL_UNWIND_FRAME: if ((state & _US_FORCE_UNWIND)) break; return _URC_HANDLER_FOUND; case _US_UNWIND_FRAME_STARTING: if (LJ_UEXCLASS_CHECK(ucb->exclass)) { errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); } else { errcode = LUA_ERRRUN; setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); } cf = err_unwind(L, cf, errcode); if ((state & _US_FORCE_UNWIND) || cf == NULL) break; _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); _Unwind_SetGR(ctx, 0, (uint32_t)ucb); _Unwind_SetGR(ctx, 1, (uint32_t)errcode); _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? (uint32_t)lj_vm_unwind_ff_eh : (uint32_t)lj_vm_unwind_c_eh); return _URC_INSTALL_CONTEXT; default: return _URC_FAILURE; } if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) return _URC_FAILURE; return _URC_CONTINUE_UNWIND; }
/* Protection twiddling failed. Probably due to kernel security. */ static LJ_NOINLINE void mcode_protfail(jit_State *J) { lua_CFunction panic = J2G(J)->panic; if (panic) { lua_State *L = J->L; setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITPROT)); panic(L); } }
/* Setup lexer state. */ int lj_lex_setup(lua_State *L, LexState *ls) { int header = 0; ls->L = L; ls->fs = NULL; ls->n = 0; ls->p = NULL; ls->vstack = NULL; ls->sizevstack = 0; ls->vtop = 0; ls->bcstack = NULL; ls->sizebcstack = 0; ls->lookahead = TK_eof; /* No look-ahead token. */ ls->linenumber = 1; ls->lastline = 1; lj_str_resizebuf(ls->L, &ls->sb, LJ_MIN_SBUF); next(ls); /* Read-ahead first char. */ if (ls->current == 0xef && ls->n >= 2 && char2int(ls->p[0]) == 0xbb && char2int(ls->p[1]) == 0xbf) { /* Skip UTF-8 BOM (if buffered). */ ls->n -= 2; ls->p += 2; next(ls); header = 1; } if (ls->current == '#') { /* Skip POSIX #! header line. */ do { next(ls); if (ls->current == END_OF_STREAM) return 0; } while (!currIsNewline(ls)); inclinenumber(ls); header = 1; } if (ls->current == LUA_SIGNATURE[0]) { /* Bytecode dump. */ if (header) { /* ** Loading bytecode with an extra header is disabled for security ** reasons. This may circumvent the usual check for bytecode vs. ** Lua code by looking at the first char. Since this is a potential ** security violation no attempt is made to echo the chunkname either. */ setstrV(L, L->top++, lj_err_str(L, LJ_ERR_BCBAD)); lj_err_throw(L, LUA_ERRSYNTAX); } return 1; } return 0; }
/* Runtime error. */ LJ_NOINLINE void lj_err_run(lua_State *L) { ptrdiff_t ef = finderrfunc(L); if (ef) { TValue *errfunc = restorestack(L, ef); TValue *top = L->top; lj_trace_abort(G(L)); if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) { setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR)); lj_err_throw(L, LUA_ERRERR); } L->status = LUA_ERRERR; copyTV(L, top, top-1); copyTV(L, top-1, errfunc); L->top = top+1; lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ } lj_err_throw(L, LUA_ERRRUN); }
static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) { LexState *ls = (LexState *)ud; GCproto *pt; GCfunc *fn; int bc; UNUSED(dummy); cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ bc = lj_lex_setup(L, ls); if (ls->mode && !strchr(ls->mode, bc ? 'b' : 't')) { setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); lj_err_throw(L, LUA_ERRSYNTAX); } pt = bc ? lj_bcread(ls) : lj_parse(ls); fn = lj_func_newL_empty(L, pt, tabref(L->env)); /* Don't combine above/below into one statement. */ setfuncV(L, L->top++, fn); return NULL; }
/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) { void *cf = (void *)_Unwind_GetGR(ctx, 13); lua_State *L = cframe_L(cf); if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); return _URC_HANDLER_FOUND; } if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { _Unwind_DeleteException(ucb); _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); _Unwind_SetGR(ctx, 0, (uint32_t)L); _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN); return _URC_INSTALL_CONTEXT; } if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) return _URC_FAILURE; return _URC_CONTINUE_UNWIND; }