diff options
Diffstat (limited to 'src/lj_err.c')
-rw-r--r-- | src/lj_err.c | 692 |
1 files changed, 495 insertions, 197 deletions
diff --git a/src/lj_err.c b/src/lj_err.c index b677b655..563c7706 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: |
@@ -28,12 +29,18 @@ | |||
28 | ** Pros and Cons: | 29 | ** Pros and Cons: |
29 | ** | 30 | ** |
30 | ** - EXT requires unwind tables for *all* functions on the C stack between | 31 | ** - EXT requires unwind tables for *all* functions on the C stack between |
31 | ** the pcall/catch and the error/throw. This is the default on x64, | 32 | ** the pcall/catch and the error/throw. C modules used by Lua code can |
32 | ** but needs to be manually enabled on x86/PPC for non-C++ code. | 33 | ** throw errors, so these need to have unwind tables, too. Transitively |
34 | ** this applies to all system libraries used by C modules -- at least | ||
35 | ** when they have callbacks which may throw an error. | ||
33 | ** | 36 | ** |
34 | ** - INT is faster when actually throwing errors (but this happens rarely). | 37 | ** - INT is faster when actually throwing errors, but this happens rarely. |
35 | ** Setting up error handlers is zero-cost in any case. | 38 | ** Setting up error handlers is zero-cost in any case. |
36 | ** | 39 | ** |
40 | ** - INT needs to save *all* callee-saved registers when entering the | ||
41 | ** interpreter. EXT only needs to save those actually used inside the | ||
42 | ** interpreter. JIT-compiled code may need to save some more. | ||
43 | ** | ||
37 | ** - EXT provides full interoperability with C++ exceptions. You can throw | 44 | ** - EXT provides full interoperability with C++ exceptions. You can throw |
38 | ** Lua errors or C++ exceptions through a mix of Lua frames and C++ frames. | 45 | ** Lua errors or C++ exceptions through a mix of Lua frames and C++ frames. |
39 | ** C++ destructors are called as needed. C++ exceptions caught by pcall | 46 | ** C++ destructors are called as needed. C++ exceptions caught by pcall |
@@ -45,27 +52,38 @@ | |||
45 | ** the wrapper function feature. Lua errors thrown through C++ frames | 52 | ** the wrapper function feature. Lua errors thrown through C++ frames |
46 | ** cannot be caught by C++ code and C++ destructors are not run. | 53 | ** cannot be caught by C++ code and C++ destructors are not run. |
47 | ** | 54 | ** |
48 | ** EXT is the default on x64 systems, INT is the default on all other systems. | 55 | ** - EXT can handle errors from internal helper functions that are called |
56 | ** from JIT-compiled code (except for Windows/x86 and 32 bit ARM). | ||
57 | ** INT has no choice but to call the panic handler, if this happens. | ||
58 | ** Note: this is mainly relevant for out-of-memory errors. | ||
59 | ** | ||
60 | ** EXT is the default on all systems where the toolchain produces unwind | ||
61 | ** tables by default (*). This is hard-coded and/or detected in src/Makefile. | ||
62 | ** You can thwart the detection with: TARGET_XCFLAGS=-DLUAJIT_UNWIND_INTERNAL | ||
63 | ** | ||
64 | ** INT is the default on all other systems. | ||
65 | ** | ||
66 | ** EXT can be manually enabled for toolchains that are able to produce | ||
67 | ** conforming unwind tables: | ||
68 | ** "TARGET_XCFLAGS=-funwind-tables -DLUAJIT_UNWIND_EXTERNAL" | ||
69 | ** As explained above, *all* C code used directly or indirectly by LuaJIT | ||
70 | ** must be compiled with -funwind-tables (or -fexceptions). C++ code must | ||
71 | ** *not* be compiled with -fno-exceptions. | ||
72 | ** | ||
73 | ** If you're unsure whether error handling inside the VM works correctly, | ||
74 | ** try running this and check whether it prints "OK": | ||
49 | ** | 75 | ** |
50 | ** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack | 76 | ** luajit -e "print(select(2, load('OK')):match('OK'))" |
51 | ** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled | ||
52 | ** with -funwind-tables (or -fexceptions). This includes LuaJIT itself (set | ||
53 | ** TARGET_CFLAGS), all of your C/Lua binding code, all loadable C modules | ||
54 | ** 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. | ||
56 | ** | 77 | ** |
57 | ** EXT cannot be enabled on WIN32 since system exceptions use code-driven SEH. | 78 | ** (*) Originally, toolchains only generated unwind tables for C++ code. For |
58 | ** EXT is mandatory on WIN64 since the calling convention has an abundance | 79 | ** interoperability reasons, this can be manually enabled for plain C code, |
59 | ** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). | 80 | ** too (with -funwind-tables). With the introduction of the x64 architecture, |
60 | ** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4). | 81 | ** the corresponding POSIX and Windows ABIs mandated unwind tables for all |
82 | ** code. Over the following years most desktop and server platforms have | ||
83 | ** enabled unwind tables by default on all architectures. OTOH mobile and | ||
84 | ** embedded platforms do not consistently mandate unwind tables. | ||
61 | */ | 85 | */ |
62 | 86 | ||
63 | #if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND | ||
64 | #define LJ_UNWIND_EXT 1 | ||
65 | #elif LJ_TARGET_X64 && LJ_TARGET_WINDOWS | ||
66 | #define LJ_UNWIND_EXT 1 | ||
67 | #endif | ||
68 | |||
69 | /* -- Error messages ------------------------------------------------------ */ | 87 | /* -- Error messages ------------------------------------------------------ */ |
70 | 88 | ||
71 | /* Error message strings. */ | 89 | /* Error message strings. */ |
@@ -98,14 +116,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
98 | TValue *top = restorestack(L, -nres); | 116 | TValue *top = restorestack(L, -nres); |
99 | if (frame < top) { /* Frame reached? */ | 117 | if (frame < top) { /* Frame reached? */ |
100 | if (errcode) { | 118 | if (errcode) { |
101 | L->cframe = cframe_prev(cf); | ||
102 | L->base = frame+1; | 119 | L->base = frame+1; |
120 | L->cframe = cframe_prev(cf); | ||
103 | unwindstack(L, top); | 121 | unwindstack(L, top); |
104 | } | 122 | } |
105 | return cf; | 123 | return cf; |
106 | } | 124 | } |
107 | } | 125 | } |
108 | if (frame <= tvref(L->stack)) | 126 | if (frame <= tvref(L->stack)+LJ_FR2) |
109 | break; | 127 | break; |
110 | switch (frame_typep(frame)) { | 128 | switch (frame_typep(frame)) { |
111 | case FRAME_LUA: /* Lua frame. */ | 129 | case FRAME_LUA: /* Lua frame. */ |
@@ -113,14 +131,12 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
113 | frame = frame_prevl(frame); | 131 | frame = frame_prevl(frame); |
114 | break; | 132 | break; |
115 | case FRAME_C: /* C frame. */ | 133 | case FRAME_C: /* C frame. */ |
116 | #if LJ_HASFFI | ||
117 | unwind_c: | 134 | unwind_c: |
118 | #endif | ||
119 | #if LJ_UNWIND_EXT | 135 | #if LJ_UNWIND_EXT |
120 | if (errcode) { | 136 | if (errcode) { |
121 | L->cframe = cframe_prev(cf); | ||
122 | L->base = frame_prevd(frame) + 1; | 137 | L->base = frame_prevd(frame) + 1; |
123 | unwindstack(L, frame); | 138 | L->cframe = cframe_prev(cf); |
139 | unwindstack(L, frame - LJ_FR2); | ||
124 | } else if (cf != stopcf) { | 140 | } else if (cf != stopcf) { |
125 | cf = cframe_prev(cf); | 141 | cf = cframe_prev(cf); |
126 | frame = frame_prevd(frame); | 142 | frame = frame_prevd(frame); |
@@ -143,16 +159,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
143 | return cf; | 159 | return cf; |
144 | } | 160 | } |
145 | if (errcode) { | 161 | if (errcode) { |
146 | L->cframe = cframe_prev(cf); | ||
147 | L->base = frame_prevd(frame) + 1; | 162 | L->base = frame_prevd(frame) + 1; |
148 | unwindstack(L, frame); | 163 | L->cframe = cframe_prev(cf); |
164 | unwindstack(L, frame - LJ_FR2); | ||
149 | } | 165 | } |
150 | return cf; | 166 | return cf; |
151 | case FRAME_CONT: /* Continuation frame. */ | 167 | case FRAME_CONT: /* Continuation frame. */ |
152 | #if LJ_HASFFI | 168 | if (frame_iscont_fficb(frame)) |
153 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
154 | goto unwind_c; | 169 | goto unwind_c; |
155 | #endif | ||
156 | /* fallthrough */ | 170 | /* fallthrough */ |
157 | case FRAME_VARG: /* Vararg frame. */ | 171 | case FRAME_VARG: /* Vararg frame. */ |
158 | frame = frame_prevd(frame); | 172 | frame = frame_prevd(frame); |
@@ -166,8 +180,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
166 | } | 180 | } |
167 | if (frame_typep(frame) == FRAME_PCALL) | 181 | if (frame_typep(frame) == FRAME_PCALL) |
168 | hook_leave(G(L)); | 182 | hook_leave(G(L)); |
169 | L->cframe = cf; | ||
170 | L->base = frame_prevd(frame) + 1; | 183 | L->base = frame_prevd(frame) + 1; |
184 | L->cframe = cf; | ||
171 | unwindstack(L, L->base); | 185 | unwindstack(L, L->base); |
172 | } | 186 | } |
173 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); | 187 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); |
@@ -175,8 +189,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
175 | } | 189 | } |
176 | /* No C frame. */ | 190 | /* No C frame. */ |
177 | if (errcode) { | 191 | if (errcode) { |
192 | L->base = tvref(L->stack)+1+LJ_FR2; | ||
178 | L->cframe = NULL; | 193 | L->cframe = NULL; |
179 | L->base = tvref(L->stack)+1; | ||
180 | unwindstack(L, L->base); | 194 | unwindstack(L, L->base); |
181 | if (G(L)->panic) | 195 | if (G(L)->panic) |
182 | G(L)->panic(L); | 196 | G(L)->panic(L); |
@@ -187,33 +201,206 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
187 | 201 | ||
188 | /* -- External frame unwinding -------------------------------------------- */ | 202 | /* -- External frame unwinding -------------------------------------------- */ |
189 | 203 | ||
190 | #if defined(__GNUC__) && !LJ_NO_UNWIND && !LJ_ABI_WIN | 204 | #if LJ_ABI_WIN |
191 | 205 | ||
192 | /* | 206 | /* |
193 | ** We have to use our own definitions instead of the mandatory (!) unwind.h, | 207 | ** Someone in Redmond owes me several days of my life. A lot of this is |
194 | ** since various OS, distros and compilers mess up the header installation. | 208 | ** undocumented or just plain wrong on MSDN. Some of it can be gathered |
209 | ** from 3rd party docs or must be found by trial-and-error. They really | ||
210 | ** don't want you to write your own language-specific exception handler | ||
211 | ** or to interact gracefully with MSVC. :-( | ||
212 | ** | ||
213 | ** Apparently MSVC doesn't call C++ destructors for foreign exceptions | ||
214 | ** unless you compile your C++ code with /EHa. Unfortunately this means | ||
215 | ** catch (...) also catches things like access violations. The use of | ||
216 | ** _set_se_translator doesn't really help, because it requires /EHa, too. | ||
195 | */ | 217 | */ |
196 | 218 | ||
197 | typedef struct _Unwind_Exception | 219 | #define WIN32_LEAN_AND_MEAN |
220 | #include <windows.h> | ||
221 | |||
222 | #if LJ_TARGET_X86 | ||
223 | typedef void *UndocumentedDispatcherContext; /* Unused on x86. */ | ||
224 | #else | ||
225 | /* Taken from: http://www.nynaeve.net/?p=99 */ | ||
226 | typedef struct UndocumentedDispatcherContext { | ||
227 | ULONG64 ControlPc; | ||
228 | ULONG64 ImageBase; | ||
229 | PRUNTIME_FUNCTION FunctionEntry; | ||
230 | ULONG64 EstablisherFrame; | ||
231 | ULONG64 TargetIp; | ||
232 | PCONTEXT ContextRecord; | ||
233 | void (*LanguageHandler)(void); | ||
234 | PVOID HandlerData; | ||
235 | PUNWIND_HISTORY_TABLE HistoryTable; | ||
236 | ULONG ScopeIndex; | ||
237 | ULONG Fill0; | ||
238 | } UndocumentedDispatcherContext; | ||
239 | #endif | ||
240 | |||
241 | /* Another wild guess. */ | ||
242 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); | ||
243 | |||
244 | #if LJ_TARGET_X64 && defined(MINGW_SDK_INIT) | ||
245 | /* Workaround for broken MinGW64 declaration. */ | ||
246 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | ||
247 | #define RtlUnwindEx RtlUnwindEx_FIXED | ||
248 | #endif | ||
249 | |||
250 | #define LJ_MSVC_EXCODE ((DWORD)0xe06d7363) | ||
251 | #define LJ_GCC_EXCODE ((DWORD)0x20474343) | ||
252 | |||
253 | #define LJ_EXCODE ((DWORD)0xe24c4a00) | ||
254 | #define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) | ||
255 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | ||
256 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
257 | |||
258 | /* Windows exception handler for interpreter frame. */ | ||
259 | LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, | ||
260 | void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) | ||
198 | { | 261 | { |
199 | uint64_t exclass; | 262 | #if LJ_TARGET_X86 |
200 | void (*excleanup)(int, struct _Unwind_Exception *); | 263 | void *cf = (char *)f - CFRAME_OFS_SEH; |
201 | uintptr_t p1, p2; | 264 | #else |
202 | } __attribute__((__aligned__)) _Unwind_Exception; | 265 | void *cf = f; |
266 | #endif | ||
267 | lua_State *L = cframe_L(cf); | ||
268 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? | ||
269 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; | ||
270 | if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */ | ||
271 | /* Unwind internal frames. */ | ||
272 | err_unwind(L, cf, errcode); | ||
273 | } else { | ||
274 | void *cf2 = err_unwind(L, cf, 0); | ||
275 | if (cf2) { /* We catch it, so start unwinding the upper frames. */ | ||
276 | if (rec->ExceptionCode == LJ_MSVC_EXCODE || | ||
277 | rec->ExceptionCode == LJ_GCC_EXCODE) { | ||
278 | #if !LJ_TARGET_CYGWIN | ||
279 | __DestructExceptionObject(rec, 1); | ||
280 | #endif | ||
281 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | ||
282 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { | ||
283 | /* Don't catch access violations etc. */ | ||
284 | return 1; /* ExceptionContinueSearch */ | ||
285 | } | ||
286 | #if LJ_TARGET_X86 | ||
287 | UNUSED(ctx); | ||
288 | UNUSED(dispatch); | ||
289 | /* Call all handlers for all lower C frames (including ourselves) again | ||
290 | ** with EH_UNWINDING set. Then call the specified function, passing cf | ||
291 | ** and errcode. | ||
292 | */ | ||
293 | lj_vm_rtlunwind(cf, (void *)rec, | ||
294 | (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
295 | (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode); | ||
296 | /* lj_vm_rtlunwind does not return. */ | ||
297 | #else | ||
298 | /* Unwind the stack and call all handlers for all lower C frames | ||
299 | ** (including ourselves) again with EH_UNWINDING set. Then set | ||
300 | ** stack pointer = cf, result = errcode and jump to the specified target. | ||
301 | */ | ||
302 | RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
303 | lj_vm_unwind_ff_eh : | ||
304 | lj_vm_unwind_c_eh), | ||
305 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); | ||
306 | /* RtlUnwindEx should never return. */ | ||
307 | #endif | ||
308 | } | ||
309 | } | ||
310 | return 1; /* ExceptionContinueSearch */ | ||
311 | } | ||
312 | |||
313 | #if LJ_UNWIND_JIT | ||
314 | |||
315 | #if LJ_TARGET_X64 | ||
316 | #define CONTEXT_REG_PC Rip | ||
317 | #elif LJ_TARGET_ARM64 | ||
318 | #define CONTEXT_REG_PC Pc | ||
319 | #else | ||
320 | #error "NYI: Windows arch-specific unwinder for JIT-compiled code" | ||
321 | #endif | ||
322 | |||
323 | /* Windows unwinder for JIT-compiled code. */ | ||
324 | static void err_unwind_win_jit(global_State *g, int errcode) | ||
325 | { | ||
326 | CONTEXT ctx; | ||
327 | UNWIND_HISTORY_TABLE hist; | ||
328 | |||
329 | memset(&hist, 0, sizeof(hist)); | ||
330 | RtlCaptureContext(&ctx); | ||
331 | while (1) { | ||
332 | uintptr_t frame, base, addr = ctx.CONTEXT_REG_PC; | ||
333 | void *hdata; | ||
334 | PRUNTIME_FUNCTION func = RtlLookupFunctionEntry(addr, &base, &hist); | ||
335 | if (!func) { /* Found frame without .pdata: must be JIT-compiled code. */ | ||
336 | ExitNo exitno; | ||
337 | uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno); | ||
338 | if (stub) { /* Jump to side exit to unwind the trace. */ | ||
339 | ctx.CONTEXT_REG_PC = stub; | ||
340 | G2J(g)->exitcode = errcode; | ||
341 | RtlRestoreContext(&ctx, NULL); /* Does not return. */ | ||
342 | } | ||
343 | break; | ||
344 | } | ||
345 | RtlVirtualUnwind(UNW_FLAG_NHANDLER, base, addr, func, | ||
346 | &ctx, &hdata, &frame, NULL); | ||
347 | if (!addr) break; | ||
348 | } | ||
349 | /* Unwinding failed, if we end up here. */ | ||
350 | } | ||
351 | #endif | ||
352 | |||
353 | /* Raise Windows exception. */ | ||
354 | static void err_raise_ext(global_State *g, int errcode) | ||
355 | { | ||
356 | #if LJ_UNWIND_JIT | ||
357 | if (tvref(g->jit_base)) { | ||
358 | err_unwind_win_jit(g, errcode); | ||
359 | return; /* Unwinding failed. */ | ||
360 | } | ||
361 | #elif LJ_HASJIT | ||
362 | /* Cannot catch on-trace errors for Windows/x86 SEH. Unwind to interpreter. */ | ||
363 | setmref(g->jit_base, NULL); | ||
364 | #endif | ||
365 | UNUSED(g); | ||
366 | RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); | ||
367 | } | ||
368 | |||
369 | #elif !LJ_NO_UNWIND && (defined(__GNUC__) || defined(__clang__)) | ||
370 | |||
371 | /* | ||
372 | ** We have to use our own definitions instead of the mandatory (!) unwind.h, | ||
373 | ** since various OS, distros and compilers mess up the header installation. | ||
374 | */ | ||
203 | 375 | ||
204 | typedef struct _Unwind_Context _Unwind_Context; | 376 | typedef struct _Unwind_Context _Unwind_Context; |
205 | 377 | ||
206 | #define _URC_OK 0 | 378 | #define _URC_OK 0 |
379 | #define _URC_FATAL_PHASE2_ERROR 2 | ||
207 | #define _URC_FATAL_PHASE1_ERROR 3 | 380 | #define _URC_FATAL_PHASE1_ERROR 3 |
208 | #define _URC_HANDLER_FOUND 6 | 381 | #define _URC_HANDLER_FOUND 6 |
209 | #define _URC_INSTALL_CONTEXT 7 | 382 | #define _URC_INSTALL_CONTEXT 7 |
210 | #define _URC_CONTINUE_UNWIND 8 | 383 | #define _URC_CONTINUE_UNWIND 8 |
211 | #define _URC_FAILURE 9 | 384 | #define _URC_FAILURE 9 |
212 | 385 | ||
386 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
387 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
388 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
389 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
390 | |||
213 | #if !LJ_TARGET_ARM | 391 | #if !LJ_TARGET_ARM |
214 | 392 | ||
393 | typedef struct _Unwind_Exception | ||
394 | { | ||
395 | uint64_t exclass; | ||
396 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
397 | uintptr_t p1, p2; | ||
398 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
399 | #define UNWIND_EXCEPTION_TYPE _Unwind_Exception | ||
400 | |||
215 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 401 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
216 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 402 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
403 | extern uintptr_t _Unwind_GetIP(_Unwind_Context *); | ||
217 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 404 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
218 | extern void _Unwind_DeleteException(_Unwind_Exception *); | 405 | extern void _Unwind_DeleteException(_Unwind_Exception *); |
219 | extern int _Unwind_RaiseException(_Unwind_Exception *); | 406 | extern int _Unwind_RaiseException(_Unwind_Exception *); |
@@ -223,11 +410,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *); | |||
223 | #define _UA_HANDLER_FRAME 4 | 410 | #define _UA_HANDLER_FRAME 4 |
224 | #define _UA_FORCE_UNWIND 8 | 411 | #define _UA_FORCE_UNWIND 8 |
225 | 412 | ||
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. */ | 413 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ |
232 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | 414 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, |
233 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | 415 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) |
@@ -236,7 +418,6 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | |||
236 | lua_State *L; | 418 | lua_State *L; |
237 | if (version != 1) | 419 | if (version != 1) |
238 | return _URC_FATAL_PHASE1_ERROR; | 420 | return _URC_FATAL_PHASE1_ERROR; |
239 | UNUSED(uexclass); | ||
240 | cf = (void *)_Unwind_GetCFA(ctx); | 421 | cf = (void *)_Unwind_GetCFA(ctx); |
241 | L = cframe_L(cf); | 422 | L = cframe_L(cf); |
242 | if ((actions & _UA_SEARCH_PHASE)) { | 423 | if ((actions & _UA_SEARCH_PHASE)) { |
@@ -284,27 +465,162 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | |||
284 | ** it on non-x64 because the interpreter restores all callee-saved regs. | 465 | ** it on non-x64 because the interpreter restores all callee-saved regs. |
285 | */ | 466 | */ |
286 | lj_err_throw(L, errcode); | 467 | lj_err_throw(L, errcode); |
468 | #if LJ_TARGET_X64 | ||
469 | #error "Broken build system -- only use the provided Makefiles!" | ||
470 | #endif | ||
287 | #endif | 471 | #endif |
288 | } | 472 | } |
289 | return _URC_CONTINUE_UNWIND; | 473 | return _URC_CONTINUE_UNWIND; |
290 | } | 474 | } |
291 | 475 | ||
292 | #if LJ_UNWIND_EXT | 476 | #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) |
293 | static __thread _Unwind_Exception static_uex; | 477 | struct dwarf_eh_bases { void *tbase, *dbase, *func; }; |
478 | extern const void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases); | ||
294 | 479 | ||
295 | /* Raise DWARF2 exception. */ | 480 | /* Verify that external error handling actually has a chance to work. */ |
296 | static void err_raise_ext(int errcode) | 481 | void lj_err_verify(void) |
297 | { | 482 | { |
298 | static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); | 483 | #if !LJ_TARGET_OSX |
299 | static_uex.excleanup = NULL; | 484 | /* Check disabled on MacOS due to brilliant software engineering at Apple. */ |
300 | _Unwind_RaiseException(&static_uex); | 485 | struct dwarf_eh_bases ehb; |
486 | lj_assertX(_Unwind_Find_FDE((void *)lj_err_throw, &ehb), "broken build: external frame unwinding enabled, but missing -funwind-tables"); | ||
487 | #endif | ||
488 | /* Check disabled, because of broken Fedora/ARM64. See #722. | ||
489 | lj_assertX(_Unwind_Find_FDE((void *)_Unwind_RaiseException, &ehb), "broken build: external frame unwinding enabled, but system libraries have no unwind tables"); | ||
490 | */ | ||
301 | } | 491 | } |
302 | #endif | 492 | #endif |
303 | 493 | ||
494 | #if LJ_UNWIND_JIT | ||
495 | /* DWARF2 personality handler for JIT-compiled code. */ | ||
496 | static int err_unwind_jit(int version, int actions, | ||
497 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | ||
498 | { | ||
499 | /* NYI: FFI C++ exception interoperability. */ | ||
500 | if (version != 1 || !LJ_UEXCLASS_CHECK(uexclass)) | ||
501 | return _URC_FATAL_PHASE1_ERROR; | ||
502 | if ((actions & _UA_SEARCH_PHASE)) { | ||
503 | return _URC_HANDLER_FOUND; | ||
504 | } | ||
505 | if ((actions & _UA_CLEANUP_PHASE)) { | ||
506 | global_State *g = *(global_State **)(uex+1); | ||
507 | ExitNo exitno; | ||
508 | uintptr_t addr = _Unwind_GetIP(ctx); /* Return address _after_ call. */ | ||
509 | uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno); | ||
510 | lj_assertG(tvref(g->jit_base), "unexpected throw across mcode frame"); | ||
511 | if (stub) { /* Jump to side exit to unwind the trace. */ | ||
512 | G2J(g)->exitcode = LJ_UEXCLASS_ERRCODE(uexclass); | ||
513 | #ifdef LJ_TARGET_MIPS | ||
514 | _Unwind_SetGR(ctx, 4, stub); | ||
515 | _Unwind_SetGR(ctx, 5, exitno); | ||
516 | _Unwind_SetIP(ctx, (uintptr_t)(void *)lj_vm_unwind_stub); | ||
517 | #else | ||
518 | _Unwind_SetIP(ctx, stub); | ||
519 | #endif | ||
520 | return _URC_INSTALL_CONTEXT; | ||
521 | } | ||
522 | return _URC_FATAL_PHASE2_ERROR; | ||
523 | } | ||
524 | return _URC_FATAL_PHASE1_ERROR; | ||
525 | } | ||
526 | |||
527 | /* DWARF2 template frame info for JIT-compiled code. | ||
528 | ** | ||
529 | ** After copying the template to the start of the mcode segment, | ||
530 | ** the frame handler function and the code size is patched. | ||
531 | ** The frame handler always installs a new context to jump to the exit, | ||
532 | ** so don't bother to add any unwind opcodes. | ||
533 | */ | ||
534 | static const uint8_t err_frame_jit_template[] = { | ||
535 | #if LJ_BE | ||
536 | 0,0,0, | ||
537 | #endif | ||
538 | LJ_64 ? 0x1c : 0x14, /* CIE length. */ | ||
539 | #if LJ_LE | ||
540 | 0,0,0, | ||
541 | #endif | ||
542 | 0,0,0,0, 1, 'z','P','R',0, /* CIE mark, CIE version, augmentation. */ | ||
543 | 1, LJ_64 ? 0x78 : 0x7c, LJ_TARGET_EHRAREG, /* Code/data align, RA. */ | ||
544 | #if LJ_64 | ||
545 | 10, 0, 0,0,0,0,0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ | ||
546 | 0,0,0,0,0, /* Alignment. */ | ||
547 | #else | ||
548 | 6, 0, 0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ | ||
549 | 0, /* Alignment. */ | ||
550 | #endif | ||
551 | #if LJ_BE | ||
552 | 0,0,0, | ||
553 | #endif | ||
554 | LJ_64 ? 0x14 : 0x10, /* FDE length. */ | ||
555 | 0,0,0, | ||
556 | LJ_64 ? 0x24 : 0x1c, /* CIE offset. */ | ||
557 | 0,0,0, | ||
558 | LJ_64 ? 0x14 : 0x10, /* Code offset. After Final FDE. */ | ||
559 | #if LJ_LE | ||
560 | 0,0,0, | ||
561 | #endif | ||
562 | 0,0,0,0, 0, 0,0,0, /* Code size, augmentation length, alignment. */ | ||
563 | #if LJ_64 | ||
564 | 0,0,0,0, /* Alignment. */ | ||
565 | #endif | ||
566 | 0,0,0,0 /* Final FDE. */ | ||
567 | }; | ||
568 | |||
569 | #define ERR_FRAME_JIT_OFS_HANDLER 0x12 | ||
570 | #define ERR_FRAME_JIT_OFS_FDE (LJ_64 ? 0x20 : 0x18) | ||
571 | #define ERR_FRAME_JIT_OFS_CODE_SIZE (LJ_64 ? 0x2c : 0x24) | ||
572 | #if LJ_TARGET_OSX | ||
573 | #define ERR_FRAME_JIT_OFS_REGISTER ERR_FRAME_JIT_OFS_FDE | ||
304 | #else | 574 | #else |
575 | #define ERR_FRAME_JIT_OFS_REGISTER 0 | ||
576 | #endif | ||
577 | |||
578 | extern void __register_frame(const void *); | ||
579 | extern void __deregister_frame(const void *); | ||
580 | |||
581 | uint8_t *lj_err_register_mcode(void *base, size_t sz, uint8_t *info) | ||
582 | { | ||
583 | void **handler; | ||
584 | memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template)); | ||
585 | handler = (void *)err_unwind_jit; | ||
586 | memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler)); | ||
587 | *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) = | ||
588 | (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base)); | ||
589 | __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | ||
590 | #ifdef LUA_USE_ASSERT | ||
591 | { | ||
592 | struct dwarf_eh_bases ehb; | ||
593 | lj_assertX(_Unwind_Find_FDE(info + sizeof(err_frame_jit_template)+1, &ehb), | ||
594 | "bad JIT unwind table registration"); | ||
595 | } | ||
596 | #endif | ||
597 | return info + sizeof(err_frame_jit_template); | ||
598 | } | ||
599 | |||
600 | void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info) | ||
601 | { | ||
602 | UNUSED(base); UNUSED(sz); | ||
603 | __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | ||
604 | } | ||
605 | #endif | ||
606 | |||
607 | #else /* LJ_TARGET_ARM */ | ||
608 | |||
609 | #define _US_VIRTUAL_UNWIND_FRAME 0 | ||
610 | #define _US_UNWIND_FRAME_STARTING 1 | ||
611 | #define _US_ACTION_MASK 3 | ||
612 | #define _US_FORCE_UNWIND 8 | ||
613 | |||
614 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | ||
615 | #define UNWIND_EXCEPTION_TYPE _Unwind_Control_Block | ||
616 | |||
617 | struct _Unwind_Control_Block { | ||
618 | uint64_t exclass; | ||
619 | uint32_t misc[20]; | ||
620 | }; | ||
305 | 621 | ||
306 | extern void _Unwind_DeleteException(void *); | 622 | extern int _Unwind_RaiseException(_Unwind_Control_Block *); |
307 | extern int __gnu_unwind_frame (void *, _Unwind_Context *); | 623 | extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); |
308 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); | 624 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); |
309 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); | 625 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); |
310 | 626 | ||
@@ -320,126 +636,98 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |||
320 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); | 636 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); |
321 | } | 637 | } |
322 | 638 | ||
323 | #define _US_VIRTUAL_UNWIND_FRAME 0 | 639 | extern void lj_vm_unwind_ext(void); |
324 | #define _US_UNWIND_FRAME_STARTING 1 | ||
325 | #define _US_ACTION_MASK 3 | ||
326 | #define _US_FORCE_UNWIND 8 | ||
327 | 640 | ||
328 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | 641 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ |
329 | LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | 642 | LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, |
643 | _Unwind_Context *ctx) | ||
330 | { | 644 | { |
331 | void *cf = (void *)_Unwind_GetGR(ctx, 13); | 645 | void *cf = (void *)_Unwind_GetGR(ctx, 13); |
332 | lua_State *L = cframe_L(cf); | 646 | lua_State *L = cframe_L(cf); |
333 | if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { | 647 | int errcode; |
334 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 648 | |
649 | switch ((state & _US_ACTION_MASK)) { | ||
650 | case _US_VIRTUAL_UNWIND_FRAME: | ||
651 | if ((state & _US_FORCE_UNWIND)) break; | ||
335 | return _URC_HANDLER_FOUND; | 652 | return _URC_HANDLER_FOUND; |
336 | } | 653 | case _US_UNWIND_FRAME_STARTING: |
337 | if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { | 654 | if (LJ_UEXCLASS_CHECK(ucb->exclass)) { |
338 | _Unwind_DeleteException(ucb); | 655 | errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); |
339 | _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); | 656 | } else { |
340 | _Unwind_SetGR(ctx, 0, (uint32_t)L); | 657 | errcode = LUA_ERRRUN; |
341 | _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN); | 658 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
659 | } | ||
660 | cf = err_unwind(L, cf, errcode); | ||
661 | if ((state & _US_FORCE_UNWIND) || cf == NULL) break; | ||
662 | _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); | ||
663 | _Unwind_SetGR(ctx, 0, (uint32_t)ucb); | ||
664 | _Unwind_SetGR(ctx, 1, (uint32_t)errcode); | ||
665 | _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? | ||
666 | (uint32_t)lj_vm_unwind_ff_eh : | ||
667 | (uint32_t)lj_vm_unwind_c_eh); | ||
342 | return _URC_INSTALL_CONTEXT; | 668 | return _URC_INSTALL_CONTEXT; |
669 | default: | ||
670 | return _URC_FAILURE; | ||
343 | } | 671 | } |
344 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 672 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
345 | return _URC_FAILURE; | 673 | return _URC_FAILURE; |
674 | #ifdef LUA_USE_ASSERT | ||
675 | /* We should never get here unless this is a forced unwind aka backtrace. */ | ||
676 | if (_Unwind_GetGR(ctx, 0) == 0xff33aa77) { | ||
677 | _Unwind_SetGR(ctx, 0, 0xff33aa88); | ||
678 | } | ||
679 | #endif | ||
346 | return _URC_CONTINUE_UNWIND; | 680 | return _URC_CONTINUE_UNWIND; |
347 | } | 681 | } |
348 | 682 | ||
349 | #endif | 683 | #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) |
684 | typedef int (*_Unwind_Trace_Fn)(_Unwind_Context *, void *); | ||
685 | extern int _Unwind_Backtrace(_Unwind_Trace_Fn, void *); | ||
686 | |||
687 | static int err_verify_bt(_Unwind_Context *ctx, int *got) | ||
688 | { | ||
689 | if (_Unwind_GetGR(ctx, 0) == 0xff33aa88) { *got = 2; } | ||
690 | else if (*got == 0) { *got = 1; _Unwind_SetGR(ctx, 0, 0xff33aa77); } | ||
691 | return _URC_OK; | ||
692 | } | ||
350 | 693 | ||
351 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 694 | /* Verify that external error handling actually has a chance to work. */ |
695 | void lj_err_verify(void) | ||
696 | { | ||
697 | int got = 0; | ||
698 | _Unwind_Backtrace((_Unwind_Trace_Fn)err_verify_bt, &got); | ||
699 | lj_assertX(got == 2, "broken build: external frame unwinding enabled, but missing -funwind-tables"); | ||
700 | } | ||
701 | #endif | ||
352 | 702 | ||
353 | /* | 703 | /* |
354 | ** Someone in Redmond owes me several days of my life. A lot of this is | 704 | ** Note: LJ_UNWIND_JIT is not implemented for 32 bit ARM. |
355 | ** undocumented or just plain wrong on MSDN. Some of it can be gathered | ||
356 | ** from 3rd party docs or must be found by trial-and-error. They really | ||
357 | ** don't want you to write your own language-specific exception handler | ||
358 | ** or to interact gracefully with MSVC. :-( | ||
359 | ** | 705 | ** |
360 | ** Apparently MSVC doesn't call C++ destructors for foreign exceptions | 706 | ** The quirky ARM unwind API doesn't have __register_frame(). |
361 | ** unless you compile your C++ code with /EHa. Unfortunately this means | 707 | ** A potential workaround might involve _Unwind_Backtrace. |
362 | ** catch (...) also catches things like access violations. The use of | 708 | ** But most 32 bit ARM targets don't qualify for LJ_UNWIND_EXT, anyway, |
363 | ** _set_se_translator doesn't really help, because it requires /EHa, too. | 709 | ** since they are built without unwind tables by default. |
364 | */ | 710 | */ |
365 | 711 | ||
366 | #define WIN32_LEAN_AND_MEAN | 712 | #endif /* LJ_TARGET_ARM */ |
367 | #include <windows.h> | ||
368 | 713 | ||
369 | /* Taken from: http://www.nynaeve.net/?p=99 */ | ||
370 | typedef struct UndocumentedDispatcherContext { | ||
371 | ULONG64 ControlPc; | ||
372 | ULONG64 ImageBase; | ||
373 | PRUNTIME_FUNCTION FunctionEntry; | ||
374 | ULONG64 EstablisherFrame; | ||
375 | ULONG64 TargetIp; | ||
376 | PCONTEXT ContextRecord; | ||
377 | void (*LanguageHandler)(void); | ||
378 | PVOID HandlerData; | ||
379 | PUNWIND_HISTORY_TABLE HistoryTable; | ||
380 | ULONG ScopeIndex; | ||
381 | ULONG Fill0; | ||
382 | } UndocumentedDispatcherContext; | ||
383 | |||
384 | /* Another wild guess. */ | ||
385 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); | ||
386 | |||
387 | #ifdef MINGW_SDK_INIT | ||
388 | /* Workaround for broken MinGW64 declaration. */ | ||
389 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | ||
390 | #define RtlUnwindEx RtlUnwindEx_FIXED | ||
391 | #endif | ||
392 | |||
393 | #define LJ_MSVC_EXCODE ((DWORD)0xe06d7363) | ||
394 | #define LJ_GCC_EXCODE ((DWORD)0x20474343) | ||
395 | 714 | ||
396 | #define LJ_EXCODE ((DWORD)0xe24c4a00) | 715 | #if LJ_UNWIND_EXT |
397 | #define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) | 716 | static __thread struct { |
398 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | 717 | UNWIND_EXCEPTION_TYPE ex; |
399 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) | 718 | global_State *g; |
719 | } static_uex; | ||
400 | 720 | ||
401 | /* Win64 exception handler for interpreter frame. */ | 721 | /* Raise external exception. */ |
402 | LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | 722 | static void err_raise_ext(global_State *g, int errcode) |
403 | void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) | ||
404 | { | 723 | { |
405 | lua_State *L = cframe_L(cf); | 724 | memset(&static_uex, 0, sizeof(static_uex)); |
406 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? | 725 | static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode); |
407 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; | 726 | static_uex.g = g; |
408 | if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */ | 727 | _Unwind_RaiseException(&static_uex.ex); |
409 | /* Unwind internal frames. */ | ||
410 | err_unwind(L, cf, errcode); | ||
411 | } else { | ||
412 | void *cf2 = err_unwind(L, cf, 0); | ||
413 | if (cf2) { /* We catch it, so start unwinding the upper frames. */ | ||
414 | if (rec->ExceptionCode == LJ_MSVC_EXCODE || | ||
415 | rec->ExceptionCode == LJ_GCC_EXCODE) { | ||
416 | #if LJ_TARGET_WINDOWS | ||
417 | __DestructExceptionObject(rec, 1); | ||
418 | #endif | ||
419 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | ||
420 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { | ||
421 | /* Don't catch access violations etc. */ | ||
422 | return ExceptionContinueSearch; | ||
423 | } | ||
424 | /* Unwind the stack and call all handlers for all lower C frames | ||
425 | ** (including ourselves) again with EH_UNWINDING set. Then set | ||
426 | ** rsp = cf, rax = errcode and jump to the specified target. | ||
427 | */ | ||
428 | RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
429 | lj_vm_unwind_ff_eh : | ||
430 | lj_vm_unwind_c_eh), | ||
431 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); | ||
432 | /* RtlUnwindEx should never return. */ | ||
433 | } | ||
434 | } | ||
435 | return ExceptionContinueSearch; | ||
436 | } | 728 | } |
437 | 729 | ||
438 | /* Raise Windows exception. */ | 730 | #endif |
439 | static void err_raise_ext(int errcode) | ||
440 | { | ||
441 | RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); | ||
442 | } | ||
443 | 731 | ||
444 | #endif | 732 | #endif |
445 | 733 | ||
@@ -450,22 +738,23 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) | |||
450 | { | 738 | { |
451 | global_State *g = G(L); | 739 | global_State *g = G(L); |
452 | lj_trace_abort(g); | 740 | lj_trace_abort(g); |
453 | setgcrefnull(g->jit_L); | 741 | L->status = LUA_OK; |
454 | L->status = 0; | ||
455 | #if LJ_UNWIND_EXT | 742 | #if LJ_UNWIND_EXT |
456 | err_raise_ext(errcode); | 743 | err_raise_ext(g, errcode); |
457 | /* | 744 | /* |
458 | ** A return from this function signals a corrupt C stack that cannot be | 745 | ** A return from this function signals a corrupt C stack that cannot be |
459 | ** unwound. We have no choice but to call the panic function and exit. | 746 | ** unwound. We have no choice but to call the panic function and exit. |
460 | ** | 747 | ** |
461 | ** Usually this is caused by a C function without unwind information. | 748 | ** Usually this is caused by a C function without unwind information. |
462 | ** This should never happen on x64, but may happen if you've manually | 749 | ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL |
463 | ** enabled LUAJIT_UNWIND_EXTERNAL and forgot to recompile *every* | 750 | ** and forgot to recompile *every* non-C++ file with -funwind-tables. |
464 | ** non-C++ file with -funwind-tables. | ||
465 | */ | 751 | */ |
466 | if (G(L)->panic) | 752 | if (G(L)->panic) |
467 | G(L)->panic(L); | 753 | G(L)->panic(L); |
468 | #else | 754 | #else |
755 | #if LJ_HASJIT | ||
756 | setmref(g->jit_base, NULL); | ||
757 | #endif | ||
469 | { | 758 | { |
470 | void *cf = err_unwind(L, NULL, errcode); | 759 | void *cf = err_unwind(L, NULL, errcode); |
471 | if (cframe_unwind_ff(cf)) | 760 | if (cframe_unwind_ff(cf)) |
@@ -495,7 +784,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) | |||
495 | /* Find error function for runtime errors. Requires an extra stack traversal. */ | 784 | /* Find error function for runtime errors. Requires an extra stack traversal. */ |
496 | static ptrdiff_t finderrfunc(lua_State *L) | 785 | static ptrdiff_t finderrfunc(lua_State *L) |
497 | { | 786 | { |
498 | cTValue *frame = L->base-1, *bot = tvref(L->stack); | 787 | cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; |
499 | void *cf = L->cframe; | 788 | void *cf = L->cframe; |
500 | while (frame > bot && cf) { | 789 | while (frame > bot && cf) { |
501 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ | 790 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ |
@@ -519,10 +808,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
519 | frame = frame_prevd(frame); | 808 | frame = frame_prevd(frame); |
520 | break; | 809 | break; |
521 | case FRAME_CONT: | 810 | case FRAME_CONT: |
522 | #if LJ_HASFFI | 811 | if (frame_iscont_fficb(frame)) |
523 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
524 | cf = cframe_prev(cf); | 812 | cf = cframe_prev(cf); |
525 | #endif | ||
526 | frame = frame_prevd(frame); | 813 | frame = frame_prevd(frame); |
527 | break; | 814 | break; |
528 | case FRAME_CP: | 815 | case FRAME_CP: |
@@ -534,11 +821,11 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
534 | break; | 821 | break; |
535 | case FRAME_PCALL: | 822 | case FRAME_PCALL: |
536 | case FRAME_PCALLH: | 823 | case FRAME_PCALLH: |
537 | if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ | 824 | if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) |
538 | return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ | 825 | return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ |
539 | return 0; | 826 | return 0; |
540 | default: | 827 | default: |
541 | lua_assert(0); | 828 | lj_assertL(0, "bad frame type"); |
542 | return 0; | 829 | return 0; |
543 | } | 830 | } |
544 | } | 831 | } |
@@ -548,7 +835,7 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
548 | /* Runtime error. */ | 835 | /* Runtime error. */ |
549 | LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | 836 | LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) |
550 | { | 837 | { |
551 | ptrdiff_t ef = finderrfunc(L); | 838 | ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L); |
552 | if (ef) { | 839 | if (ef) { |
553 | TValue *errfunc = restorestack(L, ef); | 840 | TValue *errfunc = restorestack(L, ef); |
554 | TValue *top = L->top; | 841 | TValue *top = L->top; |
@@ -558,14 +845,25 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | |||
558 | lj_err_throw(L, LUA_ERRERR); | 845 | lj_err_throw(L, LUA_ERRERR); |
559 | } | 846 | } |
560 | L->status = LUA_ERRERR; | 847 | L->status = LUA_ERRERR; |
561 | copyTV(L, top, top-1); | 848 | copyTV(L, top+LJ_FR2, top-1); |
562 | copyTV(L, top-1, errfunc); | 849 | copyTV(L, top-1, errfunc); |
850 | if (LJ_FR2) setnilV(top++); | ||
563 | L->top = top+1; | 851 | L->top = top+1; |
564 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ | 852 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ |
565 | } | 853 | } |
566 | lj_err_throw(L, LUA_ERRRUN); | 854 | lj_err_throw(L, LUA_ERRRUN); |
567 | } | 855 | } |
568 | 856 | ||
857 | #if LJ_HASJIT | ||
858 | LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode) | ||
859 | { | ||
860 | if (errcode == LUA_ERRRUN) | ||
861 | lj_err_run(L); | ||
862 | else | ||
863 | lj_err_throw(L, errcode); | ||
864 | } | ||
865 | #endif | ||
866 | |||
569 | /* Formatted runtime error message. */ | 867 | /* Formatted runtime error message. */ |
570 | LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | 868 | LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) |
571 | { | 869 | { |
@@ -573,7 +871,7 @@ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | |||
573 | va_list argp; | 871 | va_list argp; |
574 | va_start(argp, em); | 872 | va_start(argp, em); |
575 | if (curr_funcisL(L)) L->top = curr_topL(L); | 873 | if (curr_funcisL(L)) L->top = curr_topL(L); |
576 | msg = lj_str_pushvf(L, err2msg(em), argp); | 874 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
577 | va_end(argp); | 875 | va_end(argp); |
578 | lj_debug_addloc(L, msg, L->base-1, NULL); | 876 | lj_debug_addloc(L, msg, L->base-1, NULL); |
579 | lj_err_run(L); | 877 | lj_err_run(L); |
@@ -591,11 +889,11 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | |||
591 | { | 889 | { |
592 | char buff[LUA_IDSIZE]; | 890 | char buff[LUA_IDSIZE]; |
593 | const char *msg; | 891 | const char *msg; |
594 | lj_debug_shortname(buff, src); | 892 | lj_debug_shortname(buff, src, line); |
595 | msg = lj_str_pushvf(L, err2msg(em), argp); | 893 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
596 | msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); | 894 | msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg); |
597 | if (tok) | 895 | if (tok) |
598 | lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); | 896 | lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); |
599 | lj_err_throw(L, LUA_ERRSYNTAX); | 897 | lj_err_throw(L, LUA_ERRSYNTAX); |
600 | } | 898 | } |
601 | 899 | ||
@@ -634,8 +932,9 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
634 | const BCIns *pc = cframe_Lpc(L); | 932 | const BCIns *pc = cframe_Lpc(L); |
635 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { | 933 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { |
636 | const char *tname = lj_typename(o); | 934 | const char *tname = lj_typename(o); |
935 | setframe_gc(o, obj2gco(L), LJ_TTHREAD); | ||
936 | if (LJ_FR2) o++; | ||
637 | setframe_pc(o, pc); | 937 | setframe_pc(o, pc); |
638 | setframe_gc(o, obj2gco(L)); | ||
639 | L->top = L->base = o+1; | 938 | L->top = L->base = o+1; |
640 | err_msgv(L, LJ_ERR_BADCALL, tname); | 939 | err_msgv(L, LJ_ERR_BADCALL, tname); |
641 | } | 940 | } |
@@ -645,28 +944,27 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
645 | /* Error in context of caller. */ | 944 | /* Error in context of caller. */ |
646 | LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) | 945 | LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) |
647 | { | 946 | { |
648 | TValue *frame = L->base-1; | 947 | TValue *frame = NULL, *pframe = NULL; |
649 | TValue *pframe = NULL; | 948 | if (!(LJ_HASJIT && tvref(G(L)->jit_base))) { |
650 | if (frame_islua(frame)) { | 949 | frame = L->base-1; |
651 | pframe = frame_prevl(frame); | 950 | if (frame_islua(frame)) { |
652 | } else if (frame_iscont(frame)) { | 951 | pframe = frame_prevl(frame); |
952 | } else if (frame_iscont(frame)) { | ||
953 | if (frame_iscont_fficb(frame)) { | ||
954 | pframe = frame; | ||
955 | frame = NULL; | ||
956 | } else { | ||
957 | pframe = frame_prevd(frame); | ||
653 | #if LJ_HASFFI | 958 | #if LJ_HASFFI |
654 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) { | 959 | /* Remove frame for FFI metamethods. */ |
655 | pframe = frame; | 960 | if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && |
656 | frame = NULL; | 961 | frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { |
657 | } else | 962 | L->base = pframe+1; |
963 | L->top = frame; | ||
964 | setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); | ||
965 | } | ||
658 | #endif | 966 | #endif |
659 | { | ||
660 | pframe = frame_prevd(frame); | ||
661 | #if LJ_HASFFI | ||
662 | /* Remove frame for FFI metamethods. */ | ||
663 | if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && | ||
664 | frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { | ||
665 | L->base = pframe+1; | ||
666 | L->top = frame; | ||
667 | setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); | ||
668 | } | 967 | } |
669 | #endif | ||
670 | } | 968 | } |
671 | } | 969 | } |
672 | lj_debug_addloc(L, msg, pframe, frame); | 970 | lj_debug_addloc(L, msg, pframe, frame); |
@@ -679,7 +977,7 @@ LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...) | |||
679 | const char *msg; | 977 | const char *msg; |
680 | va_list argp; | 978 | va_list argp; |
681 | va_start(argp, em); | 979 | va_start(argp, em); |
682 | msg = lj_str_pushvf(L, err2msg(em), argp); | 980 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
683 | va_end(argp); | 981 | va_end(argp); |
684 | lj_err_callermsg(L, msg); | 982 | lj_err_callermsg(L, msg); |
685 | } | 983 | } |
@@ -699,9 +997,9 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg, | |||
699 | if (narg < 0 && narg > LUA_REGISTRYINDEX) | 997 | if (narg < 0 && narg > LUA_REGISTRYINDEX) |
700 | narg = (int)(L->top - L->base) + narg + 1; | 998 | narg = (int)(L->top - L->base) + narg + 1; |
701 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ | 999 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ |
702 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); | 1000 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); |
703 | else | 1001 | else |
704 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); | 1002 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); |
705 | lj_err_callermsg(L, msg); | 1003 | lj_err_callermsg(L, msg); |
706 | } | 1004 | } |
707 | 1005 | ||
@@ -711,7 +1009,7 @@ LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...) | |||
711 | const char *msg; | 1009 | const char *msg; |
712 | va_list argp; | 1010 | va_list argp; |
713 | va_start(argp, em); | 1011 | va_start(argp, em); |
714 | msg = lj_str_pushvf(L, err2msg(em), argp); | 1012 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
715 | va_end(argp); | 1013 | va_end(argp); |
716 | err_argmsg(L, narg, msg); | 1014 | err_argmsg(L, narg, msg); |
717 | } | 1015 | } |
@@ -741,7 +1039,7 @@ LJ_NOINLINE void lj_err_argtype(lua_State *L, int narg, const char *xname) | |||
741 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; | 1039 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; |
742 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; | 1040 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; |
743 | } | 1041 | } |
744 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); | 1042 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); |
745 | err_argmsg(L, narg, msg); | 1043 | err_argmsg(L, narg, msg); |
746 | } | 1044 | } |
747 | 1045 | ||
@@ -791,7 +1089,7 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) | |||
791 | const char *msg; | 1089 | const char *msg; |
792 | va_list argp; | 1090 | va_list argp; |
793 | va_start(argp, fmt); | 1091 | va_start(argp, fmt); |
794 | msg = lj_str_pushvf(L, fmt, argp); | 1092 | msg = lj_strfmt_pushvf(L, fmt, argp); |
795 | va_end(argp); | 1093 | va_end(argp); |
796 | lj_err_callermsg(L, msg); | 1094 | lj_err_callermsg(L, msg); |
797 | return 0; /* unreachable */ | 1095 | return 0; /* unreachable */ |