diff options
Diffstat (limited to 'src/lj_err.c')
-rw-r--r-- | src/lj_err.c | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/src/lj_err.c b/src/lj_err.c index 9ac0c988..d641735e 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
@@ -190,13 +190,6 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
190 | ** since various OS, distros and compilers mess up the header installation. | 190 | ** since various OS, distros and compilers mess up the header installation. |
191 | */ | 191 | */ |
192 | 192 | ||
193 | typedef struct _Unwind_Exception | ||
194 | { | ||
195 | uint64_t exclass; | ||
196 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
197 | uintptr_t p1, p2; | ||
198 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
199 | |||
200 | typedef struct _Unwind_Context _Unwind_Context; | 193 | typedef struct _Unwind_Context _Unwind_Context; |
201 | 194 | ||
202 | #define _URC_OK 0 | 195 | #define _URC_OK 0 |
@@ -206,8 +199,20 @@ typedef struct _Unwind_Context _Unwind_Context; | |||
206 | #define _URC_CONTINUE_UNWIND 8 | 199 | #define _URC_CONTINUE_UNWIND 8 |
207 | #define _URC_FAILURE 9 | 200 | #define _URC_FAILURE 9 |
208 | 201 | ||
202 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
203 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
204 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
205 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
206 | |||
209 | #if !LJ_TARGET_ARM | 207 | #if !LJ_TARGET_ARM |
210 | 208 | ||
209 | typedef struct _Unwind_Exception | ||
210 | { | ||
211 | uint64_t exclass; | ||
212 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
213 | uintptr_t p1, p2; | ||
214 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
215 | |||
211 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 216 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
212 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 217 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
213 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 218 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
@@ -219,11 +224,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *); | |||
219 | #define _UA_HANDLER_FRAME 4 | 224 | #define _UA_HANDLER_FRAME 4 |
220 | #define _UA_FORCE_UNWIND 8 | 225 | #define _UA_FORCE_UNWIND 8 |
221 | 226 | ||
222 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
223 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
224 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
225 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
226 | |||
227 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ | 227 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ |
228 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | 228 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, |
229 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | 229 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) |
@@ -302,10 +302,23 @@ static void err_raise_ext(int errcode) | |||
302 | } | 302 | } |
303 | #endif | 303 | #endif |
304 | 304 | ||
305 | #else | 305 | #else /* LJ_TARGET_ARM */ |
306 | |||
307 | #define _US_VIRTUAL_UNWIND_FRAME 0 | ||
308 | #define _US_UNWIND_FRAME_STARTING 1 | ||
309 | #define _US_ACTION_MASK 3 | ||
310 | #define _US_FORCE_UNWIND 8 | ||
311 | |||
312 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | ||
313 | typedef struct _Unwind_Context _Unwind_Context; | ||
314 | |||
315 | struct _Unwind_Control_Block { | ||
316 | uint64_t exclass; | ||
317 | uint32_t misc[20]; | ||
318 | }; | ||
306 | 319 | ||
307 | extern void _Unwind_DeleteException(void *); | 320 | extern int _Unwind_RaiseException(_Unwind_Control_Block *); |
308 | extern int __gnu_unwind_frame (void *, _Unwind_Context *); | 321 | extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); |
309 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); | 322 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); |
310 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); | 323 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); |
311 | 324 | ||
@@ -321,34 +334,57 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |||
321 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); | 334 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); |
322 | } | 335 | } |
323 | 336 | ||
324 | #define _US_VIRTUAL_UNWIND_FRAME 0 | 337 | extern void lj_vm_unwind_ext(void); |
325 | #define _US_UNWIND_FRAME_STARTING 1 | ||
326 | #define _US_ACTION_MASK 3 | ||
327 | #define _US_FORCE_UNWIND 8 | ||
328 | 338 | ||
329 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | 339 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ |
330 | LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | 340 | LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, |
341 | _Unwind_Context *ctx) | ||
331 | { | 342 | { |
332 | void *cf = (void *)_Unwind_GetGR(ctx, 13); | 343 | void *cf = (void *)_Unwind_GetGR(ctx, 13); |
333 | lua_State *L = cframe_L(cf); | 344 | lua_State *L = cframe_L(cf); |
334 | if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { | 345 | int errcode; |
335 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 346 | |
347 | switch ((state & _US_ACTION_MASK)) { | ||
348 | case _US_VIRTUAL_UNWIND_FRAME: | ||
349 | if ((state & _US_FORCE_UNWIND)) break; | ||
336 | return _URC_HANDLER_FOUND; | 350 | return _URC_HANDLER_FOUND; |
337 | } | 351 | case _US_UNWIND_FRAME_STARTING: |
338 | if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { | 352 | if (LJ_UEXCLASS_CHECK(ucb->exclass)) { |
339 | _Unwind_DeleteException(ucb); | 353 | errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); |
340 | _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); | 354 | } else { |
341 | _Unwind_SetGR(ctx, 0, (uint32_t)L); | 355 | errcode = LUA_ERRRUN; |
342 | _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN); | 356 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
357 | } | ||
358 | cf = err_unwind(L, cf, errcode); | ||
359 | if ((state & _US_FORCE_UNWIND) || cf == NULL) break; | ||
360 | _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); | ||
361 | _Unwind_SetGR(ctx, 0, (uint32_t)ucb); | ||
362 | _Unwind_SetGR(ctx, 1, (uint32_t)errcode); | ||
363 | _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? | ||
364 | (uint32_t)lj_vm_unwind_ff_eh : | ||
365 | (uint32_t)lj_vm_unwind_c_eh); | ||
343 | return _URC_INSTALL_CONTEXT; | 366 | return _URC_INSTALL_CONTEXT; |
367 | default: | ||
368 | return _URC_FAILURE; | ||
344 | } | 369 | } |
345 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 370 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
346 | return _URC_FAILURE; | 371 | return _URC_FAILURE; |
347 | return _URC_CONTINUE_UNWIND; | 372 | return _URC_CONTINUE_UNWIND; |
348 | } | 373 | } |
349 | 374 | ||
375 | #if LJ_UNWIND_EXT | ||
376 | static __thread _Unwind_Control_Block static_uex; | ||
377 | |||
378 | static void err_raise_ext(int errcode) | ||
379 | { | ||
380 | memset(&static_uex, 0, sizeof(static_uex)); | ||
381 | static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); | ||
382 | _Unwind_RaiseException(&static_uex); | ||
383 | } | ||
350 | #endif | 384 | #endif |
351 | 385 | ||
386 | #endif /* LJ_TARGET_ARM */ | ||
387 | |||
352 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 388 | #elif LJ_TARGET_X64 && LJ_ABI_WIN |
353 | 389 | ||
354 | /* | 390 | /* |