diff --git a/src/buildvm_asm.c b/src/buildvm_asm.c index 6468912c..35f413b9 100644 --- a/src/buildvm_asm.c +++ b/src/buildvm_asm.c @@ -191,6 +191,14 @@ void emit_asm(BuildCtx *ctx) if (ctx->mode != BUILD_machasm) fprintf(ctx->fp, ".Lbegin:\n"); +#if LJ_TARGET_ARM && defined(__GNUC__) + /* This should really be moved into buildvm_arm.dasc. */ + fprintf(ctx->fp, + ".fnstart\n" + ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" + ".pad #28\n"); +#endif + for (i = rel = 0; i < ctx->nsym; i++) { int32_t ofs = ctx->sym[i].ofs; int32_t next = ctx->sym[i+1].ofs; @@ -219,6 +227,13 @@ void emit_asm(BuildCtx *ctx) #endif } +#if LJ_TARGET_ARM && defined(__GNUC__) + fprintf(ctx->fp, + ".globl lj_err_unwind_arm\n" + ".personality lj_err_unwind_arm\n" + ".fnend\n"); +#endif + fprintf(ctx->fp, "\n"); switch (ctx->mode) { case BUILD_elfasm: diff --git a/src/lj_err.c b/src/lj_err.c index d1d326e9..11f0922f 100644 --- a/src/lj_err.c +++ b/src/lj_err.c @@ -531,7 +531,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) /* -- External frame unwinding -------------------------------------------- */ -#if defined(__GNUC__) && !LJ_TARGET_ARM +#if defined(__GNUC__) #ifdef __clang__ /* http://llvm.org/bugs/show_bug.cgi?id=8703 */ @@ -545,6 +545,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) +#if !LJ_TARGET_ARM + /* DWARF2 personality handler referenced from interpreter .eh_frame. */ LJ_FUNCA int lj_err_unwind_dwarf(int version, _Unwind_Action actions, _Unwind_Exception_Class uexclass, struct _Unwind_Exception *uex, @@ -618,6 +620,33 @@ static void err_raise_ext(int errcode) } #endif +#else + +/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ +LJ_FUNCA _Unwind_Reason_Code lj_err_unwind_arm(_Unwind_State state, + _Unwind_Control_Block *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_UNWIND_FRAME_STARTING) { + _Unwind_DeleteException(ucb); + _Unwind_SetGR(ctx, 15, (_Unwind_Word)(void *)lj_err_throw); + _Unwind_SetGR(ctx, 0, (_Unwind_Word)L); + _Unwind_SetGR(ctx, 1, (_Unwind_Word)LUA_ERRRUN); + return _URC_INSTALL_CONTEXT; + } + if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) + return _URC_FAILURE; + return _URC_CONTINUE_UNWIND; +} + +#endif + #elif LJ_TARGET_X64 && LJ_TARGET_WINDOWS /*