diff options
Diffstat (limited to 'src/lj_err.c')
-rw-r--r-- | src/lj_err.c | 205 |
1 files changed, 128 insertions, 77 deletions
diff --git a/src/lj_err.c b/src/lj_err.c index 13a1ded7..abf176e5 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "lj_ff.h" | 16 | #include "lj_ff.h" |
17 | #include "lj_trace.h" | 17 | #include "lj_trace.h" |
18 | #include "lj_vm.h" | 18 | #include "lj_vm.h" |
19 | #include "lj_strfmt.h" | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | ** LuaJIT can either use internal or external frame unwinding: | 22 | ** LuaJIT can either use internal or external frame unwinding: |
@@ -45,7 +46,8 @@ | |||
45 | ** the wrapper function feature. Lua errors thrown through C++ frames | 46 | ** the wrapper function feature. Lua errors thrown through C++ frames |
46 | ** cannot be caught by C++ code and C++ destructors are not run. | 47 | ** cannot be caught by C++ code and C++ destructors are not run. |
47 | ** | 48 | ** |
48 | ** EXT is the default on x64 systems, INT is the default on all other systems. | 49 | ** EXT is the default on x64 systems and on Windows, INT is the default on all |
50 | ** other systems. | ||
49 | ** | 51 | ** |
50 | ** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack | 52 | ** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack |
51 | ** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled | 53 | ** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled |
@@ -54,7 +56,6 @@ | |||
54 | ** and all C libraries that have callbacks which may be used to call back | 56 | ** and all C libraries that have callbacks which may be used to call back |
55 | ** into Lua. C++ code must *not* be compiled with -fno-exceptions. | 57 | ** into Lua. C++ code must *not* be compiled with -fno-exceptions. |
56 | ** | 58 | ** |
57 | ** EXT cannot be enabled on WIN32 since system exceptions use code-driven SEH. | ||
58 | ** EXT is mandatory on WIN64 since the calling convention has an abundance | 59 | ** EXT is mandatory on WIN64 since the calling convention has an abundance |
59 | ** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). | 60 | ** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). |
60 | ** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4). | 61 | ** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4). |
@@ -62,7 +63,7 @@ | |||
62 | 63 | ||
63 | #if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND | 64 | #if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND |
64 | #define LJ_UNWIND_EXT 1 | 65 | #define LJ_UNWIND_EXT 1 |
65 | #elif LJ_TARGET_X64 && LJ_TARGET_WINDOWS | 66 | #elif LJ_TARGET_WINDOWS |
66 | #define LJ_UNWIND_EXT 1 | 67 | #define LJ_UNWIND_EXT 1 |
67 | #endif | 68 | #endif |
68 | 69 | ||
@@ -98,14 +99,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
98 | TValue *top = restorestack(L, -nres); | 99 | TValue *top = restorestack(L, -nres); |
99 | if (frame < top) { /* Frame reached? */ | 100 | if (frame < top) { /* Frame reached? */ |
100 | if (errcode) { | 101 | if (errcode) { |
101 | L->cframe = cframe_prev(cf); | ||
102 | L->base = frame+1; | 102 | L->base = frame+1; |
103 | L->cframe = cframe_prev(cf); | ||
103 | unwindstack(L, top); | 104 | unwindstack(L, top); |
104 | } | 105 | } |
105 | return cf; | 106 | return cf; |
106 | } | 107 | } |
107 | } | 108 | } |
108 | if (frame <= tvref(L->stack)) | 109 | if (frame <= tvref(L->stack)+LJ_FR2) |
109 | break; | 110 | break; |
110 | switch (frame_typep(frame)) { | 111 | switch (frame_typep(frame)) { |
111 | case FRAME_LUA: /* Lua frame. */ | 112 | case FRAME_LUA: /* Lua frame. */ |
@@ -113,14 +114,12 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
113 | frame = frame_prevl(frame); | 114 | frame = frame_prevl(frame); |
114 | break; | 115 | break; |
115 | case FRAME_C: /* C frame. */ | 116 | case FRAME_C: /* C frame. */ |
116 | #if LJ_HASFFI | ||
117 | unwind_c: | 117 | unwind_c: |
118 | #endif | ||
119 | #if LJ_UNWIND_EXT | 118 | #if LJ_UNWIND_EXT |
120 | if (errcode) { | 119 | if (errcode) { |
121 | L->cframe = cframe_prev(cf); | ||
122 | L->base = frame_prevd(frame) + 1; | 120 | L->base = frame_prevd(frame) + 1; |
123 | unwindstack(L, frame); | 121 | L->cframe = cframe_prev(cf); |
122 | unwindstack(L, frame - LJ_FR2); | ||
124 | } else if (cf != stopcf) { | 123 | } else if (cf != stopcf) { |
125 | cf = cframe_prev(cf); | 124 | cf = cframe_prev(cf); |
126 | frame = frame_prevd(frame); | 125 | frame = frame_prevd(frame); |
@@ -143,16 +142,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
143 | return cf; | 142 | return cf; |
144 | } | 143 | } |
145 | if (errcode) { | 144 | if (errcode) { |
146 | L->cframe = cframe_prev(cf); | ||
147 | L->base = frame_prevd(frame) + 1; | 145 | L->base = frame_prevd(frame) + 1; |
148 | unwindstack(L, frame); | 146 | L->cframe = cframe_prev(cf); |
147 | unwindstack(L, frame - LJ_FR2); | ||
149 | } | 148 | } |
150 | return cf; | 149 | return cf; |
151 | case FRAME_CONT: /* Continuation frame. */ | 150 | case FRAME_CONT: /* Continuation frame. */ |
152 | #if LJ_HASFFI | 151 | if (frame_iscont_fficb(frame)) |
153 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
154 | goto unwind_c; | 152 | goto unwind_c; |
155 | #endif | ||
156 | /* fallthrough */ | 153 | /* fallthrough */ |
157 | case FRAME_VARG: /* Vararg frame. */ | 154 | case FRAME_VARG: /* Vararg frame. */ |
158 | frame = frame_prevd(frame); | 155 | frame = frame_prevd(frame); |
@@ -166,8 +163,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
166 | } | 163 | } |
167 | if (frame_typep(frame) == FRAME_PCALL) | 164 | if (frame_typep(frame) == FRAME_PCALL) |
168 | hook_leave(G(L)); | 165 | hook_leave(G(L)); |
169 | L->cframe = cf; | ||
170 | L->base = frame_prevd(frame) + 1; | 166 | L->base = frame_prevd(frame) + 1; |
167 | L->cframe = cf; | ||
171 | unwindstack(L, L->base); | 168 | unwindstack(L, L->base); |
172 | } | 169 | } |
173 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); | 170 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); |
@@ -175,8 +172,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
175 | } | 172 | } |
176 | /* No C frame. */ | 173 | /* No C frame. */ |
177 | if (errcode) { | 174 | if (errcode) { |
175 | L->base = tvref(L->stack)+1+LJ_FR2; | ||
178 | L->cframe = NULL; | 176 | L->cframe = NULL; |
179 | L->base = tvref(L->stack)+1; | ||
180 | unwindstack(L, L->base); | 177 | unwindstack(L, L->base); |
181 | if (G(L)->panic) | 178 | if (G(L)->panic) |
182 | G(L)->panic(L); | 179 | G(L)->panic(L); |
@@ -194,13 +191,6 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
194 | ** since various OS, distros and compilers mess up the header installation. | 191 | ** since various OS, distros and compilers mess up the header installation. |
195 | */ | 192 | */ |
196 | 193 | ||
197 | typedef struct _Unwind_Exception | ||
198 | { | ||
199 | uint64_t exclass; | ||
200 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
201 | uintptr_t p1, p2; | ||
202 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
203 | |||
204 | typedef struct _Unwind_Context _Unwind_Context; | 194 | typedef struct _Unwind_Context _Unwind_Context; |
205 | 195 | ||
206 | #define _URC_OK 0 | 196 | #define _URC_OK 0 |
@@ -210,8 +200,20 @@ typedef struct _Unwind_Context _Unwind_Context; | |||
210 | #define _URC_CONTINUE_UNWIND 8 | 200 | #define _URC_CONTINUE_UNWIND 8 |
211 | #define _URC_FAILURE 9 | 201 | #define _URC_FAILURE 9 |
212 | 202 | ||
203 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
204 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
205 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
206 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
207 | |||
213 | #if !LJ_TARGET_ARM | 208 | #if !LJ_TARGET_ARM |
214 | 209 | ||
210 | typedef struct _Unwind_Exception | ||
211 | { | ||
212 | uint64_t exclass; | ||
213 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
214 | uintptr_t p1, p2; | ||
215 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
216 | |||
215 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 217 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
216 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 218 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
217 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 219 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
@@ -223,11 +225,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *); | |||
223 | #define _UA_HANDLER_FRAME 4 | 225 | #define _UA_HANDLER_FRAME 4 |
224 | #define _UA_FORCE_UNWIND 8 | 226 | #define _UA_FORCE_UNWIND 8 |
225 | 227 | ||
226 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
227 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
228 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
229 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
230 | |||
231 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ | 228 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ |
232 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | 229 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, |
233 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | 230 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) |
@@ -306,10 +303,22 @@ static void err_raise_ext(int errcode) | |||
306 | } | 303 | } |
307 | #endif | 304 | #endif |
308 | 305 | ||
309 | #else | 306 | #else /* LJ_TARGET_ARM */ |
310 | 307 | ||
311 | extern void _Unwind_DeleteException(void *); | 308 | #define _US_VIRTUAL_UNWIND_FRAME 0 |
312 | extern int __gnu_unwind_frame (void *, _Unwind_Context *); | 309 | #define _US_UNWIND_FRAME_STARTING 1 |
310 | #define _US_ACTION_MASK 3 | ||
311 | #define _US_FORCE_UNWIND 8 | ||
312 | |||
313 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | ||
314 | |||
315 | struct _Unwind_Control_Block { | ||
316 | uint64_t exclass; | ||
317 | uint32_t misc[20]; | ||
318 | }; | ||
319 | |||
320 | extern int _Unwind_RaiseException(_Unwind_Control_Block *); | ||
321 | extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); | ||
313 | 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 *); |
314 | 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 *); |
315 | 324 | ||
@@ -325,35 +334,58 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |||
325 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); | 334 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); |
326 | } | 335 | } |
327 | 336 | ||
328 | #define _US_VIRTUAL_UNWIND_FRAME 0 | 337 | extern void lj_vm_unwind_ext(void); |
329 | #define _US_UNWIND_FRAME_STARTING 1 | ||
330 | #define _US_ACTION_MASK 3 | ||
331 | #define _US_FORCE_UNWIND 8 | ||
332 | 338 | ||
333 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | 339 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ |
334 | 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) | ||
335 | { | 342 | { |
336 | void *cf = (void *)_Unwind_GetGR(ctx, 13); | 343 | void *cf = (void *)_Unwind_GetGR(ctx, 13); |
337 | lua_State *L = cframe_L(cf); | 344 | lua_State *L = cframe_L(cf); |
338 | if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { | 345 | int errcode; |
339 | 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; | ||
340 | return _URC_HANDLER_FOUND; | 350 | return _URC_HANDLER_FOUND; |
341 | } | 351 | case _US_UNWIND_FRAME_STARTING: |
342 | if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { | 352 | if (LJ_UEXCLASS_CHECK(ucb->exclass)) { |
343 | _Unwind_DeleteException(ucb); | 353 | errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); |
344 | _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); | 354 | } else { |
345 | _Unwind_SetGR(ctx, 0, (uint32_t)L); | 355 | errcode = LUA_ERRRUN; |
346 | _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); | ||
347 | return _URC_INSTALL_CONTEXT; | 366 | return _URC_INSTALL_CONTEXT; |
367 | default: | ||
368 | return _URC_FAILURE; | ||
348 | } | 369 | } |
349 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 370 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
350 | return _URC_FAILURE; | 371 | return _URC_FAILURE; |
351 | return _URC_CONTINUE_UNWIND; | 372 | return _URC_CONTINUE_UNWIND; |
352 | } | 373 | } |
353 | 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 | } | ||
354 | #endif | 384 | #endif |
355 | 385 | ||
356 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 386 | #endif /* LJ_TARGET_ARM */ |
387 | |||
388 | #elif LJ_ABI_WIN | ||
357 | 389 | ||
358 | /* | 390 | /* |
359 | ** Someone in Redmond owes me several days of my life. A lot of this is | 391 | ** Someone in Redmond owes me several days of my life. A lot of this is |
@@ -371,6 +403,7 @@ LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | |||
371 | #define WIN32_LEAN_AND_MEAN | 403 | #define WIN32_LEAN_AND_MEAN |
372 | #include <windows.h> | 404 | #include <windows.h> |
373 | 405 | ||
406 | #if LJ_TARGET_X64 | ||
374 | /* Taken from: http://www.nynaeve.net/?p=99 */ | 407 | /* Taken from: http://www.nynaeve.net/?p=99 */ |
375 | typedef struct UndocumentedDispatcherContext { | 408 | typedef struct UndocumentedDispatcherContext { |
376 | ULONG64 ControlPc; | 409 | ULONG64 ControlPc; |
@@ -385,11 +418,14 @@ typedef struct UndocumentedDispatcherContext { | |||
385 | ULONG ScopeIndex; | 418 | ULONG ScopeIndex; |
386 | ULONG Fill0; | 419 | ULONG Fill0; |
387 | } UndocumentedDispatcherContext; | 420 | } UndocumentedDispatcherContext; |
421 | #else | ||
422 | typedef void *UndocumentedDispatcherContext; | ||
423 | #endif | ||
388 | 424 | ||
389 | /* Another wild guess. */ | 425 | /* Another wild guess. */ |
390 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); | 426 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); |
391 | 427 | ||
392 | #ifdef MINGW_SDK_INIT | 428 | #if LJ_TARGET_X64 && defined(MINGW_SDK_INIT) |
393 | /* Workaround for broken MinGW64 declaration. */ | 429 | /* Workaround for broken MinGW64 declaration. */ |
394 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | 430 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); |
395 | #define RtlUnwindEx RtlUnwindEx_FIXED | 431 | #define RtlUnwindEx RtlUnwindEx_FIXED |
@@ -403,10 +439,15 @@ VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | |||
403 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | 439 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) |
404 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) | 440 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) |
405 | 441 | ||
406 | /* Win64 exception handler for interpreter frame. */ | 442 | /* Windows exception handler for interpreter frame. */ |
407 | LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | 443 | LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, |
408 | void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) | 444 | void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) |
409 | { | 445 | { |
446 | #if LJ_TARGET_X64 | ||
447 | void *cf = f; | ||
448 | #else | ||
449 | void *cf = (char *)f - CFRAME_OFS_SEH; | ||
450 | #endif | ||
410 | lua_State *L = cframe_L(cf); | 451 | lua_State *L = cframe_L(cf); |
411 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? | 452 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? |
412 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; | 453 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; |
@@ -424,8 +465,9 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | |||
424 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 465 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
425 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { | 466 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { |
426 | /* Don't catch access violations etc. */ | 467 | /* Don't catch access violations etc. */ |
427 | return ExceptionContinueSearch; | 468 | return 1; /* ExceptionContinueSearch */ |
428 | } | 469 | } |
470 | #if LJ_TARGET_X64 | ||
429 | /* Unwind the stack and call all handlers for all lower C frames | 471 | /* Unwind the stack and call all handlers for all lower C frames |
430 | ** (including ourselves) again with EH_UNWINDING set. Then set | 472 | ** (including ourselves) again with EH_UNWINDING set. Then set |
431 | ** rsp = cf, rax = errcode and jump to the specified target. | 473 | ** rsp = cf, rax = errcode and jump to the specified target. |
@@ -435,9 +477,21 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | |||
435 | lj_vm_unwind_c_eh), | 477 | lj_vm_unwind_c_eh), |
436 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); | 478 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); |
437 | /* RtlUnwindEx should never return. */ | 479 | /* RtlUnwindEx should never return. */ |
480 | #else | ||
481 | UNUSED(ctx); | ||
482 | UNUSED(dispatch); | ||
483 | /* Call all handlers for all lower C frames (including ourselves) again | ||
484 | ** with EH_UNWINDING set. Then call the specified function, passing cf | ||
485 | ** and errcode. | ||
486 | */ | ||
487 | lj_vm_rtlunwind(cf, (void *)rec, | ||
488 | (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
489 | (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode); | ||
490 | /* lj_vm_rtlunwind does not return. */ | ||
491 | #endif | ||
438 | } | 492 | } |
439 | } | 493 | } |
440 | return ExceptionContinueSearch; | 494 | return 1; /* ExceptionContinueSearch */ |
441 | } | 495 | } |
442 | 496 | ||
443 | /* Raise Windows exception. */ | 497 | /* Raise Windows exception. */ |
@@ -455,8 +509,8 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) | |||
455 | { | 509 | { |
456 | global_State *g = G(L); | 510 | global_State *g = G(L); |
457 | lj_trace_abort(g); | 511 | lj_trace_abort(g); |
458 | setgcrefnull(g->jit_L); | 512 | setmref(g->jit_base, NULL); |
459 | L->status = 0; | 513 | L->status = LUA_OK; |
460 | #if LJ_UNWIND_EXT | 514 | #if LJ_UNWIND_EXT |
461 | err_raise_ext(errcode); | 515 | err_raise_ext(errcode); |
462 | /* | 516 | /* |
@@ -500,7 +554,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) | |||
500 | /* Find error function for runtime errors. Requires an extra stack traversal. */ | 554 | /* Find error function for runtime errors. Requires an extra stack traversal. */ |
501 | static ptrdiff_t finderrfunc(lua_State *L) | 555 | static ptrdiff_t finderrfunc(lua_State *L) |
502 | { | 556 | { |
503 | cTValue *frame = L->base-1, *bot = tvref(L->stack); | 557 | cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; |
504 | void *cf = L->cframe; | 558 | void *cf = L->cframe; |
505 | while (frame > bot && cf) { | 559 | while (frame > bot && cf) { |
506 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ | 560 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ |
@@ -524,10 +578,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
524 | frame = frame_prevd(frame); | 578 | frame = frame_prevd(frame); |
525 | break; | 579 | break; |
526 | case FRAME_CONT: | 580 | case FRAME_CONT: |
527 | #if LJ_HASFFI | 581 | if (frame_iscont_fficb(frame)) |
528 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
529 | cf = cframe_prev(cf); | 582 | cf = cframe_prev(cf); |
530 | #endif | ||
531 | frame = frame_prevd(frame); | 583 | frame = frame_prevd(frame); |
532 | break; | 584 | break; |
533 | case FRAME_CP: | 585 | case FRAME_CP: |
@@ -538,8 +590,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
538 | break; | 590 | break; |
539 | case FRAME_PCALL: | 591 | case FRAME_PCALL: |
540 | case FRAME_PCALLH: | 592 | case FRAME_PCALLH: |
541 | if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ | 593 | if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) |
542 | return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ | 594 | return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ |
543 | return 0; | 595 | return 0; |
544 | default: | 596 | default: |
545 | lua_assert(0); | 597 | lua_assert(0); |
@@ -562,8 +614,9 @@ LJ_NOINLINE void lj_err_run(lua_State *L) | |||
562 | lj_err_throw(L, LUA_ERRERR); | 614 | lj_err_throw(L, LUA_ERRERR); |
563 | } | 615 | } |
564 | L->status = LUA_ERRERR; | 616 | L->status = LUA_ERRERR; |
565 | copyTV(L, top, top-1); | 617 | copyTV(L, top+LJ_FR2, top-1); |
566 | copyTV(L, top-1, errfunc); | 618 | copyTV(L, top-1, errfunc); |
619 | if (LJ_FR2) setnilV(top++); | ||
567 | L->top = top+1; | 620 | L->top = top+1; |
568 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ | 621 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ |
569 | } | 622 | } |
@@ -577,7 +630,7 @@ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | |||
577 | va_list argp; | 630 | va_list argp; |
578 | va_start(argp, em); | 631 | va_start(argp, em); |
579 | if (curr_funcisL(L)) L->top = curr_topL(L); | 632 | if (curr_funcisL(L)) L->top = curr_topL(L); |
580 | msg = lj_str_pushvf(L, err2msg(em), argp); | 633 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
581 | va_end(argp); | 634 | va_end(argp); |
582 | lj_debug_addloc(L, msg, L->base-1, NULL); | 635 | lj_debug_addloc(L, msg, L->base-1, NULL); |
583 | lj_err_run(L); | 636 | lj_err_run(L); |
@@ -595,11 +648,11 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | |||
595 | { | 648 | { |
596 | char buff[LUA_IDSIZE]; | 649 | char buff[LUA_IDSIZE]; |
597 | const char *msg; | 650 | const char *msg; |
598 | lj_debug_shortname(buff, src); | 651 | lj_debug_shortname(buff, src, line); |
599 | msg = lj_str_pushvf(L, err2msg(em), argp); | 652 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
600 | msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); | 653 | msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg); |
601 | if (tok) | 654 | if (tok) |
602 | lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); | 655 | lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); |
603 | lj_err_throw(L, LUA_ERRSYNTAX); | 656 | lj_err_throw(L, LUA_ERRSYNTAX); |
604 | } | 657 | } |
605 | 658 | ||
@@ -638,8 +691,9 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
638 | const BCIns *pc = cframe_Lpc(L); | 691 | const BCIns *pc = cframe_Lpc(L); |
639 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { | 692 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { |
640 | const char *tname = lj_typename(o); | 693 | const char *tname = lj_typename(o); |
694 | if (LJ_FR2) o++; | ||
641 | setframe_pc(o, pc); | 695 | setframe_pc(o, pc); |
642 | setframe_gc(o, obj2gco(L)); | 696 | setframe_gc(o, obj2gco(L), LJ_TTHREAD); |
643 | L->top = L->base = o+1; | 697 | L->top = L->base = o+1; |
644 | err_msgv(L, LJ_ERR_BADCALL, tname); | 698 | err_msgv(L, LJ_ERR_BADCALL, tname); |
645 | } | 699 | } |
@@ -654,13 +708,10 @@ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) | |||
654 | if (frame_islua(frame)) { | 708 | if (frame_islua(frame)) { |
655 | pframe = frame_prevl(frame); | 709 | pframe = frame_prevl(frame); |
656 | } else if (frame_iscont(frame)) { | 710 | } else if (frame_iscont(frame)) { |
657 | #if LJ_HASFFI | 711 | if (frame_iscont_fficb(frame)) { |
658 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) { | ||
659 | pframe = frame; | 712 | pframe = frame; |
660 | frame = NULL; | 713 | frame = NULL; |
661 | } else | 714 | } else { |
662 | #endif | ||
663 | { | ||
664 | pframe = frame_prevd(frame); | 715 | pframe = frame_prevd(frame); |
665 | #if LJ_HASFFI | 716 | #if LJ_HASFFI |
666 | /* Remove frame for FFI metamethods. */ | 717 | /* Remove frame for FFI metamethods. */ |
@@ -683,7 +734,7 @@ LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...) | |||
683 | const char *msg; | 734 | const char *msg; |
684 | va_list argp; | 735 | va_list argp; |
685 | va_start(argp, em); | 736 | va_start(argp, em); |
686 | msg = lj_str_pushvf(L, err2msg(em), argp); | 737 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
687 | va_end(argp); | 738 | va_end(argp); |
688 | lj_err_callermsg(L, msg); | 739 | lj_err_callermsg(L, msg); |
689 | } | 740 | } |
@@ -703,9 +754,9 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg, | |||
703 | if (narg < 0 && narg > LUA_REGISTRYINDEX) | 754 | if (narg < 0 && narg > LUA_REGISTRYINDEX) |
704 | narg = (int)(L->top - L->base) + narg + 1; | 755 | narg = (int)(L->top - L->base) + narg + 1; |
705 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ | 756 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ |
706 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); | 757 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); |
707 | else | 758 | else |
708 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); | 759 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); |
709 | lj_err_callermsg(L, msg); | 760 | lj_err_callermsg(L, msg); |
710 | } | 761 | } |
711 | 762 | ||
@@ -715,7 +766,7 @@ LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...) | |||
715 | const char *msg; | 766 | const char *msg; |
716 | va_list argp; | 767 | va_list argp; |
717 | va_start(argp, em); | 768 | va_start(argp, em); |
718 | msg = lj_str_pushvf(L, err2msg(em), argp); | 769 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
719 | va_end(argp); | 770 | va_end(argp); |
720 | err_argmsg(L, narg, msg); | 771 | err_argmsg(L, narg, msg); |
721 | } | 772 | } |
@@ -745,7 +796,7 @@ LJ_NOINLINE void lj_err_argtype(lua_State *L, int narg, const char *xname) | |||
745 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; | 796 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; |
746 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; | 797 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; |
747 | } | 798 | } |
748 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); | 799 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); |
749 | err_argmsg(L, narg, msg); | 800 | err_argmsg(L, narg, msg); |
750 | } | 801 | } |
751 | 802 | ||
@@ -795,7 +846,7 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) | |||
795 | const char *msg; | 846 | const char *msg; |
796 | va_list argp; | 847 | va_list argp; |
797 | va_start(argp, fmt); | 848 | va_start(argp, fmt); |
798 | msg = lj_str_pushvf(L, fmt, argp); | 849 | msg = lj_strfmt_pushvf(L, fmt, argp); |
799 | va_end(argp); | 850 | va_end(argp); |
800 | lj_err_callermsg(L, msg); | 851 | lj_err_callermsg(L, msg); |
801 | return 0; /* unreachable */ | 852 | return 0; /* unreachable */ |