mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
ARM: Add external frame unwinding.
Thanks to Nick Zavaritsky.
This commit is contained in:
parent
a687a60eaa
commit
f61148c486
@ -261,11 +261,20 @@ void emit_asm(BuildCtx *ctx)
|
|||||||
|
|
||||||
#if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND
|
#if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND
|
||||||
/* This should really be moved into buildvm_arm.dasc. */
|
/* This should really be moved into buildvm_arm.dasc. */
|
||||||
|
#if LJ_ARCH_HASFPU
|
||||||
|
fprintf(ctx->fp,
|
||||||
|
".fnstart\n"
|
||||||
|
".save {r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
||||||
|
".vsave {d8-d15}\n"
|
||||||
|
".save {r4}\n"
|
||||||
|
".pad #28\n");
|
||||||
|
#else
|
||||||
fprintf(ctx->fp,
|
fprintf(ctx->fp,
|
||||||
".fnstart\n"
|
".fnstart\n"
|
||||||
".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
||||||
".pad #28\n");
|
".pad #28\n");
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#if LJ_TARGET_MIPS
|
#if LJ_TARGET_MIPS
|
||||||
fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n");
|
fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n");
|
||||||
#endif
|
#endif
|
||||||
|
92
src/lj_err.c
92
src/lj_err.c
@ -190,13 +190,6 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
|
|||||||
** since various OS, distros and compilers mess up the header installation.
|
** since various OS, distros and compilers mess up the header installation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct _Unwind_Exception
|
|
||||||
{
|
|
||||||
uint64_t exclass;
|
|
||||||
void (*excleanup)(int, struct _Unwind_Exception *);
|
|
||||||
uintptr_t p1, p2;
|
|
||||||
} __attribute__((__aligned__)) _Unwind_Exception;
|
|
||||||
|
|
||||||
typedef struct _Unwind_Context _Unwind_Context;
|
typedef struct _Unwind_Context _Unwind_Context;
|
||||||
|
|
||||||
#define _URC_OK 0
|
#define _URC_OK 0
|
||||||
@ -206,8 +199,20 @@ typedef struct _Unwind_Context _Unwind_Context;
|
|||||||
#define _URC_CONTINUE_UNWIND 8
|
#define _URC_CONTINUE_UNWIND 8
|
||||||
#define _URC_FAILURE 9
|
#define _URC_FAILURE 9
|
||||||
|
|
||||||
|
#define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */
|
||||||
|
#define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c))
|
||||||
|
#define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff)
|
||||||
|
#define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff))
|
||||||
|
|
||||||
#if !LJ_TARGET_ARM
|
#if !LJ_TARGET_ARM
|
||||||
|
|
||||||
|
typedef struct _Unwind_Exception
|
||||||
|
{
|
||||||
|
uint64_t exclass;
|
||||||
|
void (*excleanup)(int, struct _Unwind_Exception *);
|
||||||
|
uintptr_t p1, p2;
|
||||||
|
} __attribute__((__aligned__)) _Unwind_Exception;
|
||||||
|
|
||||||
extern uintptr_t _Unwind_GetCFA(_Unwind_Context *);
|
extern uintptr_t _Unwind_GetCFA(_Unwind_Context *);
|
||||||
extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t);
|
extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t);
|
||||||
extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t);
|
extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t);
|
||||||
@ -219,11 +224,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *);
|
|||||||
#define _UA_HANDLER_FRAME 4
|
#define _UA_HANDLER_FRAME 4
|
||||||
#define _UA_FORCE_UNWIND 8
|
#define _UA_FORCE_UNWIND 8
|
||||||
|
|
||||||
#define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */
|
|
||||||
#define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c))
|
|
||||||
#define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff)
|
|
||||||
#define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff))
|
|
||||||
|
|
||||||
/* DWARF2 personality handler referenced from interpreter .eh_frame. */
|
/* DWARF2 personality handler referenced from interpreter .eh_frame. */
|
||||||
LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions,
|
LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions,
|
||||||
uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx)
|
uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx)
|
||||||
@ -302,10 +302,23 @@ static void err_raise_ext(int errcode)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else /* LJ_TARGET_ARM */
|
||||||
|
|
||||||
extern void _Unwind_DeleteException(void *);
|
#define _US_VIRTUAL_UNWIND_FRAME 0
|
||||||
extern int __gnu_unwind_frame (void *, _Unwind_Context *);
|
#define _US_UNWIND_FRAME_STARTING 1
|
||||||
|
#define _US_ACTION_MASK 3
|
||||||
|
#define _US_FORCE_UNWIND 8
|
||||||
|
|
||||||
|
typedef struct _Unwind_Control_Block _Unwind_Control_Block;
|
||||||
|
typedef struct _Unwind_Context _Unwind_Context;
|
||||||
|
|
||||||
|
struct _Unwind_Control_Block {
|
||||||
|
uint64_t exclass;
|
||||||
|
uint32_t misc[20];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int _Unwind_RaiseException(_Unwind_Control_Block *);
|
||||||
|
extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *);
|
||||||
extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *);
|
extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *);
|
||||||
extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *);
|
extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *);
|
||||||
|
|
||||||
@ -321,34 +334,57 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v)
|
|||||||
_Unwind_VRS_Set(ctx, 0, r, 0, &v);
|
_Unwind_VRS_Set(ctx, 0, r, 0, &v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _US_VIRTUAL_UNWIND_FRAME 0
|
extern void lj_vm_unwind_ext(void);
|
||||||
#define _US_UNWIND_FRAME_STARTING 1
|
|
||||||
#define _US_ACTION_MASK 3
|
|
||||||
#define _US_FORCE_UNWIND 8
|
|
||||||
|
|
||||||
/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */
|
/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */
|
||||||
LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx)
|
LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb,
|
||||||
|
_Unwind_Context *ctx)
|
||||||
{
|
{
|
||||||
void *cf = (void *)_Unwind_GetGR(ctx, 13);
|
void *cf = (void *)_Unwind_GetGR(ctx, 13);
|
||||||
lua_State *L = cframe_L(cf);
|
lua_State *L = cframe_L(cf);
|
||||||
if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) {
|
int errcode;
|
||||||
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
|
|
||||||
|
switch ((state & _US_ACTION_MASK)) {
|
||||||
|
case _US_VIRTUAL_UNWIND_FRAME:
|
||||||
|
if ((state & _US_FORCE_UNWIND)) break;
|
||||||
return _URC_HANDLER_FOUND;
|
return _URC_HANDLER_FOUND;
|
||||||
}
|
case _US_UNWIND_FRAME_STARTING:
|
||||||
if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) {
|
if (LJ_UEXCLASS_CHECK(ucb->exclass)) {
|
||||||
_Unwind_DeleteException(ucb);
|
errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass);
|
||||||
_Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw);
|
} else {
|
||||||
_Unwind_SetGR(ctx, 0, (uint32_t)L);
|
errcode = LUA_ERRRUN;
|
||||||
_Unwind_SetGR(ctx, 1, (uint32_t)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;
|
return _URC_INSTALL_CONTEXT;
|
||||||
|
default:
|
||||||
|
return _URC_FAILURE;
|
||||||
}
|
}
|
||||||
if (__gnu_unwind_frame(ucb, ctx) != _URC_OK)
|
if (__gnu_unwind_frame(ucb, ctx) != _URC_OK)
|
||||||
return _URC_FAILURE;
|
return _URC_FAILURE;
|
||||||
return _URC_CONTINUE_UNWIND;
|
return _URC_CONTINUE_UNWIND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LJ_UNWIND_EXT
|
||||||
|
static __thread _Unwind_Control_Block static_uex;
|
||||||
|
|
||||||
|
static void err_raise_ext(int errcode)
|
||||||
|
{
|
||||||
|
memset(&static_uex, 0, sizeof(static_uex));
|
||||||
|
static_uex.exclass = LJ_UEXCLASS_MAKE(errcode);
|
||||||
|
_Unwind_RaiseException(&static_uex);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* LJ_TARGET_ARM */
|
||||||
|
|
||||||
#elif LJ_TARGET_X64 && LJ_ABI_WIN
|
#elif LJ_TARGET_X64 && LJ_ABI_WIN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -372,6 +372,17 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| str CARG1, [BASE, #-4] // Prepend false to error message.
|
| str CARG1, [BASE, #-4] // Prepend false to error message.
|
||||||
| st_vmstate CARG2
|
| st_vmstate CARG2
|
||||||
| b ->vm_returnc
|
| b ->vm_returnc
|
||||||
|
|
|
||||||
|
|->vm_unwind_ext: // Complete external unwind.
|
||||||
|
#if !LJ_NO_UNWIND
|
||||||
|
| push {r0, r1, r2, lr}
|
||||||
|
| bl extern _Unwind_Complete
|
||||||
|
| ldr r0, [sp]
|
||||||
|
| bl extern _Unwind_DeleteException
|
||||||
|
| pop {r0, r1, r2, lr}
|
||||||
|
| mov r0, r1
|
||||||
|
| bx r2
|
||||||
|
#endif
|
||||||
|
|
|
|
||||||
|//-----------------------------------------------------------------------
|
|//-----------------------------------------------------------------------
|
||||||
|//-- Grow stack for calls -----------------------------------------------
|
|//-- Grow stack for calls -----------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user