diff options
Diffstat (limited to 'src/lj_err.c')
| -rw-r--r-- | src/lj_err.c | 746 |
1 files changed, 550 insertions, 196 deletions
diff --git a/src/lj_err.c b/src/lj_err.c index 0ff37212..d2cffb0d 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); |
| @@ -160,14 +174,17 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
| 160 | case FRAME_PCALL: /* FF pcall() frame. */ | 174 | case FRAME_PCALL: /* FF pcall() frame. */ |
| 161 | case FRAME_PCALLH: /* FF pcall() frame inside hook. */ | 175 | case FRAME_PCALLH: /* FF pcall() frame inside hook. */ |
| 162 | if (errcode) { | 176 | if (errcode) { |
| 177 | global_State *g; | ||
| 163 | if (errcode == LUA_YIELD) { | 178 | if (errcode == LUA_YIELD) { |
| 164 | frame = frame_prevd(frame); | 179 | frame = frame_prevd(frame); |
| 165 | break; | 180 | break; |
| 166 | } | 181 | } |
| 182 | g = G(L); | ||
| 183 | setgcref(g->cur_L, obj2gco(L)); | ||
| 167 | if (frame_typep(frame) == FRAME_PCALL) | 184 | if (frame_typep(frame) == FRAME_PCALL) |
| 168 | hook_leave(G(L)); | 185 | hook_leave(g); |
| 169 | L->cframe = cf; | ||
| 170 | L->base = frame_prevd(frame) + 1; | 186 | L->base = frame_prevd(frame) + 1; |
| 187 | L->cframe = cf; | ||
| 171 | unwindstack(L, L->base); | 188 | unwindstack(L, L->base); |
| 172 | } | 189 | } |
| 173 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); | 190 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); |
| @@ -175,8 +192,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
| 175 | } | 192 | } |
| 176 | /* No C frame. */ | 193 | /* No C frame. */ |
| 177 | if (errcode) { | 194 | if (errcode) { |
| 195 | L->base = tvref(L->stack)+1+LJ_FR2; | ||
| 178 | L->cframe = NULL; | 196 | L->cframe = NULL; |
| 179 | L->base = tvref(L->stack)+1; | ||
| 180 | unwindstack(L, L->base); | 197 | unwindstack(L, L->base); |
| 181 | if (G(L)->panic) | 198 | if (G(L)->panic) |
| 182 | G(L)->panic(L); | 199 | G(L)->panic(L); |
| @@ -187,33 +204,226 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
| 187 | 204 | ||
| 188 | /* -- External frame unwinding -------------------------------------------- */ | 205 | /* -- External frame unwinding -------------------------------------------- */ |
| 189 | 206 | ||
| 190 | #if defined(__GNUC__) && !LJ_NO_UNWIND && !LJ_ABI_WIN | 207 | #if LJ_ABI_WIN |
| 191 | 208 | ||
| 192 | /* | 209 | /* |
| 193 | ** We have to use our own definitions instead of the mandatory (!) unwind.h, | 210 | ** 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. | 211 | ** undocumented or just plain wrong on MSDN. Some of it can be gathered |
| 212 | ** from 3rd party docs or must be found by trial-and-error. They really | ||
| 213 | ** don't want you to write your own language-specific exception handler | ||
| 214 | ** or to interact gracefully with MSVC. :-( | ||
| 195 | */ | 215 | */ |
| 196 | 216 | ||
| 197 | typedef struct _Unwind_Exception | 217 | #define WIN32_LEAN_AND_MEAN |
| 218 | #include <windows.h> | ||
| 219 | |||
| 220 | #if LJ_TARGET_X86 | ||
| 221 | typedef void *UndocumentedDispatcherContext; /* Unused on x86. */ | ||
| 222 | #else | ||
| 223 | /* Taken from: http://www.nynaeve.net/?p=99 */ | ||
| 224 | typedef struct UndocumentedDispatcherContext { | ||
| 225 | ULONG64 ControlPc; | ||
| 226 | ULONG64 ImageBase; | ||
| 227 | PRUNTIME_FUNCTION FunctionEntry; | ||
| 228 | ULONG64 EstablisherFrame; | ||
| 229 | ULONG64 TargetIp; | ||
| 230 | PCONTEXT ContextRecord; | ||
| 231 | void (*LanguageHandler)(void); | ||
| 232 | PVOID HandlerData; | ||
| 233 | PUNWIND_HISTORY_TABLE HistoryTable; | ||
| 234 | ULONG ScopeIndex; | ||
| 235 | ULONG Fill0; | ||
| 236 | } UndocumentedDispatcherContext; | ||
| 237 | #endif | ||
| 238 | |||
| 239 | /* Another wild guess. */ | ||
| 240 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); | ||
| 241 | |||
| 242 | #define LJ_MSVC_EXCODE ((DWORD)0xe06d7363) | ||
| 243 | #define LJ_GCC_EXCODE ((DWORD)0x20474343) | ||
| 244 | |||
| 245 | #define LJ_EXCODE ((DWORD)0xe24c4a00) | ||
| 246 | #define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) | ||
| 247 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | ||
| 248 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
| 249 | |||
| 250 | /* Windows exception handler for interpreter frame. */ | ||
| 251 | LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, | ||
| 252 | void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) | ||
| 198 | { | 253 | { |
| 199 | uint64_t exclass; | 254 | #if LJ_TARGET_X86 |
| 200 | void (*excleanup)(int, struct _Unwind_Exception *); | 255 | void *cf = (char *)f - CFRAME_OFS_SEH; |
| 201 | uintptr_t p1, p2; | 256 | #elif LJ_TARGET_ARM64 |
| 202 | } __attribute__((__aligned__)) _Unwind_Exception; | 257 | void *cf = (char *)f - CFRAME_SIZE; |
| 258 | #else | ||
| 259 | void *cf = f; | ||
| 260 | #endif | ||
| 261 | lua_State *L = cframe_L(cf); | ||
| 262 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? | ||
| 263 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; | ||
| 264 | if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */ | ||
| 265 | if (rec->ExceptionCode == STATUS_LONGJUMP && | ||
| 266 | rec->ExceptionRecord && | ||
| 267 | LJ_EXCODE_CHECK(rec->ExceptionRecord->ExceptionCode)) { | ||
| 268 | errcode = LJ_EXCODE_ERRCODE(rec->ExceptionRecord->ExceptionCode); | ||
| 269 | if ((rec->ExceptionFlags & 0x20)) { /* EH_TARGET_UNWIND */ | ||
| 270 | /* Unwinding is about to finish; revert the ExceptionCode so that | ||
| 271 | ** RtlRestoreContext does not try to restore from a _JUMP_BUFFER. | ||
| 272 | */ | ||
| 273 | rec->ExceptionCode = 0; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | /* Unwind internal frames. */ | ||
| 277 | err_unwind(L, cf, errcode); | ||
| 278 | } else { | ||
| 279 | void *cf2 = err_unwind(L, cf, 0); | ||
| 280 | if (cf2) { /* We catch it, so start unwinding the upper frames. */ | ||
| 281 | #if !LJ_TARGET_X86 | ||
| 282 | EXCEPTION_RECORD rec2; | ||
| 283 | #endif | ||
| 284 | if (rec->ExceptionCode == LJ_MSVC_EXCODE || | ||
| 285 | rec->ExceptionCode == LJ_GCC_EXCODE) { | ||
| 286 | #if !LJ_TARGET_CYGWIN | ||
| 287 | __DestructExceptionObject(rec, 1); | ||
| 288 | #endif | ||
| 289 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | ||
| 290 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { | ||
| 291 | /* Don't catch access violations etc. */ | ||
| 292 | return 1; /* ExceptionContinueSearch */ | ||
| 293 | } | ||
| 294 | #if LJ_TARGET_X86 | ||
| 295 | UNUSED(ctx); | ||
| 296 | UNUSED(dispatch); | ||
| 297 | /* Call all handlers for all lower C frames (including ourselves) again | ||
| 298 | ** with EH_UNWINDING set. Then call the specified function, passing cf | ||
| 299 | ** and errcode. | ||
| 300 | */ | ||
| 301 | lj_vm_rtlunwind(cf, (void *)rec, | ||
| 302 | (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
| 303 | (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode); | ||
| 304 | /* lj_vm_rtlunwind does not return. */ | ||
| 305 | #else | ||
| 306 | if (LJ_EXCODE_CHECK(rec->ExceptionCode)) { | ||
| 307 | /* For unwind purposes, wrap the EXCEPTION_RECORD in something that | ||
| 308 | ** looks like a longjmp, so that MSVC will execute C++ destructors in | ||
| 309 | ** the frames we unwind over. ExceptionInformation[0] should really | ||
| 310 | ** contain a _JUMP_BUFFER*, but hopefully nobody is looking too closely | ||
| 311 | ** at this point. | ||
| 312 | */ | ||
| 313 | rec2.ExceptionCode = STATUS_LONGJUMP; | ||
| 314 | rec2.ExceptionRecord = rec; | ||
| 315 | rec2.ExceptionAddress = 0; | ||
| 316 | rec2.NumberParameters = 1; | ||
| 317 | rec2.ExceptionInformation[0] = (ULONG_PTR)ctx; | ||
| 318 | rec = &rec2; | ||
| 319 | } | ||
| 320 | /* Unwind the stack and call all handlers for all lower C frames | ||
| 321 | ** (including ourselves) again with EH_UNWINDING set. Then set | ||
| 322 | ** stack pointer = f, result = errcode and jump to the specified target. | ||
| 323 | */ | ||
| 324 | RtlUnwindEx(f, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
| 325 | lj_vm_unwind_ff_eh : | ||
| 326 | lj_vm_unwind_c_eh), | ||
| 327 | rec, (void *)(uintptr_t)errcode, dispatch->ContextRecord, | ||
| 328 | dispatch->HistoryTable); | ||
| 329 | /* RtlUnwindEx should never return. */ | ||
| 330 | #endif | ||
| 331 | } | ||
| 332 | } | ||
| 333 | return 1; /* ExceptionContinueSearch */ | ||
| 334 | } | ||
| 335 | |||
| 336 | #if LJ_UNWIND_JIT | ||
| 337 | |||
| 338 | #if LJ_TARGET_X64 | ||
| 339 | #define CONTEXT_REG_PC Rip | ||
| 340 | #elif LJ_TARGET_ARM64 | ||
| 341 | #define CONTEXT_REG_PC Pc | ||
| 342 | #else | ||
| 343 | #error "NYI: Windows arch-specific unwinder for JIT-compiled code" | ||
| 344 | #endif | ||
| 345 | |||
| 346 | /* Windows unwinder for JIT-compiled code. */ | ||
| 347 | static void err_unwind_win_jit(global_State *g, int errcode) | ||
| 348 | { | ||
| 349 | CONTEXT ctx; | ||
| 350 | UNWIND_HISTORY_TABLE hist; | ||
| 351 | |||
| 352 | memset(&hist, 0, sizeof(hist)); | ||
| 353 | RtlCaptureContext(&ctx); | ||
| 354 | while (1) { | ||
| 355 | DWORD64 frame, base, addr = ctx.CONTEXT_REG_PC; | ||
| 356 | void *hdata; | ||
| 357 | PRUNTIME_FUNCTION func = RtlLookupFunctionEntry(addr, &base, &hist); | ||
| 358 | if (!func) { /* Found frame without .pdata: must be JIT-compiled code. */ | ||
| 359 | ExitNo exitno; | ||
| 360 | uintptr_t stub = lj_trace_unwind(G2J(g), (uintptr_t)(addr - sizeof(MCode)), &exitno); | ||
| 361 | if (stub) { /* Jump to side exit to unwind the trace. */ | ||
| 362 | ctx.CONTEXT_REG_PC = stub; | ||
| 363 | G2J(g)->exitcode = errcode; | ||
| 364 | RtlRestoreContext(&ctx, NULL); /* Does not return. */ | ||
| 365 | } | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | RtlVirtualUnwind(UNW_FLAG_NHANDLER, base, addr, func, | ||
| 369 | &ctx, &hdata, &frame, NULL); | ||
| 370 | if (!addr) break; | ||
| 371 | } | ||
| 372 | /* Unwinding failed, if we end up here. */ | ||
| 373 | } | ||
| 374 | #endif | ||
| 375 | |||
| 376 | /* Raise Windows exception. */ | ||
| 377 | static void err_raise_ext(global_State *g, int errcode) | ||
| 378 | { | ||
| 379 | #if LJ_UNWIND_JIT | ||
| 380 | if (tvref(g->jit_base)) { | ||
| 381 | err_unwind_win_jit(g, errcode); | ||
| 382 | return; /* Unwinding failed. */ | ||
| 383 | } | ||
| 384 | #elif LJ_HASJIT | ||
| 385 | /* Cannot catch on-trace errors for Windows/x86 SEH. Unwind to interpreter. */ | ||
| 386 | setmref(g->jit_base, NULL); | ||
| 387 | #endif | ||
| 388 | UNUSED(g); | ||
| 389 | RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); | ||
| 390 | } | ||
| 391 | |||
| 392 | #elif !LJ_NO_UNWIND && (defined(__GNUC__) || defined(__clang__)) | ||
| 393 | |||
| 394 | /* | ||
| 395 | ** We have to use our own definitions instead of the mandatory (!) unwind.h, | ||
| 396 | ** since various OS, distros and compilers mess up the header installation. | ||
| 397 | */ | ||
| 203 | 398 | ||
| 204 | typedef struct _Unwind_Context _Unwind_Context; | 399 | typedef struct _Unwind_Context _Unwind_Context; |
| 205 | 400 | ||
| 206 | #define _URC_OK 0 | 401 | #define _URC_OK 0 |
| 402 | #define _URC_FATAL_PHASE2_ERROR 2 | ||
| 207 | #define _URC_FATAL_PHASE1_ERROR 3 | 403 | #define _URC_FATAL_PHASE1_ERROR 3 |
| 208 | #define _URC_HANDLER_FOUND 6 | 404 | #define _URC_HANDLER_FOUND 6 |
| 209 | #define _URC_INSTALL_CONTEXT 7 | 405 | #define _URC_INSTALL_CONTEXT 7 |
| 210 | #define _URC_CONTINUE_UNWIND 8 | 406 | #define _URC_CONTINUE_UNWIND 8 |
| 211 | #define _URC_FAILURE 9 | 407 | #define _URC_FAILURE 9 |
| 212 | 408 | ||
| 409 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
| 410 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
| 411 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
| 412 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
| 413 | |||
| 213 | #if !LJ_TARGET_ARM | 414 | #if !LJ_TARGET_ARM |
| 214 | 415 | ||
| 416 | typedef struct _Unwind_Exception | ||
| 417 | { | ||
| 418 | uint64_t exclass; | ||
| 419 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
| 420 | uintptr_t p1, p2; | ||
| 421 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
| 422 | #define UNWIND_EXCEPTION_TYPE _Unwind_Exception | ||
| 423 | |||
| 215 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 424 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
| 216 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 425 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
| 426 | extern uintptr_t _Unwind_GetIP(_Unwind_Context *); | ||
| 217 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 427 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
| 218 | extern void _Unwind_DeleteException(_Unwind_Exception *); | 428 | extern void _Unwind_DeleteException(_Unwind_Exception *); |
| 219 | extern int _Unwind_RaiseException(_Unwind_Exception *); | 429 | extern int _Unwind_RaiseException(_Unwind_Exception *); |
| @@ -223,11 +433,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *); | |||
| 223 | #define _UA_HANDLER_FRAME 4 | 433 | #define _UA_HANDLER_FRAME 4 |
| 224 | #define _UA_FORCE_UNWIND 8 | 434 | #define _UA_FORCE_UNWIND 8 |
| 225 | 435 | ||
| 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. */ | 436 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ |
| 232 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | 437 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, |
| 233 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | 438 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) |
| @@ -236,7 +441,6 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | |||
| 236 | lua_State *L; | 441 | lua_State *L; |
| 237 | if (version != 1) | 442 | if (version != 1) |
| 238 | return _URC_FATAL_PHASE1_ERROR; | 443 | return _URC_FATAL_PHASE1_ERROR; |
| 239 | UNUSED(uexclass); | ||
| 240 | cf = (void *)_Unwind_GetCFA(ctx); | 444 | cf = (void *)_Unwind_GetCFA(ctx); |
| 241 | L = cframe_L(cf); | 445 | L = cframe_L(cf); |
| 242 | if ((actions & _UA_SEARCH_PHASE)) { | 446 | if ((actions & _UA_SEARCH_PHASE)) { |
| @@ -263,10 +467,10 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | |||
| 263 | if ((actions & _UA_FORCE_UNWIND)) { | 467 | if ((actions & _UA_FORCE_UNWIND)) { |
| 264 | return _URC_CONTINUE_UNWIND; | 468 | return _URC_CONTINUE_UNWIND; |
| 265 | } else if (cf) { | 469 | } else if (cf) { |
| 470 | ASMFunction ip; | ||
| 266 | _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode); | 471 | _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode); |
| 267 | _Unwind_SetIP(ctx, (uintptr_t)(cframe_unwind_ff(cf) ? | 472 | ip = cframe_unwind_ff(cf) ? lj_vm_unwind_ff_eh : lj_vm_unwind_c_eh; |
| 268 | lj_vm_unwind_ff_eh : | 473 | _Unwind_SetIP(ctx, (uintptr_t)lj_ptr_strip(ip)); |
| 269 | lj_vm_unwind_c_eh)); | ||
| 270 | return _URC_INSTALL_CONTEXT; | 474 | return _URC_INSTALL_CONTEXT; |
| 271 | } | 475 | } |
| 272 | #if LJ_TARGET_X86ORX64 | 476 | #if LJ_TARGET_X86ORX64 |
| @@ -284,27 +488,170 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | |||
| 284 | ** it on non-x64 because the interpreter restores all callee-saved regs. | 488 | ** it on non-x64 because the interpreter restores all callee-saved regs. |
| 285 | */ | 489 | */ |
| 286 | lj_err_throw(L, errcode); | 490 | lj_err_throw(L, errcode); |
| 491 | #if LJ_TARGET_X64 | ||
| 492 | #error "Broken build system -- only use the provided Makefiles!" | ||
| 493 | #endif | ||
| 287 | #endif | 494 | #endif |
| 288 | } | 495 | } |
| 289 | return _URC_CONTINUE_UNWIND; | 496 | return _URC_CONTINUE_UNWIND; |
| 290 | } | 497 | } |
| 291 | 498 | ||
| 292 | #if LJ_UNWIND_EXT | 499 | #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) |
| 293 | static __thread _Unwind_Exception static_uex; | 500 | struct dwarf_eh_bases { void *tbase, *dbase, *func; }; |
| 501 | extern const void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases); | ||
| 294 | 502 | ||
| 295 | /* Raise DWARF2 exception. */ | 503 | /* Verify that external error handling actually has a chance to work. */ |
| 296 | static void err_raise_ext(int errcode) | 504 | void lj_err_verify(void) |
| 297 | { | 505 | { |
| 298 | static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); | 506 | #if !LJ_TARGET_OSX |
| 299 | static_uex.excleanup = NULL; | 507 | /* Check disabled on MacOS due to brilliant software engineering at Apple. */ |
| 300 | _Unwind_RaiseException(&static_uex); | 508 | struct dwarf_eh_bases ehb; |
| 509 | lj_assertX(_Unwind_Find_FDE((void *)lj_err_throw, &ehb), "broken build: external frame unwinding enabled, but missing -funwind-tables"); | ||
| 510 | #endif | ||
| 511 | /* Check disabled, because of broken Fedora/ARM64. See #722. | ||
| 512 | lj_assertX(_Unwind_Find_FDE((void *)_Unwind_RaiseException, &ehb), "broken build: external frame unwinding enabled, but system libraries have no unwind tables"); | ||
| 513 | */ | ||
| 301 | } | 514 | } |
| 302 | #endif | 515 | #endif |
| 303 | 516 | ||
| 517 | #if LJ_UNWIND_JIT | ||
| 518 | /* DWARF2 personality handler for JIT-compiled code. */ | ||
| 519 | static int err_unwind_jit(int version, int actions, | ||
| 520 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | ||
| 521 | { | ||
| 522 | /* NYI: FFI C++ exception interoperability. */ | ||
| 523 | if (version != 1 || !LJ_UEXCLASS_CHECK(uexclass)) | ||
| 524 | return _URC_FATAL_PHASE1_ERROR; | ||
| 525 | if ((actions & _UA_SEARCH_PHASE)) { | ||
| 526 | return _URC_HANDLER_FOUND; | ||
| 527 | } | ||
| 528 | if ((actions & _UA_CLEANUP_PHASE)) { | ||
| 529 | global_State *g = *(global_State **)(uex+1); | ||
| 530 | ExitNo exitno; | ||
| 531 | uintptr_t addr = _Unwind_GetIP(ctx); /* Return address _after_ call. */ | ||
| 532 | uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno); | ||
| 533 | lj_assertG(tvref(g->jit_base), "unexpected throw across mcode frame"); | ||
| 534 | if (stub) { /* Jump to side exit to unwind the trace. */ | ||
| 535 | G2J(g)->exitcode = LJ_UEXCLASS_ERRCODE(uexclass); | ||
| 536 | #ifdef LJ_TARGET_MIPS | ||
| 537 | _Unwind_SetGR(ctx, 4, stub); | ||
| 538 | _Unwind_SetGR(ctx, 5, exitno); | ||
| 539 | _Unwind_SetIP(ctx, (uintptr_t)(void *)lj_vm_unwind_stub); | ||
| 540 | #else | ||
| 541 | _Unwind_SetIP(ctx, stub); | ||
| 542 | #endif | ||
| 543 | return _URC_INSTALL_CONTEXT; | ||
| 544 | } | ||
| 545 | return _URC_FATAL_PHASE2_ERROR; | ||
| 546 | } | ||
| 547 | return _URC_FATAL_PHASE1_ERROR; | ||
| 548 | } | ||
| 549 | |||
| 550 | /* DWARF2 template frame info for JIT-compiled code. | ||
| 551 | ** | ||
| 552 | ** After copying the template to the start of the mcode segment, | ||
| 553 | ** the frame handler function and the code size is patched. | ||
| 554 | ** The frame handler always installs a new context to jump to the exit, | ||
| 555 | ** so don't bother to add any unwind opcodes. | ||
| 556 | */ | ||
| 557 | static const uint8_t err_frame_jit_template[] = { | ||
| 558 | #if LJ_BE | ||
| 559 | 0,0,0, | ||
| 560 | #endif | ||
| 561 | LJ_64 ? 0x1c : 0x14, /* CIE length. */ | ||
| 562 | #if LJ_LE | ||
| 563 | 0,0,0, | ||
| 564 | #endif | ||
| 565 | 0,0,0,0, 1, 'z','P','R',0, /* CIE mark, CIE version, augmentation. */ | ||
| 566 | 1, LJ_64 ? 0x78 : 0x7c, LJ_TARGET_EHRAREG, /* Code/data align, RA. */ | ||
| 567 | #if LJ_64 | ||
| 568 | 10, 0, 0,0,0,0,0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ | ||
| 569 | 0,0,0,0,0, /* Alignment. */ | ||
| 570 | #else | ||
| 571 | 6, 0, 0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ | ||
| 572 | 0, /* Alignment. */ | ||
| 573 | #endif | ||
| 574 | #if LJ_BE | ||
| 575 | 0,0,0, | ||
| 576 | #endif | ||
| 577 | LJ_64 ? 0x14 : 0x10, /* FDE length. */ | ||
| 578 | 0,0,0, | ||
| 579 | LJ_64 ? 0x24 : 0x1c, /* CIE offset. */ | ||
| 580 | 0,0,0, | ||
| 581 | LJ_64 ? 0x14 : 0x10, /* Code offset. After Final FDE. */ | ||
| 582 | #if LJ_LE | ||
| 583 | 0,0,0, | ||
| 584 | #endif | ||
| 585 | 0,0,0,0, 0, 0,0,0, /* Code size, augmentation length, alignment. */ | ||
| 586 | #if LJ_64 | ||
| 587 | 0,0,0,0, /* Alignment. */ | ||
| 588 | #endif | ||
| 589 | 0,0,0,0 /* Final FDE. */ | ||
| 590 | }; | ||
| 591 | |||
| 592 | #define ERR_FRAME_JIT_OFS_HANDLER 0x12 | ||
| 593 | #define ERR_FRAME_JIT_OFS_FDE (LJ_64 ? 0x20 : 0x18) | ||
| 594 | #define ERR_FRAME_JIT_OFS_CODE_SIZE (LJ_64 ? 0x2c : 0x24) | ||
| 595 | #if LJ_TARGET_OSX | ||
| 596 | #define ERR_FRAME_JIT_OFS_REGISTER ERR_FRAME_JIT_OFS_FDE | ||
| 304 | #else | 597 | #else |
| 598 | #define ERR_FRAME_JIT_OFS_REGISTER 0 | ||
| 599 | #endif | ||
| 600 | |||
| 601 | extern void __register_frame(const void *); | ||
| 602 | extern void __deregister_frame(const void *); | ||
| 603 | |||
| 604 | uint8_t *lj_err_register_mcode(void *base, size_t sz, uint8_t *info) | ||
| 605 | { | ||
| 606 | ASMFunction handler = (ASMFunction)err_unwind_jit; | ||
| 607 | memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template)); | ||
| 608 | #if LJ_ABI_PAUTH | ||
| 609 | #if LJ_TARGET_ARM64 | ||
| 610 | handler = ptrauth_auth_and_resign(handler, | ||
| 611 | ptrauth_key_function_pointer, 0, | ||
| 612 | ptrauth_key_process_independent_code, info + ERR_FRAME_JIT_OFS_HANDLER); | ||
| 613 | #else | ||
| 614 | #error "missing pointer authentication support for this architecture" | ||
| 615 | #endif | ||
| 616 | #endif | ||
| 617 | memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler)); | ||
| 618 | *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) = | ||
| 619 | (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base)); | ||
| 620 | __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | ||
| 621 | #ifdef LUA_USE_ASSERT | ||
| 622 | { | ||
| 623 | struct dwarf_eh_bases ehb; | ||
| 624 | lj_assertX(_Unwind_Find_FDE(info + sizeof(err_frame_jit_template)+1, &ehb), | ||
| 625 | "bad JIT unwind table registration"); | ||
| 626 | } | ||
| 627 | #endif | ||
| 628 | return info + sizeof(err_frame_jit_template); | ||
| 629 | } | ||
| 630 | |||
| 631 | void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info) | ||
| 632 | { | ||
| 633 | UNUSED(base); UNUSED(sz); | ||
| 634 | __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | ||
| 635 | } | ||
| 636 | #endif | ||
| 637 | |||
| 638 | #else /* LJ_TARGET_ARM */ | ||
| 305 | 639 | ||
| 306 | extern void _Unwind_DeleteException(void *); | 640 | #define _US_VIRTUAL_UNWIND_FRAME 0 |
| 307 | extern int __gnu_unwind_frame (void *, _Unwind_Context *); | 641 | #define _US_UNWIND_FRAME_STARTING 1 |
| 642 | #define _US_ACTION_MASK 3 | ||
| 643 | #define _US_FORCE_UNWIND 8 | ||
| 644 | |||
| 645 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | ||
| 646 | #define UNWIND_EXCEPTION_TYPE _Unwind_Control_Block | ||
| 647 | |||
| 648 | struct _Unwind_Control_Block { | ||
| 649 | uint64_t exclass; | ||
| 650 | uint32_t misc[20]; | ||
| 651 | }; | ||
| 652 | |||
| 653 | extern int _Unwind_RaiseException(_Unwind_Control_Block *); | ||
| 654 | extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); | ||
| 308 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); | 655 | 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 *); | 656 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); |
| 310 | 657 | ||
| @@ -320,120 +667,98 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |||
| 320 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); | 667 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); |
| 321 | } | 668 | } |
| 322 | 669 | ||
| 323 | #define _US_VIRTUAL_UNWIND_FRAME 0 | 670 | 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 | 671 | ||
| 328 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | 672 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ |
| 329 | LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | 673 | LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, |
| 674 | _Unwind_Context *ctx) | ||
| 330 | { | 675 | { |
| 331 | void *cf = (void *)_Unwind_GetGR(ctx, 13); | 676 | void *cf = (void *)_Unwind_GetGR(ctx, 13); |
| 332 | lua_State *L = cframe_L(cf); | 677 | lua_State *L = cframe_L(cf); |
| 333 | if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { | 678 | int errcode; |
| 334 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 679 | |
| 680 | switch ((state & _US_ACTION_MASK)) { | ||
| 681 | case _US_VIRTUAL_UNWIND_FRAME: | ||
| 682 | if ((state & _US_FORCE_UNWIND)) break; | ||
| 335 | return _URC_HANDLER_FOUND; | 683 | return _URC_HANDLER_FOUND; |
| 336 | } | 684 | case _US_UNWIND_FRAME_STARTING: |
| 337 | if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { | 685 | if (LJ_UEXCLASS_CHECK(ucb->exclass)) { |
| 338 | _Unwind_DeleteException(ucb); | 686 | errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); |
| 339 | _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); | 687 | } else { |
| 340 | _Unwind_SetGR(ctx, 0, (uint32_t)L); | 688 | errcode = LUA_ERRRUN; |
| 341 | _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN); | 689 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
| 690 | } | ||
| 691 | cf = err_unwind(L, cf, errcode); | ||
| 692 | if ((state & _US_FORCE_UNWIND) || cf == NULL) break; | ||
| 693 | _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); | ||
| 694 | _Unwind_SetGR(ctx, 0, (uint32_t)ucb); | ||
| 695 | _Unwind_SetGR(ctx, 1, (uint32_t)errcode); | ||
| 696 | _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? | ||
| 697 | (uint32_t)lj_vm_unwind_ff_eh : | ||
| 698 | (uint32_t)lj_vm_unwind_c_eh); | ||
| 342 | return _URC_INSTALL_CONTEXT; | 699 | return _URC_INSTALL_CONTEXT; |
| 700 | default: | ||
| 701 | return _URC_FAILURE; | ||
| 343 | } | 702 | } |
| 344 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 703 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
| 345 | return _URC_FAILURE; | 704 | return _URC_FAILURE; |
| 705 | #ifdef LUA_USE_ASSERT | ||
| 706 | /* We should never get here unless this is a forced unwind aka backtrace. */ | ||
| 707 | if (_Unwind_GetGR(ctx, 0) == 0xff33aa77) { | ||
| 708 | _Unwind_SetGR(ctx, 0, 0xff33aa88); | ||
| 709 | } | ||
| 710 | #endif | ||
| 346 | return _URC_CONTINUE_UNWIND; | 711 | return _URC_CONTINUE_UNWIND; |
| 347 | } | 712 | } |
| 348 | 713 | ||
| 349 | #endif | 714 | #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) |
| 715 | typedef int (*_Unwind_Trace_Fn)(_Unwind_Context *, void *); | ||
| 716 | extern int _Unwind_Backtrace(_Unwind_Trace_Fn, void *); | ||
| 350 | 717 | ||
| 351 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 718 | static int err_verify_bt(_Unwind_Context *ctx, int *got) |
| 719 | { | ||
| 720 | if (_Unwind_GetGR(ctx, 0) == 0xff33aa88) { *got = 2; } | ||
| 721 | else if (*got == 0) { *got = 1; _Unwind_SetGR(ctx, 0, 0xff33aa77); } | ||
| 722 | return _URC_OK; | ||
| 723 | } | ||
| 724 | |||
| 725 | /* Verify that external error handling actually has a chance to work. */ | ||
| 726 | void lj_err_verify(void) | ||
| 727 | { | ||
| 728 | int got = 0; | ||
| 729 | _Unwind_Backtrace((_Unwind_Trace_Fn)err_verify_bt, &got); | ||
| 730 | lj_assertX(got == 2, "broken build: external frame unwinding enabled, but missing -funwind-tables"); | ||
| 731 | } | ||
| 732 | #endif | ||
| 352 | 733 | ||
| 353 | /* | 734 | /* |
| 354 | ** Someone in Redmond owes me several days of my life. A lot of this is | 735 | ** 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 | ** | 736 | ** |
| 360 | ** Apparently MSVC doesn't call C++ destructors for foreign exceptions | 737 | ** The quirky ARM unwind API doesn't have __register_frame(). |
| 361 | ** unless you compile your C++ code with /EHa. Unfortunately this means | 738 | ** A potential workaround might involve _Unwind_Backtrace. |
| 362 | ** catch (...) also catches things like access violations. The use of | 739 | ** 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. | 740 | ** since they are built without unwind tables by default. |
| 364 | */ | 741 | */ |
| 365 | 742 | ||
| 366 | #define WIN32_LEAN_AND_MEAN | 743 | #endif /* LJ_TARGET_ARM */ |
| 367 | #include <windows.h> | ||
| 368 | 744 | ||
| 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 | #define LJ_MSVC_EXCODE ((DWORD)0xe06d7363) | ||
| 388 | #define LJ_GCC_EXCODE ((DWORD)0x20474343) | ||
| 389 | 745 | ||
| 390 | #define LJ_EXCODE ((DWORD)0xe24c4a00) | 746 | #if LJ_UNWIND_EXT |
| 391 | #define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) | 747 | static __thread struct { |
| 392 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | 748 | UNWIND_EXCEPTION_TYPE ex; |
| 393 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) | 749 | global_State *g; |
| 750 | } static_uex; | ||
| 394 | 751 | ||
| 395 | /* Win64 exception handler for interpreter frame. */ | 752 | /* Raise external exception. */ |
| 396 | LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | 753 | static void err_raise_ext(global_State *g, int errcode) |
| 397 | void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) | ||
| 398 | { | 754 | { |
| 399 | lua_State *L = cframe_L(cf); | 755 | memset(&static_uex, 0, sizeof(static_uex)); |
| 400 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? | 756 | static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode); |
| 401 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; | 757 | static_uex.g = g; |
| 402 | if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */ | 758 | _Unwind_RaiseException(&static_uex.ex); |
| 403 | /* Unwind internal frames. */ | ||
| 404 | err_unwind(L, cf, errcode); | ||
| 405 | } else { | ||
| 406 | void *cf2 = err_unwind(L, cf, 0); | ||
| 407 | if (cf2) { /* We catch it, so start unwinding the upper frames. */ | ||
| 408 | if (rec->ExceptionCode == LJ_MSVC_EXCODE || | ||
| 409 | rec->ExceptionCode == LJ_GCC_EXCODE) { | ||
| 410 | #if LJ_TARGET_WINDOWS | ||
| 411 | __DestructExceptionObject(rec, 1); | ||
| 412 | #endif | ||
| 413 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | ||
| 414 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { | ||
| 415 | /* Don't catch access violations etc. */ | ||
| 416 | return ExceptionContinueSearch; | ||
| 417 | } | ||
| 418 | /* Unwind the stack and call all handlers for all lower C frames | ||
| 419 | ** (including ourselves) again with EH_UNWINDING set. Then set | ||
| 420 | ** rsp = cf, rax = errcode and jump to the specified target. | ||
| 421 | */ | ||
| 422 | RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
| 423 | lj_vm_unwind_ff_eh : | ||
| 424 | lj_vm_unwind_c_eh), | ||
| 425 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); | ||
| 426 | /* RtlUnwindEx should never return. */ | ||
| 427 | } | ||
| 428 | } | ||
| 429 | return ExceptionContinueSearch; | ||
| 430 | } | 759 | } |
| 431 | 760 | ||
| 432 | /* Raise Windows exception. */ | 761 | #endif |
| 433 | static void err_raise_ext(int errcode) | ||
| 434 | { | ||
| 435 | RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); | ||
| 436 | } | ||
| 437 | 762 | ||
| 438 | #endif | 763 | #endif |
| 439 | 764 | ||
| @@ -444,22 +769,23 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) | |||
| 444 | { | 769 | { |
| 445 | global_State *g = G(L); | 770 | global_State *g = G(L); |
| 446 | lj_trace_abort(g); | 771 | lj_trace_abort(g); |
| 447 | setgcrefnull(g->jit_L); | 772 | L->status = LUA_OK; |
| 448 | L->status = 0; | ||
| 449 | #if LJ_UNWIND_EXT | 773 | #if LJ_UNWIND_EXT |
| 450 | err_raise_ext(errcode); | 774 | err_raise_ext(g, errcode); |
| 451 | /* | 775 | /* |
| 452 | ** A return from this function signals a corrupt C stack that cannot be | 776 | ** A return from this function signals a corrupt C stack that cannot be |
| 453 | ** unwound. We have no choice but to call the panic function and exit. | 777 | ** unwound. We have no choice but to call the panic function and exit. |
| 454 | ** | 778 | ** |
| 455 | ** Usually this is caused by a C function without unwind information. | 779 | ** Usually this is caused by a C function without unwind information. |
| 456 | ** This should never happen on x64, but may happen if you've manually | 780 | ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL |
| 457 | ** enabled LUAJIT_UNWIND_EXTERNAL and forgot to recompile *every* | 781 | ** and forgot to recompile *every* non-C++ file with -funwind-tables. |
| 458 | ** non-C++ file with -funwind-tables. | ||
| 459 | */ | 782 | */ |
| 460 | if (G(L)->panic) | 783 | if (G(L)->panic) |
| 461 | G(L)->panic(L); | 784 | G(L)->panic(L); |
| 462 | #else | 785 | #else |
| 786 | #if LJ_HASJIT | ||
| 787 | setmref(g->jit_base, NULL); | ||
| 788 | #endif | ||
| 463 | { | 789 | { |
| 464 | void *cf = err_unwind(L, NULL, errcode); | 790 | void *cf = err_unwind(L, NULL, errcode); |
| 465 | if (cframe_unwind_ff(cf)) | 791 | if (cframe_unwind_ff(cf)) |
| @@ -477,17 +803,29 @@ LJ_NOINLINE GCstr *lj_err_str(lua_State *L, ErrMsg em) | |||
| 477 | return lj_str_newz(L, err2msg(em)); | 803 | return lj_str_newz(L, err2msg(em)); |
| 478 | } | 804 | } |
| 479 | 805 | ||
| 806 | LJ_NORET LJ_NOINLINE static void lj_err_err(lua_State *L) | ||
| 807 | { | ||
| 808 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRERR)); | ||
| 809 | lj_err_throw(L, LUA_ERRERR); | ||
| 810 | } | ||
| 811 | |||
| 480 | /* Out-of-memory error. */ | 812 | /* Out-of-memory error. */ |
| 481 | LJ_NOINLINE void lj_err_mem(lua_State *L) | 813 | LJ_NOINLINE void lj_err_mem(lua_State *L) |
| 482 | { | 814 | { |
| 815 | if (L->status == LUA_ERRERR) | ||
| 816 | lj_err_err(L); | ||
| 483 | if (L->status == LUA_ERRERR+1) /* Don't touch the stack during lua_open. */ | 817 | if (L->status == LUA_ERRERR+1) /* Don't touch the stack during lua_open. */ |
| 484 | lj_vm_unwind_c(L->cframe, LUA_ERRMEM); | 818 | lj_vm_unwind_c(L->cframe, LUA_ERRMEM); |
| 819 | if (LJ_HASJIT) { | ||
| 820 | TValue *base = tvref(G(L)->jit_base); | ||
| 821 | if (base) L->base = base; | ||
| 822 | } | ||
| 485 | if (curr_funcisL(L)) { | 823 | if (curr_funcisL(L)) { |
| 486 | L->top = curr_topL(L); | 824 | L->top = curr_topL(L); |
| 487 | if (LJ_UNLIKELY(L->top > tvref(L->maxstack))) { | 825 | if (LJ_UNLIKELY(L->top > tvref(L->maxstack))) { |
| 488 | /* The current Lua frame violates the stack. Replace it with a dummy. */ | 826 | /* The current Lua frame violates the stack. Replace it with a dummy. */ |
| 489 | L->top = L->base; | 827 | L->top = L->base; |
| 490 | setframe_gc(L->base - 1, obj2gco(L)); | 828 | setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD); |
| 491 | } | 829 | } |
| 492 | } | 830 | } |
| 493 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM)); | 831 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM)); |
| @@ -497,7 +835,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) | |||
| 497 | /* Find error function for runtime errors. Requires an extra stack traversal. */ | 835 | /* Find error function for runtime errors. Requires an extra stack traversal. */ |
| 498 | static ptrdiff_t finderrfunc(lua_State *L) | 836 | static ptrdiff_t finderrfunc(lua_State *L) |
| 499 | { | 837 | { |
| 500 | cTValue *frame = L->base-1, *bot = tvref(L->stack); | 838 | cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; |
| 501 | void *cf = L->cframe; | 839 | void *cf = L->cframe; |
| 502 | while (frame > bot && cf) { | 840 | while (frame > bot && cf) { |
| 503 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ | 841 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ |
| @@ -521,10 +859,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
| 521 | frame = frame_prevd(frame); | 859 | frame = frame_prevd(frame); |
| 522 | break; | 860 | break; |
| 523 | case FRAME_CONT: | 861 | case FRAME_CONT: |
| 524 | #if LJ_HASFFI | 862 | if (frame_iscont_fficb(frame)) |
| 525 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
| 526 | cf = cframe_prev(cf); | 863 | cf = cframe_prev(cf); |
| 527 | #endif | ||
| 528 | frame = frame_prevd(frame); | 864 | frame = frame_prevd(frame); |
| 529 | break; | 865 | break; |
| 530 | case FRAME_CP: | 866 | case FRAME_CP: |
| @@ -536,11 +872,11 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
| 536 | break; | 872 | break; |
| 537 | case FRAME_PCALL: | 873 | case FRAME_PCALL: |
| 538 | case FRAME_PCALLH: | 874 | case FRAME_PCALLH: |
| 539 | if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ | 875 | if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) |
| 540 | return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ | 876 | return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ |
| 541 | return 0; | 877 | return 0; |
| 542 | default: | 878 | default: |
| 543 | lua_assert(0); | 879 | lj_assertL(0, "bad frame type"); |
| 544 | return 0; | 880 | return 0; |
| 545 | } | 881 | } |
| 546 | } | 882 | } |
| @@ -550,7 +886,7 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
| 550 | /* Runtime error. */ | 886 | /* Runtime error. */ |
| 551 | LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | 887 | LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) |
| 552 | { | 888 | { |
| 553 | ptrdiff_t ef = finderrfunc(L); | 889 | ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L); |
| 554 | if (ef) { | 890 | if (ef) { |
| 555 | TValue *errfunc, *top; | 891 | TValue *errfunc, *top; |
| 556 | lj_state_checkstack(L, LUA_MINSTACK * 2); /* Might raise new error. */ | 892 | lj_state_checkstack(L, LUA_MINSTACK * 2); /* Might raise new error. */ |
| @@ -562,8 +898,9 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | |||
| 562 | lj_err_throw(L, LUA_ERRERR); | 898 | lj_err_throw(L, LUA_ERRERR); |
| 563 | } | 899 | } |
| 564 | L->status = LUA_ERRERR; | 900 | L->status = LUA_ERRERR; |
| 565 | copyTV(L, top, top-1); | 901 | copyTV(L, top+LJ_FR2, top-1); |
| 566 | copyTV(L, top-1, errfunc); | 902 | copyTV(L, top-1, errfunc); |
| 903 | if (LJ_FR2) setnilV(top++); | ||
| 567 | L->top = top+1; | 904 | L->top = top+1; |
| 568 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ | 905 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ |
| 569 | } | 906 | } |
| @@ -573,18 +910,35 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | |||
| 573 | /* Stack overflow error. */ | 910 | /* Stack overflow error. */ |
| 574 | void LJ_FASTCALL lj_err_stkov(lua_State *L) | 911 | void LJ_FASTCALL lj_err_stkov(lua_State *L) |
| 575 | { | 912 | { |
| 913 | if (L->status == LUA_ERRERR) | ||
| 914 | lj_err_err(L); | ||
| 576 | lj_debug_addloc(L, err2msg(LJ_ERR_STKOV), L->base-1, NULL); | 915 | lj_debug_addloc(L, err2msg(LJ_ERR_STKOV), L->base-1, NULL); |
| 577 | lj_err_run(L); | 916 | lj_err_run(L); |
| 578 | } | 917 | } |
| 579 | 918 | ||
| 919 | #if LJ_HASJIT | ||
| 920 | /* Rethrow error after doing a trace exit. */ | ||
| 921 | LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode) | ||
| 922 | { | ||
| 923 | if (errcode == LUA_ERRRUN) | ||
| 924 | lj_err_run(L); | ||
| 925 | else | ||
| 926 | lj_err_throw(L, errcode); | ||
| 927 | } | ||
| 928 | #endif | ||
| 929 | |||
| 580 | /* Formatted runtime error message. */ | 930 | /* Formatted runtime error message. */ |
| 581 | LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | 931 | LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) |
| 582 | { | 932 | { |
| 583 | const char *msg; | 933 | const char *msg; |
| 584 | va_list argp; | 934 | va_list argp; |
| 585 | va_start(argp, em); | 935 | va_start(argp, em); |
| 936 | if (LJ_HASJIT) { | ||
| 937 | TValue *base = tvref(G(L)->jit_base); | ||
| 938 | if (base) L->base = base; | ||
| 939 | } | ||
| 586 | if (curr_funcisL(L)) L->top = curr_topL(L); | 940 | if (curr_funcisL(L)) L->top = curr_topL(L); |
| 587 | msg = lj_str_pushvf(L, err2msg(em), argp); | 941 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
| 588 | va_end(argp); | 942 | va_end(argp); |
| 589 | lj_debug_addloc(L, msg, L->base-1, NULL); | 943 | lj_debug_addloc(L, msg, L->base-1, NULL); |
| 590 | lj_err_run(L); | 944 | lj_err_run(L); |
| @@ -602,11 +956,11 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | |||
| 602 | { | 956 | { |
| 603 | char buff[LUA_IDSIZE]; | 957 | char buff[LUA_IDSIZE]; |
| 604 | const char *msg; | 958 | const char *msg; |
| 605 | lj_debug_shortname(buff, src); | 959 | lj_debug_shortname(buff, src, line); |
| 606 | msg = lj_str_pushvf(L, err2msg(em), argp); | 960 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
| 607 | msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); | 961 | msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg); |
| 608 | if (tok) | 962 | if (tok) |
| 609 | lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); | 963 | lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); |
| 610 | lj_err_throw(L, LUA_ERRSYNTAX); | 964 | lj_err_throw(L, LUA_ERRSYNTAX); |
| 611 | } | 965 | } |
| 612 | 966 | ||
| @@ -645,8 +999,9 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
| 645 | const BCIns *pc = cframe_Lpc(L); | 999 | const BCIns *pc = cframe_Lpc(L); |
| 646 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { | 1000 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { |
| 647 | const char *tname = lj_typename(o); | 1001 | const char *tname = lj_typename(o); |
| 1002 | setframe_gc(o, obj2gco(L), LJ_TTHREAD); | ||
| 1003 | if (LJ_FR2) o++; | ||
| 648 | setframe_pc(o, pc); | 1004 | setframe_pc(o, pc); |
| 649 | setframe_gc(o, obj2gco(L)); | ||
| 650 | L->top = L->base = o+1; | 1005 | L->top = L->base = o+1; |
| 651 | err_msgv(L, LJ_ERR_BADCALL, tname); | 1006 | err_msgv(L, LJ_ERR_BADCALL, tname); |
| 652 | } | 1007 | } |
| @@ -656,28 +1011,27 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
| 656 | /* Error in context of caller. */ | 1011 | /* Error in context of caller. */ |
| 657 | LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) | 1012 | LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) |
| 658 | { | 1013 | { |
| 659 | TValue *frame = L->base-1; | 1014 | TValue *frame = NULL, *pframe = NULL; |
| 660 | TValue *pframe = NULL; | 1015 | if (!(LJ_HASJIT && tvref(G(L)->jit_base))) { |
| 661 | if (frame_islua(frame)) { | 1016 | frame = L->base-1; |
| 662 | pframe = frame_prevl(frame); | 1017 | if (frame_islua(frame)) { |
| 663 | } else if (frame_iscont(frame)) { | 1018 | pframe = frame_prevl(frame); |
| 1019 | } else if (frame_iscont(frame)) { | ||
| 1020 | if (frame_iscont_fficb(frame)) { | ||
| 1021 | pframe = frame; | ||
| 1022 | frame = NULL; | ||
| 1023 | } else { | ||
| 1024 | pframe = frame_prevd(frame); | ||
| 664 | #if LJ_HASFFI | 1025 | #if LJ_HASFFI |
| 665 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) { | 1026 | /* Remove frame for FFI metamethods. */ |
| 666 | pframe = frame; | 1027 | if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && |
| 667 | frame = NULL; | 1028 | frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { |
| 668 | } else | 1029 | L->base = pframe+1; |
| 1030 | L->top = frame; | ||
| 1031 | setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); | ||
| 1032 | } | ||
| 669 | #endif | 1033 | #endif |
| 670 | { | ||
| 671 | pframe = frame_prevd(frame); | ||
| 672 | #if LJ_HASFFI | ||
| 673 | /* Remove frame for FFI metamethods. */ | ||
| 674 | if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && | ||
| 675 | frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { | ||
| 676 | L->base = pframe+1; | ||
| 677 | L->top = frame; | ||
| 678 | setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); | ||
| 679 | } | 1034 | } |
| 680 | #endif | ||
| 681 | } | 1035 | } |
| 682 | } | 1036 | } |
| 683 | lj_debug_addloc(L, msg, pframe, frame); | 1037 | lj_debug_addloc(L, msg, pframe, frame); |
| @@ -690,7 +1044,7 @@ LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...) | |||
| 690 | const char *msg; | 1044 | const char *msg; |
| 691 | va_list argp; | 1045 | va_list argp; |
| 692 | va_start(argp, em); | 1046 | va_start(argp, em); |
| 693 | msg = lj_str_pushvf(L, err2msg(em), argp); | 1047 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
| 694 | va_end(argp); | 1048 | va_end(argp); |
| 695 | lj_err_callermsg(L, msg); | 1049 | lj_err_callermsg(L, msg); |
| 696 | } | 1050 | } |
| @@ -710,9 +1064,9 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg, | |||
| 710 | if (narg < 0 && narg > LUA_REGISTRYINDEX) | 1064 | if (narg < 0 && narg > LUA_REGISTRYINDEX) |
| 711 | narg = (int)(L->top - L->base) + narg + 1; | 1065 | narg = (int)(L->top - L->base) + narg + 1; |
| 712 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ | 1066 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ |
| 713 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); | 1067 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); |
| 714 | else | 1068 | else |
| 715 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); | 1069 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); |
| 716 | lj_err_callermsg(L, msg); | 1070 | lj_err_callermsg(L, msg); |
| 717 | } | 1071 | } |
| 718 | 1072 | ||
| @@ -722,7 +1076,7 @@ LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...) | |||
| 722 | const char *msg; | 1076 | const char *msg; |
| 723 | va_list argp; | 1077 | va_list argp; |
| 724 | va_start(argp, em); | 1078 | va_start(argp, em); |
| 725 | msg = lj_str_pushvf(L, err2msg(em), argp); | 1079 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
| 726 | va_end(argp); | 1080 | va_end(argp); |
| 727 | err_argmsg(L, narg, msg); | 1081 | err_argmsg(L, narg, msg); |
| 728 | } | 1082 | } |
| @@ -752,7 +1106,7 @@ LJ_NOINLINE void lj_err_argtype(lua_State *L, int narg, const char *xname) | |||
| 752 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; | 1106 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; |
| 753 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; | 1107 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; |
| 754 | } | 1108 | } |
| 755 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); | 1109 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); |
| 756 | err_argmsg(L, narg, msg); | 1110 | err_argmsg(L, narg, msg); |
| 757 | } | 1111 | } |
| 758 | 1112 | ||
| @@ -802,7 +1156,7 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) | |||
| 802 | const char *msg; | 1156 | const char *msg; |
| 803 | va_list argp; | 1157 | va_list argp; |
| 804 | va_start(argp, fmt); | 1158 | va_start(argp, fmt); |
| 805 | msg = lj_str_pushvf(L, fmt, argp); | 1159 | msg = lj_strfmt_pushvf(L, fmt, argp); |
| 806 | va_end(argp); | 1160 | va_end(argp); |
| 807 | lj_err_callermsg(L, msg); | 1161 | lj_err_callermsg(L, msg); |
| 808 | return 0; /* unreachable */ | 1162 | return 0; /* unreachable */ |
