Mercurial
comparison third_party/luajit/src/lj_err.c @ 186:8cf4ec5e2191 hg-web
Fixed merge conflict.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 23 Jan 2026 22:38:59 -0800 |
| parents | 94705b5986b3 |
| children |
comparison
equal
deleted
inserted
replaced
| 176:fed99fc04e12 | 186:8cf4ec5e2191 |
|---|---|
| 1 /* | |
| 2 ** Error handling. | |
| 3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | |
| 4 */ | |
| 5 | |
| 6 #define lj_err_c | |
| 7 #define LUA_CORE | |
| 8 | |
| 9 #include "lj_obj.h" | |
| 10 #include "lj_err.h" | |
| 11 #include "lj_debug.h" | |
| 12 #include "lj_str.h" | |
| 13 #include "lj_func.h" | |
| 14 #include "lj_state.h" | |
| 15 #include "lj_frame.h" | |
| 16 #include "lj_ff.h" | |
| 17 #include "lj_trace.h" | |
| 18 #include "lj_vm.h" | |
| 19 #include "lj_strfmt.h" | |
| 20 | |
| 21 /* | |
| 22 ** LuaJIT can either use internal or external frame unwinding: | |
| 23 ** | |
| 24 ** - Internal frame unwinding (INT) is free-standing and doesn't require | |
| 25 ** any OS or library support. | |
| 26 ** | |
| 27 ** - External frame unwinding (EXT) uses the system-provided unwind handler. | |
| 28 ** | |
| 29 ** Pros and Cons: | |
| 30 ** | |
| 31 ** - EXT requires unwind tables for *all* functions on the C stack between | |
| 32 ** the pcall/catch and the error/throw. C modules used by Lua code can | |
| 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. | |
| 36 ** | |
| 37 ** - INT is faster when actually throwing errors, but this happens rarely. | |
| 38 ** Setting up error handlers is zero-cost in any case. | |
| 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 ** | |
| 44 ** - EXT provides full interoperability with C++ exceptions. You can throw | |
| 45 ** Lua errors or C++ exceptions through a mix of Lua frames and C++ frames. | |
| 46 ** C++ destructors are called as needed. C++ exceptions caught by pcall | |
| 47 ** are converted to the string "C++ exception". Lua errors can be caught | |
| 48 ** with catch (...) in C++. | |
| 49 ** | |
| 50 ** - INT has only limited support for automatically catching C++ exceptions | |
| 51 ** on POSIX systems using DWARF2 stack unwinding. Other systems may use | |
| 52 ** the wrapper function feature. Lua errors thrown through C++ frames | |
| 53 ** cannot be caught by C++ code and C++ destructors are not run. | |
| 54 ** | |
| 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": | |
| 75 ** | |
| 76 ** luajit -e "print(select(2, load('OK')):match('OK'))" | |
| 77 ** | |
| 78 ** (*) Originally, toolchains only generated unwind tables for C++ code. For | |
| 79 ** interoperability reasons, this can be manually enabled for plain C code, | |
| 80 ** too (with -funwind-tables). With the introduction of the x64 architecture, | |
| 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. | |
| 85 */ | |
| 86 | |
| 87 /* -- Error messages ------------------------------------------------------ */ | |
| 88 | |
| 89 /* Error message strings. */ | |
| 90 LJ_DATADEF const char *lj_err_allmsg = | |
| 91 #define ERRDEF(name, msg) msg "\0" | |
| 92 #include "lj_errmsg.h" | |
| 93 ; | |
| 94 | |
| 95 /* -- Internal frame unwinding -------------------------------------------- */ | |
| 96 | |
| 97 /* Unwind Lua stack and move error message to new top. */ | |
| 98 LJ_NOINLINE static void unwindstack(lua_State *L, TValue *top) | |
| 99 { | |
| 100 lj_func_closeuv(L, top); | |
| 101 if (top < L->top-1) { | |
| 102 copyTV(L, top, L->top-1); | |
| 103 L->top = top+1; | |
| 104 } | |
| 105 lj_state_relimitstack(L); | |
| 106 } | |
| 107 | |
| 108 /* Unwind until stop frame. Optionally cleanup frames. */ | |
| 109 static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |
| 110 { | |
| 111 TValue *frame = L->base-1; | |
| 112 void *cf = L->cframe; | |
| 113 while (cf) { | |
| 114 int32_t nres = cframe_nres(cframe_raw(cf)); | |
| 115 if (nres < 0) { /* C frame without Lua frame? */ | |
| 116 TValue *top = restorestack(L, -nres); | |
| 117 if (frame < top) { /* Frame reached? */ | |
| 118 if (errcode) { | |
| 119 L->base = frame+1; | |
| 120 L->cframe = cframe_prev(cf); | |
| 121 unwindstack(L, top); | |
| 122 } | |
| 123 return cf; | |
| 124 } | |
| 125 } | |
| 126 if (frame <= tvref(L->stack)+LJ_FR2) | |
| 127 break; | |
| 128 switch (frame_typep(frame)) { | |
| 129 case FRAME_LUA: /* Lua frame. */ | |
| 130 case FRAME_LUAP: | |
| 131 frame = frame_prevl(frame); | |
| 132 break; | |
| 133 case FRAME_C: /* C frame. */ | |
| 134 unwind_c: | |
| 135 #if LJ_UNWIND_EXT | |
| 136 if (errcode) { | |
| 137 L->base = frame_prevd(frame) + 1; | |
| 138 L->cframe = cframe_prev(cf); | |
| 139 unwindstack(L, frame - LJ_FR2); | |
| 140 } else if (cf != stopcf) { | |
| 141 cf = cframe_prev(cf); | |
| 142 frame = frame_prevd(frame); | |
| 143 break; | |
| 144 } | |
| 145 return NULL; /* Continue unwinding. */ | |
| 146 #else | |
| 147 UNUSED(stopcf); | |
| 148 cf = cframe_prev(cf); | |
| 149 frame = frame_prevd(frame); | |
| 150 break; | |
| 151 #endif | |
| 152 case FRAME_CP: /* Protected C frame. */ | |
| 153 if (cframe_canyield(cf)) { /* Resume? */ | |
| 154 if (errcode) { | |
| 155 hook_leave(G(L)); /* Assumes nobody uses coroutines inside hooks. */ | |
| 156 L->cframe = NULL; | |
| 157 L->status = (uint8_t)errcode; | |
| 158 } | |
| 159 return cf; | |
| 160 } | |
| 161 if (errcode) { | |
| 162 L->base = frame_prevd(frame) + 1; | |
| 163 L->cframe = cframe_prev(cf); | |
| 164 unwindstack(L, frame - LJ_FR2); | |
| 165 } | |
| 166 return cf; | |
| 167 case FRAME_CONT: /* Continuation frame. */ | |
| 168 if (frame_iscont_fficb(frame)) | |
| 169 goto unwind_c; | |
| 170 /* fallthrough */ | |
| 171 case FRAME_VARG: /* Vararg frame. */ | |
| 172 frame = frame_prevd(frame); | |
| 173 break; | |
| 174 case FRAME_PCALL: /* FF pcall() frame. */ | |
| 175 case FRAME_PCALLH: /* FF pcall() frame inside hook. */ | |
| 176 if (errcode) { | |
| 177 if (errcode == LUA_YIELD) { | |
| 178 frame = frame_prevd(frame); | |
| 179 break; | |
| 180 } | |
| 181 if (frame_typep(frame) == FRAME_PCALL) | |
| 182 hook_leave(G(L)); | |
| 183 L->base = frame_prevd(frame) + 1; | |
| 184 L->cframe = cf; | |
| 185 unwindstack(L, L->base); | |
| 186 } | |
| 187 return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); | |
| 188 } | |
| 189 } | |
| 190 /* No C frame. */ | |
| 191 if (errcode) { | |
| 192 L->base = tvref(L->stack)+1+LJ_FR2; | |
| 193 L->cframe = NULL; | |
| 194 unwindstack(L, L->base); | |
| 195 if (G(L)->panic) | |
| 196 G(L)->panic(L); | |
| 197 exit(EXIT_FAILURE); | |
| 198 } | |
| 199 return L; /* Anything non-NULL will do. */ | |
| 200 } | |
| 201 | |
| 202 /* -- External frame unwinding -------------------------------------------- */ | |
| 203 | |
| 204 #if LJ_ABI_WIN | |
| 205 | |
| 206 /* | |
| 207 ** Someone in Redmond owes me several days of my life. A lot of this is | |
| 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. | |
| 217 */ | |
| 218 | |
| 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) | |
| 261 { | |
| 262 #if LJ_TARGET_X86 | |
| 263 void *cf = (char *)f - CFRAME_OFS_SEH; | |
| 264 #else | |
| 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 DWORD64 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), (uintptr_t)(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 */ | |
| 375 | |
| 376 typedef struct _Unwind_Context _Unwind_Context; | |
| 377 | |
| 378 #define _URC_OK 0 | |
| 379 #define _URC_FATAL_PHASE2_ERROR 2 | |
| 380 #define _URC_FATAL_PHASE1_ERROR 3 | |
| 381 #define _URC_HANDLER_FOUND 6 | |
| 382 #define _URC_INSTALL_CONTEXT 7 | |
| 383 #define _URC_CONTINUE_UNWIND 8 | |
| 384 #define _URC_FAILURE 9 | |
| 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 | |
| 391 #if !LJ_TARGET_ARM | |
| 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 | |
| 401 extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | |
| 402 extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | |
| 403 extern uintptr_t _Unwind_GetIP(_Unwind_Context *); | |
| 404 extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | |
| 405 extern void _Unwind_DeleteException(_Unwind_Exception *); | |
| 406 extern int _Unwind_RaiseException(_Unwind_Exception *); | |
| 407 | |
| 408 #define _UA_SEARCH_PHASE 1 | |
| 409 #define _UA_CLEANUP_PHASE 2 | |
| 410 #define _UA_HANDLER_FRAME 4 | |
| 411 #define _UA_FORCE_UNWIND 8 | |
| 412 | |
| 413 /* DWARF2 personality handler referenced from interpreter .eh_frame. */ | |
| 414 LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | |
| 415 uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | |
| 416 { | |
| 417 void *cf; | |
| 418 lua_State *L; | |
| 419 if (version != 1) | |
| 420 return _URC_FATAL_PHASE1_ERROR; | |
| 421 cf = (void *)_Unwind_GetCFA(ctx); | |
| 422 L = cframe_L(cf); | |
| 423 if ((actions & _UA_SEARCH_PHASE)) { | |
| 424 #if LJ_UNWIND_EXT | |
| 425 if (err_unwind(L, cf, 0) == NULL) | |
| 426 return _URC_CONTINUE_UNWIND; | |
| 427 #endif | |
| 428 if (!LJ_UEXCLASS_CHECK(uexclass)) { | |
| 429 setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | |
| 430 } | |
| 431 return _URC_HANDLER_FOUND; | |
| 432 } | |
| 433 if ((actions & _UA_CLEANUP_PHASE)) { | |
| 434 int errcode; | |
| 435 if (LJ_UEXCLASS_CHECK(uexclass)) { | |
| 436 errcode = LJ_UEXCLASS_ERRCODE(uexclass); | |
| 437 } else { | |
| 438 if ((actions & _UA_HANDLER_FRAME)) | |
| 439 _Unwind_DeleteException(uex); | |
| 440 errcode = LUA_ERRRUN; | |
| 441 } | |
| 442 #if LJ_UNWIND_EXT | |
| 443 cf = err_unwind(L, cf, errcode); | |
| 444 if ((actions & _UA_FORCE_UNWIND)) { | |
| 445 return _URC_CONTINUE_UNWIND; | |
| 446 } else if (cf) { | |
| 447 ASMFunction ip; | |
| 448 _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode); | |
| 449 ip = cframe_unwind_ff(cf) ? lj_vm_unwind_ff_eh : lj_vm_unwind_c_eh; | |
| 450 _Unwind_SetIP(ctx, (uintptr_t)lj_ptr_strip(ip)); | |
| 451 return _URC_INSTALL_CONTEXT; | |
| 452 } | |
| 453 #if LJ_TARGET_X86ORX64 | |
| 454 else if ((actions & _UA_HANDLER_FRAME)) { | |
| 455 /* Workaround for ancient libgcc bug. Still present in RHEL 5.5. :-/ | |
| 456 ** Real fix: http://gcc.gnu.org/viewcvs/trunk/gcc/unwind-dw2.c?r1=121165&r2=124837&pathrev=153877&diff_format=h | |
| 457 */ | |
| 458 _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode); | |
| 459 _Unwind_SetIP(ctx, (uintptr_t)lj_vm_unwind_rethrow); | |
| 460 return _URC_INSTALL_CONTEXT; | |
| 461 } | |
| 462 #endif | |
| 463 #else | |
| 464 /* This is not the proper way to escape from the unwinder. We get away with | |
| 465 ** it on non-x64 because the interpreter restores all callee-saved regs. | |
| 466 */ | |
| 467 lj_err_throw(L, errcode); | |
| 468 #if LJ_TARGET_X64 | |
| 469 #error "Broken build system -- only use the provided Makefiles!" | |
| 470 #endif | |
| 471 #endif | |
| 472 } | |
| 473 return _URC_CONTINUE_UNWIND; | |
| 474 } | |
| 475 | |
| 476 #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) | |
| 477 struct dwarf_eh_bases { void *tbase, *dbase, *func; }; | |
| 478 extern const void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases); | |
| 479 | |
| 480 /* Verify that external error handling actually has a chance to work. */ | |
| 481 void lj_err_verify(void) | |
| 482 { | |
| 483 #if !LJ_TARGET_OSX | |
| 484 /* Check disabled on MacOS due to brilliant software engineering at Apple. */ | |
| 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 */ | |
| 491 } | |
| 492 #endif | |
| 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 | |
| 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 ASMFunction handler = (ASMFunction)err_unwind_jit; | |
| 584 memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template)); | |
| 585 #if LJ_ABI_PAUTH | |
| 586 #if LJ_TARGET_ARM64 | |
| 587 handler = ptrauth_auth_and_resign(handler, | |
| 588 ptrauth_key_function_pointer, 0, | |
| 589 ptrauth_key_process_independent_code, info + ERR_FRAME_JIT_OFS_HANDLER); | |
| 590 #else | |
| 591 #error "missing pointer authentication support for this architecture" | |
| 592 #endif | |
| 593 #endif | |
| 594 memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler)); | |
| 595 *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) = | |
| 596 (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base)); | |
| 597 __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | |
| 598 #ifdef LUA_USE_ASSERT | |
| 599 { | |
| 600 struct dwarf_eh_bases ehb; | |
| 601 lj_assertX(_Unwind_Find_FDE(info + sizeof(err_frame_jit_template)+1, &ehb), | |
| 602 "bad JIT unwind table registration"); | |
| 603 } | |
| 604 #endif | |
| 605 return info + sizeof(err_frame_jit_template); | |
| 606 } | |
| 607 | |
| 608 void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info) | |
| 609 { | |
| 610 UNUSED(base); UNUSED(sz); | |
| 611 __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER); | |
| 612 } | |
| 613 #endif | |
| 614 | |
| 615 #else /* LJ_TARGET_ARM */ | |
| 616 | |
| 617 #define _US_VIRTUAL_UNWIND_FRAME 0 | |
| 618 #define _US_UNWIND_FRAME_STARTING 1 | |
| 619 #define _US_ACTION_MASK 3 | |
| 620 #define _US_FORCE_UNWIND 8 | |
| 621 | |
| 622 typedef struct _Unwind_Control_Block _Unwind_Control_Block; | |
| 623 #define UNWIND_EXCEPTION_TYPE _Unwind_Control_Block | |
| 624 | |
| 625 struct _Unwind_Control_Block { | |
| 626 uint64_t exclass; | |
| 627 uint32_t misc[20]; | |
| 628 }; | |
| 629 | |
| 630 extern int _Unwind_RaiseException(_Unwind_Control_Block *); | |
| 631 extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); | |
| 632 extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); | |
| 633 extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); | |
| 634 | |
| 635 static inline uint32_t _Unwind_GetGR(_Unwind_Context *ctx, int r) | |
| 636 { | |
| 637 uint32_t v; | |
| 638 _Unwind_VRS_Get(ctx, 0, r, 0, &v); | |
| 639 return v; | |
| 640 } | |
| 641 | |
| 642 static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |
| 643 { | |
| 644 _Unwind_VRS_Set(ctx, 0, r, 0, &v); | |
| 645 } | |
| 646 | |
| 647 extern void lj_vm_unwind_ext(void); | |
| 648 | |
| 649 /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | |
| 650 LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, | |
| 651 _Unwind_Context *ctx) | |
| 652 { | |
| 653 void *cf = (void *)_Unwind_GetGR(ctx, 13); | |
| 654 lua_State *L = cframe_L(cf); | |
| 655 int errcode; | |
| 656 | |
| 657 switch ((state & _US_ACTION_MASK)) { | |
| 658 case _US_VIRTUAL_UNWIND_FRAME: | |
| 659 if ((state & _US_FORCE_UNWIND)) break; | |
| 660 return _URC_HANDLER_FOUND; | |
| 661 case _US_UNWIND_FRAME_STARTING: | |
| 662 if (LJ_UEXCLASS_CHECK(ucb->exclass)) { | |
| 663 errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); | |
| 664 } else { | |
| 665 errcode = LUA_ERRRUN; | |
| 666 setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | |
| 667 } | |
| 668 cf = err_unwind(L, cf, errcode); | |
| 669 if ((state & _US_FORCE_UNWIND) || cf == NULL) break; | |
| 670 _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); | |
| 671 _Unwind_SetGR(ctx, 0, (uint32_t)ucb); | |
| 672 _Unwind_SetGR(ctx, 1, (uint32_t)errcode); | |
| 673 _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? | |
| 674 (uint32_t)lj_vm_unwind_ff_eh : | |
| 675 (uint32_t)lj_vm_unwind_c_eh); | |
| 676 return _URC_INSTALL_CONTEXT; | |
| 677 default: | |
| 678 return _URC_FAILURE; | |
| 679 } | |
| 680 if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | |
| 681 return _URC_FAILURE; | |
| 682 #ifdef LUA_USE_ASSERT | |
| 683 /* We should never get here unless this is a forced unwind aka backtrace. */ | |
| 684 if (_Unwind_GetGR(ctx, 0) == 0xff33aa77) { | |
| 685 _Unwind_SetGR(ctx, 0, 0xff33aa88); | |
| 686 } | |
| 687 #endif | |
| 688 return _URC_CONTINUE_UNWIND; | |
| 689 } | |
| 690 | |
| 691 #if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) | |
| 692 typedef int (*_Unwind_Trace_Fn)(_Unwind_Context *, void *); | |
| 693 extern int _Unwind_Backtrace(_Unwind_Trace_Fn, void *); | |
| 694 | |
| 695 static int err_verify_bt(_Unwind_Context *ctx, int *got) | |
| 696 { | |
| 697 if (_Unwind_GetGR(ctx, 0) == 0xff33aa88) { *got = 2; } | |
| 698 else if (*got == 0) { *got = 1; _Unwind_SetGR(ctx, 0, 0xff33aa77); } | |
| 699 return _URC_OK; | |
| 700 } | |
| 701 | |
| 702 /* Verify that external error handling actually has a chance to work. */ | |
| 703 void lj_err_verify(void) | |
| 704 { | |
| 705 int got = 0; | |
| 706 _Unwind_Backtrace((_Unwind_Trace_Fn)err_verify_bt, &got); | |
| 707 lj_assertX(got == 2, "broken build: external frame unwinding enabled, but missing -funwind-tables"); | |
| 708 } | |
| 709 #endif | |
| 710 | |
| 711 /* | |
| 712 ** Note: LJ_UNWIND_JIT is not implemented for 32 bit ARM. | |
| 713 ** | |
| 714 ** The quirky ARM unwind API doesn't have __register_frame(). | |
| 715 ** A potential workaround might involve _Unwind_Backtrace. | |
| 716 ** But most 32 bit ARM targets don't qualify for LJ_UNWIND_EXT, anyway, | |
| 717 ** since they are built without unwind tables by default. | |
| 718 */ | |
| 719 | |
| 720 #endif /* LJ_TARGET_ARM */ | |
| 721 | |
| 722 | |
| 723 #if LJ_UNWIND_EXT | |
| 724 static __thread struct { | |
| 725 UNWIND_EXCEPTION_TYPE ex; | |
| 726 global_State *g; | |
| 727 } static_uex; | |
| 728 | |
| 729 /* Raise external exception. */ | |
| 730 static void err_raise_ext(global_State *g, int errcode) | |
| 731 { | |
| 732 memset(&static_uex, 0, sizeof(static_uex)); | |
| 733 static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode); | |
| 734 static_uex.g = g; | |
| 735 _Unwind_RaiseException(&static_uex.ex); | |
| 736 } | |
| 737 | |
| 738 #endif | |
| 739 | |
| 740 #endif | |
| 741 | |
| 742 /* -- Error handling ------------------------------------------------------ */ | |
| 743 | |
| 744 /* Throw error. Find catch frame, unwind stack and continue. */ | |
| 745 LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) | |
| 746 { | |
| 747 global_State *g = G(L); | |
| 748 lj_trace_abort(g); | |
| 749 L->status = LUA_OK; | |
| 750 #if LJ_UNWIND_EXT | |
| 751 err_raise_ext(g, errcode); | |
| 752 /* | |
| 753 ** A return from this function signals a corrupt C stack that cannot be | |
| 754 ** unwound. We have no choice but to call the panic function and exit. | |
| 755 ** | |
| 756 ** Usually this is caused by a C function without unwind information. | |
| 757 ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL | |
| 758 ** and forgot to recompile *every* non-C++ file with -funwind-tables. | |
| 759 */ | |
| 760 if (G(L)->panic) | |
| 761 G(L)->panic(L); | |
| 762 #else | |
| 763 #if LJ_HASJIT | |
| 764 setmref(g->jit_base, NULL); | |
| 765 #endif | |
| 766 { | |
| 767 void *cf = err_unwind(L, NULL, errcode); | |
| 768 if (cframe_unwind_ff(cf)) | |
| 769 lj_vm_unwind_ff(cframe_raw(cf)); | |
| 770 else | |
| 771 lj_vm_unwind_c(cframe_raw(cf), errcode); | |
| 772 } | |
| 773 #endif | |
| 774 exit(EXIT_FAILURE); | |
| 775 } | |
| 776 | |
| 777 /* Return string object for error message. */ | |
| 778 LJ_NOINLINE GCstr *lj_err_str(lua_State *L, ErrMsg em) | |
| 779 { | |
| 780 return lj_str_newz(L, err2msg(em)); | |
| 781 } | |
| 782 | |
| 783 /* Out-of-memory error. */ | |
| 784 LJ_NOINLINE void lj_err_mem(lua_State *L) | |
| 785 { | |
| 786 if (L->status == LUA_ERRERR+1) /* Don't touch the stack during lua_open. */ | |
| 787 lj_vm_unwind_c(L->cframe, LUA_ERRMEM); | |
| 788 if (LJ_HASJIT) { | |
| 789 TValue *base = tvref(G(L)->jit_base); | |
| 790 if (base) L->base = base; | |
| 791 } | |
| 792 if (curr_funcisL(L)) L->top = curr_topL(L); | |
| 793 setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM)); | |
| 794 lj_err_throw(L, LUA_ERRMEM); | |
| 795 } | |
| 796 | |
| 797 /* Find error function for runtime errors. Requires an extra stack traversal. */ | |
| 798 static ptrdiff_t finderrfunc(lua_State *L) | |
| 799 { | |
| 800 cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; | |
| 801 void *cf = L->cframe; | |
| 802 while (frame > bot && cf) { | |
| 803 while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ | |
| 804 if (frame >= restorestack(L, -cframe_nres(cf))) | |
| 805 break; | |
| 806 if (cframe_errfunc(cf) >= 0) /* Error handler not inherited (-1)? */ | |
| 807 return cframe_errfunc(cf); | |
| 808 cf = cframe_prev(cf); /* Else unwind cframe and continue searching. */ | |
| 809 if (cf == NULL) | |
| 810 return 0; | |
| 811 } | |
| 812 switch (frame_typep(frame)) { | |
| 813 case FRAME_LUA: | |
| 814 case FRAME_LUAP: | |
| 815 frame = frame_prevl(frame); | |
| 816 break; | |
| 817 case FRAME_C: | |
| 818 cf = cframe_prev(cf); | |
| 819 /* fallthrough */ | |
| 820 case FRAME_VARG: | |
| 821 frame = frame_prevd(frame); | |
| 822 break; | |
| 823 case FRAME_CONT: | |
| 824 if (frame_iscont_fficb(frame)) | |
| 825 cf = cframe_prev(cf); | |
| 826 frame = frame_prevd(frame); | |
| 827 break; | |
| 828 case FRAME_CP: | |
| 829 if (cframe_canyield(cf)) return 0; | |
| 830 if (cframe_errfunc(cf) >= 0) | |
| 831 return cframe_errfunc(cf); | |
| 832 cf = cframe_prev(cf); | |
| 833 frame = frame_prevd(frame); | |
| 834 break; | |
| 835 case FRAME_PCALL: | |
| 836 case FRAME_PCALLH: | |
| 837 if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) | |
| 838 return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ | |
| 839 return 0; | |
| 840 default: | |
| 841 lj_assertL(0, "bad frame type"); | |
| 842 return 0; | |
| 843 } | |
| 844 } | |
| 845 return 0; | |
| 846 } | |
| 847 | |
| 848 /* Runtime error. */ | |
| 849 LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) | |
| 850 { | |
| 851 ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L); | |
| 852 if (ef) { | |
| 853 TValue *errfunc = restorestack(L, ef); | |
| 854 TValue *top = L->top; | |
| 855 lj_trace_abort(G(L)); | |
| 856 if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) { | |
| 857 setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR)); | |
| 858 lj_err_throw(L, LUA_ERRERR); | |
| 859 } | |
| 860 L->status = LUA_ERRERR; | |
| 861 copyTV(L, top+LJ_FR2, top-1); | |
| 862 copyTV(L, top-1, errfunc); | |
| 863 if (LJ_FR2) setnilV(top++); | |
| 864 L->top = top+1; | |
| 865 lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ | |
| 866 } | |
| 867 lj_err_throw(L, LUA_ERRRUN); | |
| 868 } | |
| 869 | |
| 870 #if LJ_HASJIT | |
| 871 LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode) | |
| 872 { | |
| 873 if (errcode == LUA_ERRRUN) | |
| 874 lj_err_run(L); | |
| 875 else | |
| 876 lj_err_throw(L, errcode); | |
| 877 } | |
| 878 #endif | |
| 879 | |
| 880 /* Formatted runtime error message. */ | |
| 881 LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | |
| 882 { | |
| 883 const char *msg; | |
| 884 va_list argp; | |
| 885 va_start(argp, em); | |
| 886 if (LJ_HASJIT) { | |
| 887 TValue *base = tvref(G(L)->jit_base); | |
| 888 if (base) L->base = base; | |
| 889 } | |
| 890 if (curr_funcisL(L)) L->top = curr_topL(L); | |
| 891 msg = lj_strfmt_pushvf(L, err2msg(em), argp); | |
| 892 va_end(argp); | |
| 893 lj_debug_addloc(L, msg, L->base-1, NULL); | |
| 894 lj_err_run(L); | |
| 895 } | |
| 896 | |
| 897 /* Non-vararg variant for better calling conventions. */ | |
| 898 LJ_NOINLINE void lj_err_msg(lua_State *L, ErrMsg em) | |
| 899 { | |
| 900 err_msgv(L, em); | |
| 901 } | |
| 902 | |
| 903 /* Lexer error. */ | |
| 904 LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | |
| 905 BCLine line, ErrMsg em, va_list argp) | |
| 906 { | |
| 907 char buff[LUA_IDSIZE]; | |
| 908 const char *msg; | |
| 909 lj_debug_shortname(buff, src, line); | |
| 910 msg = lj_strfmt_pushvf(L, err2msg(em), argp); | |
| 911 msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg); | |
| 912 if (tok) | |
| 913 lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); | |
| 914 lj_err_throw(L, LUA_ERRSYNTAX); | |
| 915 } | |
| 916 | |
| 917 /* Typecheck error for operands. */ | |
| 918 LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm) | |
| 919 { | |
| 920 const char *tname = lj_typename(o); | |
| 921 const char *opname = err2msg(opm); | |
| 922 if (curr_funcisL(L)) { | |
| 923 GCproto *pt = curr_proto(L); | |
| 924 const BCIns *pc = cframe_Lpc(L) - 1; | |
| 925 const char *oname = NULL; | |
| 926 const char *kind = lj_debug_slotname(pt, pc, (BCReg)(o-L->base), &oname); | |
| 927 if (kind) | |
| 928 err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname); | |
| 929 } | |
| 930 err_msgv(L, LJ_ERR_BADOPRV, opname, tname); | |
| 931 } | |
| 932 | |
| 933 /* Typecheck error for ordered comparisons. */ | |
| 934 LJ_NOINLINE void lj_err_comp(lua_State *L, cTValue *o1, cTValue *o2) | |
| 935 { | |
| 936 const char *t1 = lj_typename(o1); | |
| 937 const char *t2 = lj_typename(o2); | |
| 938 err_msgv(L, t1 == t2 ? LJ_ERR_BADCMPV : LJ_ERR_BADCMPT, t1, t2); | |
| 939 /* This assumes the two "boolean" entries are commoned by the C compiler. */ | |
| 940 } | |
| 941 | |
| 942 /* Typecheck error for __call. */ | |
| 943 LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |
| 944 { | |
| 945 /* Gross hack if lua_[p]call or pcall/xpcall fail for a non-callable object: | |
| 946 ** L->base still points to the caller. So add a dummy frame with L instead | |
| 947 ** of a function. See lua_getstack(). | |
| 948 */ | |
| 949 const BCIns *pc = cframe_Lpc(L); | |
| 950 if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { | |
| 951 const char *tname = lj_typename(o); | |
| 952 setframe_gc(o, obj2gco(L), LJ_TTHREAD); | |
| 953 if (LJ_FR2) o++; | |
| 954 setframe_pc(o, pc); | |
| 955 L->top = L->base = o+1; | |
| 956 err_msgv(L, LJ_ERR_BADCALL, tname); | |
| 957 } | |
| 958 lj_err_optype(L, o, LJ_ERR_OPCALL); | |
| 959 } | |
| 960 | |
| 961 /* Error in context of caller. */ | |
| 962 LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) | |
| 963 { | |
| 964 TValue *frame = NULL, *pframe = NULL; | |
| 965 if (!(LJ_HASJIT && tvref(G(L)->jit_base))) { | |
| 966 frame = L->base-1; | |
| 967 if (frame_islua(frame)) { | |
| 968 pframe = frame_prevl(frame); | |
| 969 } else if (frame_iscont(frame)) { | |
| 970 if (frame_iscont_fficb(frame)) { | |
| 971 pframe = frame; | |
| 972 frame = NULL; | |
| 973 } else { | |
| 974 pframe = frame_prevd(frame); | |
| 975 #if LJ_HASFFI | |
| 976 /* Remove frame for FFI metamethods. */ | |
| 977 if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && | |
| 978 frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { | |
| 979 L->base = pframe+1; | |
| 980 L->top = frame; | |
| 981 setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); | |
| 982 } | |
| 983 #endif | |
| 984 } | |
| 985 } | |
| 986 } | |
| 987 lj_debug_addloc(L, msg, pframe, frame); | |
| 988 lj_err_run(L); | |
| 989 } | |
| 990 | |
| 991 /* Formatted error in context of caller. */ | |
| 992 LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...) | |
| 993 { | |
| 994 const char *msg; | |
| 995 va_list argp; | |
| 996 va_start(argp, em); | |
| 997 msg = lj_strfmt_pushvf(L, err2msg(em), argp); | |
| 998 va_end(argp); | |
| 999 lj_err_callermsg(L, msg); | |
| 1000 } | |
| 1001 | |
| 1002 /* Error in context of caller. */ | |
| 1003 LJ_NOINLINE void lj_err_caller(lua_State *L, ErrMsg em) | |
| 1004 { | |
| 1005 lj_err_callermsg(L, err2msg(em)); | |
| 1006 } | |
| 1007 | |
| 1008 /* Argument error message. */ | |
| 1009 LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg, | |
| 1010 const char *msg) | |
| 1011 { | |
| 1012 const char *fname = "?"; | |
| 1013 const char *ftype = lj_debug_funcname(L, L->base - 1, &fname); | |
| 1014 if (narg < 0 && narg > LUA_REGISTRYINDEX) | |
| 1015 narg = (int)(L->top - L->base) + narg + 1; | |
| 1016 if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ | |
| 1017 msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); | |
| 1018 else | |
| 1019 msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); | |
| 1020 lj_err_callermsg(L, msg); | |
| 1021 } | |
| 1022 | |
| 1023 /* Formatted argument error. */ | |
| 1024 LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...) | |
| 1025 { | |
| 1026 const char *msg; | |
| 1027 va_list argp; | |
| 1028 va_start(argp, em); | |
| 1029 msg = lj_strfmt_pushvf(L, err2msg(em), argp); | |
| 1030 va_end(argp); | |
| 1031 err_argmsg(L, narg, msg); | |
| 1032 } | |
| 1033 | |
| 1034 /* Argument error. */ | |
| 1035 LJ_NOINLINE void lj_err_arg(lua_State *L, int narg, ErrMsg em) | |
| 1036 { | |
| 1037 err_argmsg(L, narg, err2msg(em)); | |
| 1038 } | |
| 1039 | |
| 1040 /* Typecheck error for arguments. */ | |
| 1041 LJ_NOINLINE void lj_err_argtype(lua_State *L, int narg, const char *xname) | |
| 1042 { | |
| 1043 const char *tname, *msg; | |
| 1044 if (narg <= LUA_REGISTRYINDEX) { | |
| 1045 if (narg >= LUA_GLOBALSINDEX) { | |
| 1046 tname = lj_obj_itypename[~LJ_TTAB]; | |
| 1047 } else { | |
| 1048 GCfunc *fn = curr_func(L); | |
| 1049 int idx = LUA_GLOBALSINDEX - narg; | |
| 1050 if (idx <= fn->c.nupvalues) | |
| 1051 tname = lj_typename(&fn->c.upvalue[idx-1]); | |
| 1052 else | |
| 1053 tname = lj_obj_typename[0]; | |
| 1054 } | |
| 1055 } else { | |
| 1056 TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; | |
| 1057 tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; | |
| 1058 } | |
| 1059 msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); | |
| 1060 err_argmsg(L, narg, msg); | |
| 1061 } | |
| 1062 | |
| 1063 /* Typecheck error for arguments. */ | |
| 1064 LJ_NOINLINE void lj_err_argt(lua_State *L, int narg, int tt) | |
| 1065 { | |
| 1066 lj_err_argtype(L, narg, lj_obj_typename[tt+1]); | |
| 1067 } | |
| 1068 | |
| 1069 /* -- Public error handling API ------------------------------------------- */ | |
| 1070 | |
| 1071 LUA_API lua_CFunction lua_atpanic(lua_State *L, lua_CFunction panicf) | |
| 1072 { | |
| 1073 lua_CFunction old = G(L)->panic; | |
| 1074 G(L)->panic = panicf; | |
| 1075 return old; | |
| 1076 } | |
| 1077 | |
| 1078 /* Forwarders for the public API (C calling convention and no LJ_NORET). */ | |
| 1079 LUA_API int lua_error(lua_State *L) | |
| 1080 { | |
| 1081 lj_err_run(L); | |
| 1082 return 0; /* unreachable */ | |
| 1083 } | |
| 1084 | |
| 1085 LUALIB_API int luaL_argerror(lua_State *L, int narg, const char *msg) | |
| 1086 { | |
| 1087 err_argmsg(L, narg, msg); | |
| 1088 return 0; /* unreachable */ | |
| 1089 } | |
| 1090 | |
| 1091 LUALIB_API int luaL_typerror(lua_State *L, int narg, const char *xname) | |
| 1092 { | |
| 1093 lj_err_argtype(L, narg, xname); | |
| 1094 return 0; /* unreachable */ | |
| 1095 } | |
| 1096 | |
| 1097 LUALIB_API void luaL_where(lua_State *L, int level) | |
| 1098 { | |
| 1099 int size; | |
| 1100 cTValue *frame = lj_debug_frame(L, level, &size); | |
| 1101 lj_debug_addloc(L, "", frame, size ? frame+size : NULL); | |
| 1102 } | |
| 1103 | |
| 1104 LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) | |
| 1105 { | |
| 1106 const char *msg; | |
| 1107 va_list argp; | |
| 1108 va_start(argp, fmt); | |
| 1109 msg = lj_strfmt_pushvf(L, fmt, argp); | |
| 1110 va_end(argp); | |
| 1111 lj_err_callermsg(L, msg); | |
| 1112 return 0; /* unreachable */ | |
| 1113 } | |
| 1114 |