• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 6035198545

31 Aug 2023 08:55AM UTC coverage: 88.225% (+0.4%) from 87.822%
6035198545

push

github

fckxorg
test: don't skip tool CLI flag for tarantool

That skipcond was introduced to overcome the obstacles
of LuaJIT's integration testing in Tarantool. Since
the required patch is now in the Tarantool master, this
skipcond is now unnecessary.

Related to tarantool/tarantool#5688

5340 of 5975 branches covered (0.0%)

Branch coverage included in aggregate %.

20495 of 23308 relevant lines covered (87.93%)

1297339.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.09
/src/lj_err.c
1
/*
2
** Error handling.
3
** Copyright (C) 2005-2017 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)
27,032✔
99
{
100
  lj_func_closeuv(L, top);
27,032✔
101
  if (top < L->top-1) {
27,032✔
102
    copyTV(L, top, L->top-1);
26,110✔
103
    L->top = top+1;
26,110✔
104
  }
105
  lj_state_relimitstack(L);
27,032✔
106
}
27,032✔
107

108
/* Unwind until stop frame. Optionally cleanup frames. */
109
static void *err_unwind(lua_State *L, void *stopcf, int errcode)
54,084✔
110
{
111
  TValue *frame = L->base-1;
54,084✔
112
  void *cf = L->cframe;
54,084✔
113
  while (cf) {
319,126✔
114
    int32_t nres = cframe_nres(cframe_raw(cf));
319,126✔
115
    if (nres < 0) {  /* C frame without Lua frame? */
319,126✔
116
      TValue *top = restorestack(L, -nres);
27,250✔
117
      if (frame < top) {  /* Frame reached? */
27,250✔
118
        if (errcode) {
27,250✔
119
          L->base = frame+1;
13,625✔
120
          L->cframe = cframe_prev(cf);
13,625✔
121
          unwindstack(L, top);
13,625✔
122
        }
123
        return cf;
27,250✔
124
      }
125
    }
126
    if (frame <= tvref(L->stack)+LJ_FR2)
291,876✔
127
      break;
128
    switch (frame_typep(frame)) {
291,876✔
129
    case FRAME_LUA:  /* Lua frame. */
262,247✔
130
    case FRAME_LUAP:
131
      frame = frame_prevl(frame);
262,247✔
132
      break;
262,247✔
133
    case FRAME_C:  /* C frame. */
134
    unwind_c:
23✔
135
#if LJ_UNWIND_EXT
136
      if (errcode) {
23✔
137
        L->base = frame_prevd(frame) + 1;
8✔
138
        L->cframe = cframe_prev(cf);
8✔
139
        unwindstack(L, frame - LJ_FR2);
8✔
140
      } else if (cf != stopcf) {
15✔
141
        cf = cframe_prev(cf);
7✔
142
        frame = frame_prevd(frame);
7✔
143
        break;
7✔
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. */
68✔
153
      if (cframe_canyield(cf)) {  /* Resume? */
68✔
154
        if (errcode) {
20✔
155
          hook_leave(G(L));  /* Assumes nobody uses coroutines inside hooks. */
10✔
156
          L->cframe = NULL;
10✔
157
          L->status = (uint8_t)errcode;
10✔
158
        }
159
        return cf;
20✔
160
      }
161
      if (errcode) {
48✔
162
        L->base = frame_prevd(frame) + 1;
24✔
163
        L->cframe = cframe_prev(cf);
24✔
164
        unwindstack(L, frame - LJ_FR2);
24✔
165
      }
166
      return cf;
167
    case FRAME_CONT:  /* Continuation frame. */
13✔
168
      if (frame_iscont_fficb(frame))
13✔
169
        goto unwind_c;
3✔
170
      /* fallthrough */
171
    case FRAME_VARG:  /* Vararg frame. */
172
      frame = frame_prevd(frame);
2,788✔
173
      break;
2,788✔
174
    case FRAME_PCALL:  /* FF pcall() frame. */
26,750✔
175
    case FRAME_PCALLH:  /* FF pcall() frame inside hook. */
176
      if (errcode) {
26,750✔
177
        if (errcode == LUA_YIELD) {
13,375✔
178
          frame = frame_prevd(frame);
×
179
          break;
×
180
        }
181
        if (frame_typep(frame) == FRAME_PCALL)
13,375✔
182
          hook_leave(G(L));
13,374✔
183
        L->base = frame_prevd(frame) + 1;
13,375✔
184
        L->cframe = cf;
13,375✔
185
        unwindstack(L, L->base);
13,375✔
186
      }
187
      return (void *)((intptr_t)cf | CFRAME_UNWIND_FF);
26,750✔
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
    uintptr_t frame, base, addr = ctx.CONTEXT_REG_PC;
333
    void *hdata;
334
    PRUNTIME_FUNCTION func = RtlLookupFunctionEntry(addr, &base, &hist);
335
    if (!func) {  /* Found frame without .pdata: must be JIT-compiled code. */
336
      ExitNo exitno;
337
      uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno);
338
      if (stub) {  /* Jump to side exit to unwind the trace. */
339
        ctx.CONTEXT_REG_PC = stub;
340
        G2J(g)->exitcode = errcode;
341
        RtlRestoreContext(&ctx, NULL);  /* Does not return. */
342
      }
343
      break;
344
    }
345
    RtlVirtualUnwind(UNW_FLAG_NHANDLER, base, addr, func,
346
                     &ctx, &hdata, &frame, NULL);
347
    if (!addr) break;
348
  }
349
  /* Unwinding failed, if we end up here. */
350
}
351
#endif
352

353
/* Raise Windows exception. */
354
static void err_raise_ext(global_State *g, int errcode)
355
{
356
#if LJ_UNWIND_JIT
357
  if (tvref(g->jit_base)) {
358
    err_unwind_win_jit(g, errcode);
359
    return;  /* Unwinding failed. */
360
  }
361
#elif LJ_HASJIT
362
  /* Cannot catch on-trace errors for Windows/x86 SEH. Unwind to interpreter. */
363
  setmref(g->jit_base, NULL);
364
#endif
365
  UNUSED(g);
366
  RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL);
367
}
368

369
#elif !LJ_NO_UNWIND && (defined(__GNUC__) || defined(__clang__))
370

371
/*
372
** We have to use our own definitions instead of the mandatory (!) unwind.h,
373
** since various OS, distros and compilers mess up the header installation.
374
*/
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,
54,084✔
415
  uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx)
416
{
417
  void *cf;
54,084✔
418
  lua_State *L;
54,084✔
419
  if (version != 1)
54,084✔
420
    return _URC_FATAL_PHASE1_ERROR;
421
  cf = (void *)_Unwind_GetCFA(ctx);
54,084✔
422
  L = cframe_L(cf);
54,084✔
423
  if ((actions & _UA_SEARCH_PHASE)) {
54,084✔
424
#if LJ_UNWIND_EXT
425
    if (err_unwind(L, cf, 0) == NULL)
27,042✔
426
      return _URC_CONTINUE_UNWIND;
427
#endif
428
    if (!LJ_UEXCLASS_CHECK(uexclass)) {
27,034✔
429
      setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
×
430
    }
431
    return _URC_HANDLER_FOUND;
27,034✔
432
  }
433
  if ((actions & _UA_CLEANUP_PHASE)) {
27,042✔
434
    int errcode;
27,042✔
435
    if (LJ_UEXCLASS_CHECK(uexclass)) {
27,042✔
436
      errcode = LJ_UEXCLASS_ERRCODE(uexclass);
27,042✔
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);
27,042✔
444
    if ((actions & _UA_FORCE_UNWIND)) {
27,042✔
445
      return _URC_CONTINUE_UNWIND;
446
    } else if (cf) {
27,042✔
447
      _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode);
27,034✔
448
      _Unwind_SetIP(ctx, (uintptr_t)(cframe_unwind_ff(cf) ?
27,034✔
449
                                     lj_vm_unwind_ff_eh :
450
                                     lj_vm_unwind_c_eh));
451
      return _URC_INSTALL_CONTEXT;
27,034✔
452
    }
453
#if LJ_TARGET_X86ORX64
454
    else if ((actions & _UA_HANDLER_FRAME)) {
8✔
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,
2✔
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))
2✔
501
    return _URC_FATAL_PHASE1_ERROR;
502
  if ((actions & _UA_SEARCH_PHASE)) {
2✔
503
    return _URC_HANDLER_FOUND;
504
  }
505
  if ((actions & _UA_CLEANUP_PHASE)) {
1✔
506
    global_State *g = *(global_State **)(uex+1);
1✔
507
    ExitNo exitno;
1✔
508
    uintptr_t addr = _Unwind_GetIP(ctx);  /* Return address _after_ call. */
1✔
509
    uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno);
1✔
510
    lj_assertG(tvref(g->jit_base), "unexpected throw across mcode frame");
1✔
511
    if (stub) {  /* Jump to side exit to unwind the trace. */
1✔
512
      G2J(g)->exitcode = LJ_UEXCLASS_ERRCODE(uexclass);
1✔
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);
1✔
519
#endif
520
      return _URC_INSTALL_CONTEXT;
1✔
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)
334✔
582
{
583
  void **handler;
334✔
584
  memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template));
334✔
585
  handler = (void *)err_unwind_jit;
334✔
586
  memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler));
334✔
587
  *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) =
334✔
588
    (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base));
334✔
589
  __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER);
334✔
590
#ifdef LUA_USE_ASSERT
591
  {
592
    struct dwarf_eh_bases ehb;
593
    lj_assertX(_Unwind_Find_FDE(info + sizeof(err_frame_jit_template)+1, &ehb),
594
               "bad JIT unwind table registration");
595
  }
596
#endif
597
  return info + sizeof(err_frame_jit_template);
334✔
598
}
599

600
void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info)
332✔
601
{
602
  UNUSED(base); UNUSED(sz);
332✔
603
  __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER);
332✔
604
}
332✔
605
#endif
606

607
#else /* LJ_TARGET_ARM */
608

609
#define _US_VIRTUAL_UNWIND_FRAME        0
610
#define _US_UNWIND_FRAME_STARTING        1
611
#define _US_ACTION_MASK                        3
612
#define _US_FORCE_UNWIND                8
613

614
typedef struct _Unwind_Control_Block _Unwind_Control_Block;
615
#define UNWIND_EXCEPTION_TYPE        _Unwind_Control_Block
616

617
struct _Unwind_Control_Block {
618
  uint64_t exclass;
619
  uint32_t misc[20];
620
};
621

622
extern int _Unwind_RaiseException(_Unwind_Control_Block *);
623
extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *);
624
extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *);
625
extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *);
626

627
static inline uint32_t _Unwind_GetGR(_Unwind_Context *ctx, int r)
628
{
629
  uint32_t v;
630
  _Unwind_VRS_Get(ctx, 0, r, 0, &v);
631
  return v;
632
}
633

634
static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v)
635
{
636
  _Unwind_VRS_Set(ctx, 0, r, 0, &v);
637
}
638

639
extern void lj_vm_unwind_ext(void);
640

641
/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */
642
LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb,
643
                               _Unwind_Context *ctx)
644
{
645
  void *cf = (void *)_Unwind_GetGR(ctx, 13);
646
  lua_State *L = cframe_L(cf);
647
  int errcode;
648

649
  switch ((state & _US_ACTION_MASK)) {
650
  case _US_VIRTUAL_UNWIND_FRAME:
651
    if ((state & _US_FORCE_UNWIND)) break;
652
    return _URC_HANDLER_FOUND;
653
  case _US_UNWIND_FRAME_STARTING:
654
    if (LJ_UEXCLASS_CHECK(ucb->exclass)) {
655
      errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass);
656
    } else {
657
      errcode = LUA_ERRRUN;
658
      setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
659
    }
660
    cf = err_unwind(L, cf, errcode);
661
    if ((state & _US_FORCE_UNWIND) || cf == NULL) break;
662
    _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext);
663
    _Unwind_SetGR(ctx, 0, (uint32_t)ucb);
664
    _Unwind_SetGR(ctx, 1, (uint32_t)errcode);
665
    _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ?
666
                            (uint32_t)lj_vm_unwind_ff_eh :
667
                            (uint32_t)lj_vm_unwind_c_eh);
668
    return _URC_INSTALL_CONTEXT;
669
  default:
670
    return _URC_FAILURE;
671
  }
672
  if (__gnu_unwind_frame(ucb, ctx) != _URC_OK)
673
    return _URC_FAILURE;
674
#ifdef LUA_USE_ASSERT
675
  /* We should never get here unless this is a forced unwind aka backtrace. */
676
  if (_Unwind_GetGR(ctx, 0) == 0xff33aa77) {
677
    _Unwind_SetGR(ctx, 0, 0xff33aa88);
678
  }
679
#endif
680
  return _URC_CONTINUE_UNWIND;
681
}
682

683
#if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT)
684
typedef int (*_Unwind_Trace_Fn)(_Unwind_Context *, void *);
685
extern int _Unwind_Backtrace(_Unwind_Trace_Fn, void *);
686

687
static int err_verify_bt(_Unwind_Context *ctx, int *got)
688
{
689
  if (_Unwind_GetGR(ctx, 0) == 0xff33aa88) { *got = 2; }
690
  else if (*got == 0) { *got = 1; _Unwind_SetGR(ctx, 0, 0xff33aa77); }
691
  return _URC_OK;
692
}
693

694
/* Verify that external error handling actually has a chance to work. */
695
void lj_err_verify(void)
696
{
697
  int got = 0;
698
  _Unwind_Backtrace((_Unwind_Trace_Fn)err_verify_bt, &got);
699
  lj_assertX(got == 2, "broken build: external frame unwinding enabled, but missing -funwind-tables");
700
}
701
#endif
702

703
/*
704
** Note: LJ_UNWIND_JIT is not implemented for 32 bit ARM.
705
**
706
** The quirky ARM unwind API doesn't have __register_frame().
707
** A potential workaround might involve _Unwind_Backtrace.
708
** But most 32 bit ARM targets don't qualify for LJ_UNWIND_EXT, anyway,
709
** since they are built without unwind tables by default.
710
*/
711

712
#endif /* LJ_TARGET_ARM */
713

714

715
#if LJ_UNWIND_EXT
716
static __thread struct {
717
  UNWIND_EXCEPTION_TYPE ex;
718
  global_State *g;
719
} static_uex;
720

721
/* Raise external exception. */
722
static void err_raise_ext(global_State *g, int errcode)
27,035✔
723
{
724
  memset(&static_uex, 0, sizeof(static_uex));
27,035✔
725
  static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode);
27,035✔
726
  static_uex.g = g;
27,035✔
727
  _Unwind_RaiseException(&static_uex.ex);
27,035✔
728
}
×
729

730
#endif
731

732
#endif
733

734
/* -- Error handling ------------------------------------------------------ */
735

736
/* Throw error. Find catch frame, unwind stack and continue. */
737
LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode)
27,035✔
738
{
739
  global_State *g = G(L);
27,035✔
740
  lj_trace_abort(g);
27,035✔
741
  L->status = LUA_OK;
27,035✔
742
#if LJ_UNWIND_EXT
743
  err_raise_ext(g, errcode);
27,035✔
744
  /*
745
  ** A return from this function signals a corrupt C stack that cannot be
746
  ** unwound. We have no choice but to call the panic function and exit.
747
  **
748
  ** Usually this is caused by a C function without unwind information.
749
  ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL
750
  ** and forgot to recompile *every* non-C++ file with -funwind-tables.
751
  */
752
  if (G(L)->panic)
×
753
    G(L)->panic(L);
×
754
#else
755
#if LJ_HASJIT
756
  setmref(g->jit_base, NULL);
757
#endif
758
  {
759
    void *cf = err_unwind(L, NULL, errcode);
760
    if (cframe_unwind_ff(cf))
761
      lj_vm_unwind_ff(cframe_raw(cf));
762
    else
763
      lj_vm_unwind_c(cframe_raw(cf), errcode);
764
  }
765
#endif
766
  exit(EXIT_FAILURE);
×
767
}
768

769
/* Return string object for error message. */
770
LJ_NOINLINE GCstr *lj_err_str(lua_State *L, ErrMsg em)
264✔
771
{
772
  return lj_str_newz(L, err2msg(em));
264✔
773
}
774

775
/* Out-of-memory error. */
776
LJ_NOINLINE void lj_err_mem(lua_State *L)
1✔
777
{
778
  if (L->status == LUA_ERRERR+1)  /* Don't touch the stack during lua_open. */
1✔
779
    lj_vm_unwind_c(L->cframe, LUA_ERRMEM);
×
780
  if (curr_funcisL(L)) L->top = curr_topL(L);
1✔
781
  setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM));
1✔
782
  lj_err_throw(L, LUA_ERRMEM);
1✔
783
}
784

785
/* Find error function for runtime errors. Requires an extra stack traversal. */
786
static ptrdiff_t finderrfunc(lua_State *L)
13,411✔
787
{
788
  cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2;
13,411✔
789
  void *cf = L->cframe;
13,411✔
790
  while (frame > bot && cf) {
145,951✔
791
    while (cframe_nres(cframe_raw(cf)) < 0) {  /* cframe without frame? */
145,942✔
792
      if (frame >= restorestack(L, -cframe_nres(cf)))
4✔
793
        break;
794
      if (cframe_errfunc(cf) >= 0)  /* Error handler not inherited (-1)? */
4✔
795
        return cframe_errfunc(cf);
2✔
796
      cf = cframe_prev(cf);  /* Else unwind cframe and continue searching. */
2✔
797
      if (cf == NULL)
2✔
798
        return 0;
799
    }
800
    switch (frame_typep(frame)) {
145,938✔
801
    case FRAME_LUA:
131,125✔
802
    case FRAME_LUAP:
803
      frame = frame_prevl(frame);
131,125✔
804
      break;
131,125✔
805
    case FRAME_C:
6✔
806
      cf = cframe_prev(cf);
6✔
807
      /* fallthrough */
808
    case FRAME_VARG:
1,398✔
809
      frame = frame_prevd(frame);
1,398✔
810
      break;
1,398✔
811
    case FRAME_CONT:
4✔
812
      if (frame_iscont_fficb(frame))
4✔
813
        cf = cframe_prev(cf);
1✔
814
      frame = frame_prevd(frame);
4✔
815
      break;
4✔
816
    case FRAME_CP:
34✔
817
      if (cframe_canyield(cf)) return 0;
34✔
818
      if (cframe_errfunc(cf) >= 0)
26✔
819
        return cframe_errfunc(cf);
13✔
820
      cf = cframe_prev(cf);
13✔
821
      frame = frame_prevd(frame);
13✔
822
      break;
13✔
823
    case FRAME_PCALL:
13,377✔
824
    case FRAME_PCALLH:
825
      if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall)
13,377✔
826
        return savestack(L, frame_prevd(frame)+1);  /* xpcall's errorfunc. */
18✔
827
      return 0;
828
    default:
829
      lj_assertL(0, "bad frame type");
830
      return 0;
831
    }
832
  }
833
  return 0;
834
}
835

836
/* Runtime error. */
837
LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L)
13,412✔
838
{
839
  ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L);
13,412✔
840
  if (ef) {
13,411✔
841
    TValue *errfunc = restorestack(L, ef);
22✔
842
    TValue *top = L->top;
22✔
843
    lj_trace_abort(G(L));
22✔
844
    if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) {
22✔
845
      setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR));
3✔
846
      lj_err_throw(L, LUA_ERRERR);
3✔
847
    }
848
    L->status = LUA_ERRERR;
19✔
849
    copyTV(L, top+LJ_FR2, top-1);
19✔
850
    copyTV(L, top-1, errfunc);
19✔
851
    if (LJ_FR2) setnilV(top++);
19✔
852
    L->top = top+1;
19✔
853
    lj_vm_call(L, top, 1+1);  /* Stack: |errfunc|msg| -> |msg| */
19✔
854
  }
855
  lj_err_throw(L, LUA_ERRRUN);
13,406✔
856
}
857

858
#if LJ_HASJIT
859
LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode)
2✔
860
{
861
  if (errcode == LUA_ERRRUN)
2✔
862
    lj_err_run(L);
2✔
863
  else
864
    lj_err_throw(L, errcode);
×
865
}
866
#endif
867

868
/* Formatted runtime error message. */
869
LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...)
13,095✔
870
{
871
  const char *msg;
13,095✔
872
  va_list argp;
13,095✔
873
  va_start(argp, em);
13,095✔
874
  if (curr_funcisL(L)) L->top = curr_topL(L);
13,095✔
875
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
13,095✔
876
  va_end(argp);
13,095✔
877
  lj_debug_addloc(L, msg, L->base-1, NULL);
13,095✔
878
  lj_err_run(L);
13,095✔
879
}
880

881
/* Non-vararg variant for better calling conventions. */
882
LJ_NOINLINE void lj_err_msg(lua_State *L, ErrMsg em)
24✔
883
{
884
  err_msgv(L, em);
24✔
885
}
886

887
/* Lexer error. */
888
LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok,
12,702✔
889
                            BCLine line, ErrMsg em, va_list argp)
890
{
891
  char buff[LUA_IDSIZE];
12,702✔
892
  const char *msg;
12,702✔
893
  lj_debug_shortname(buff, src, line);
12,702✔
894
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
12,702✔
895
  msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg);
12,702✔
896
  if (tok)
12,702✔
897
    lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok);
12,675✔
898
  lj_err_throw(L, LUA_ERRSYNTAX);
12,702✔
899
}
900

901
/* Typecheck error for operands. */
902
LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm)
1,486✔
903
{
904
  const char *tname = lj_typename(o);
1,486✔
905
  const char *opname = err2msg(opm);
1,486✔
906
  if (curr_funcisL(L)) {
1,486✔
907
    GCproto *pt = curr_proto(L);
1,486✔
908
    const BCIns *pc = cframe_Lpc(L) - 1;
1,486✔
909
    const char *oname = NULL;
1,486✔
910
    const char *kind = lj_debug_slotname(pt, pc, (BCReg)(o-L->base), &oname);
1,486✔
911
    if (kind)
1,486✔
912
      err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname);
423✔
913
  }
914
  err_msgv(L, LJ_ERR_BADOPRV, opname, tname);
1,063✔
915
}
916

917
/* Typecheck error for ordered comparisons. */
918
LJ_NOINLINE void lj_err_comp(lua_State *L, cTValue *o1, cTValue *o2)
78✔
919
{
920
  const char *t1 = lj_typename(o1);
78✔
921
  const char *t2 = lj_typename(o2);
78✔
922
  err_msgv(L, t1 == t2 ? LJ_ERR_BADCMPV : LJ_ERR_BADCMPT, t1, t2);
78✔
923
  /* This assumes the two "boolean" entries are commoned by the C compiler. */
924
}
925

926
/* Typecheck error for __call. */
927
LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o)
11,712✔
928
{
929
  /* Gross hack if lua_[p]call or pcall/xpcall fail for a non-callable object:
930
  ** L->base still points to the caller. So add a dummy frame with L instead
931
  ** of a function. See lua_getstack().
932
  */
933
  const BCIns *pc = cframe_Lpc(L);
11,712✔
934
  if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) {
11,712✔
935
    const char *tname = lj_typename(o);
11,507✔
936
    setframe_gc(o, obj2gco(L), LJ_TTHREAD);
11,507✔
937
    if (LJ_FR2) o++;
11,507✔
938
    setframe_pc(o, pc);
11,507✔
939
    L->top = L->base = o+1;
11,507✔
940
    err_msgv(L, LJ_ERR_BADCALL, tname);
11,507✔
941
  }
942
  lj_err_optype(L, o, LJ_ERR_OPCALL);
205✔
943
}
944

945
/* Error in context of caller. */
946
LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg)
232✔
947
{
948
  TValue *frame = L->base-1;
232✔
949
  TValue *pframe = NULL;
232✔
950
  if (frame_islua(frame)) {
232✔
951
    pframe = frame_prevl(frame);
100✔
952
  } else if (frame_iscont(frame)) {
132✔
953
    if (frame_iscont_fficb(frame)) {
4✔
954
      pframe = frame;
955
      frame = NULL;
956
    } else {
957
      pframe = frame_prevd(frame);
4✔
958
#if LJ_HASFFI
959
      /* Remove frame for FFI metamethods. */
960
      if (frame_func(frame)->c.ffid >= FF_ffi_meta___index &&
4✔
961
          frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) {
962
        L->base = pframe+1;
3✔
963
        L->top = frame;
3✔
964
        setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame));
3✔
965
      }
966
#endif
967
    }
968
  }
969
  lj_debug_addloc(L, msg, pframe, frame);
232✔
970
  lj_err_run(L);
232✔
971
}
972

973
/* Formatted error in context of caller. */
974
LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...)
17✔
975
{
976
  const char *msg;
17✔
977
  va_list argp;
17✔
978
  va_start(argp, em);
17✔
979
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
17✔
980
  va_end(argp);
17✔
981
  lj_err_callermsg(L, msg);
17✔
982
}
983

984
/* Error in context of caller. */
985
LJ_NOINLINE void lj_err_caller(lua_State *L, ErrMsg em)
44✔
986
{
987
  lj_err_callermsg(L, err2msg(em));
44✔
988
}
989

990
/* Argument error message. */
991
LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg,
107✔
992
                                            const char *msg)
993
{
994
  const char *fname = "?";
107✔
995
  const char *ftype = lj_debug_funcname(L, L->base - 1, &fname);
107✔
996
  if (narg < 0 && narg > LUA_REGISTRYINDEX)
107✔
997
    narg = (int)(L->top - L->base) + narg + 1;
×
998
  if (ftype && ftype[3] == 'h' && --narg == 0)  /* Check for "method". */
107✔
999
    msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg);
×
1000
  else
1001
    msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg);
107✔
1002
  lj_err_callermsg(L, msg);
107✔
1003
}
1004

1005
/* Formatted argument error. */
1006
LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...)
4✔
1007
{
1008
  const char *msg;
4✔
1009
  va_list argp;
4✔
1010
  va_start(argp, em);
4✔
1011
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
4✔
1012
  va_end(argp);
4✔
1013
  err_argmsg(L, narg, msg);
4✔
1014
}
1015

1016
/* Argument error. */
1017
LJ_NOINLINE void lj_err_arg(lua_State *L, int narg, ErrMsg em)
30✔
1018
{
1019
  err_argmsg(L, narg, err2msg(em));
30✔
1020
}
1021

1022
/* Typecheck error for arguments. */
1023
LJ_NOINLINE void lj_err_argtype(lua_State *L, int narg, const char *xname)
71✔
1024
{
1025
  const char *tname, *msg;
71✔
1026
  if (narg <= LUA_REGISTRYINDEX) {
71✔
1027
    if (narg >= LUA_GLOBALSINDEX) {
×
1028
      tname = lj_obj_itypename[~LJ_TTAB];
×
1029
    } else {
1030
      GCfunc *fn = curr_func(L);
×
1031
      int idx = LUA_GLOBALSINDEX - narg;
×
1032
      if (idx <= fn->c.nupvalues)
×
1033
        tname = lj_typename(&fn->c.upvalue[idx-1]);
×
1034
      else
1035
        tname = lj_obj_typename[0];
×
1036
    }
1037
  } else {
1038
    TValue *o = narg < 0 ? L->top + narg : L->base + narg-1;
71✔
1039
    tname = o < L->top ? lj_typename(o) : lj_obj_typename[0];
71✔
1040
  }
1041
  msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname);
71✔
1042
  err_argmsg(L, narg, msg);
71✔
1043
}
1044

1045
/* Typecheck error for arguments. */
1046
LJ_NOINLINE void lj_err_argt(lua_State *L, int narg, int tt)
69✔
1047
{
1048
  lj_err_argtype(L, narg, lj_obj_typename[tt+1]);
69✔
1049
}
1050

1051
/* -- Public error handling API ------------------------------------------- */
1052

1053
LUA_API lua_CFunction lua_atpanic(lua_State *L, lua_CFunction panicf)
×
1054
{
1055
  lua_CFunction old = G(L)->panic;
×
1056
  G(L)->panic = panicf;
×
1057
  return old;
×
1058
}
1059

1060
/* Forwarders for the public API (C calling convention and no LJ_NORET). */
1061
LUA_API int lua_error(lua_State *L)
80✔
1062
{
1063
  lj_err_run(L);
80✔
1064
  return 0;  /* unreachable */
1065
}
1066

1067
LUALIB_API int luaL_argerror(lua_State *L, int narg, const char *msg)
2✔
1068
{
1069
  err_argmsg(L, narg, msg);
2✔
1070
  return 0;  /* unreachable */
1071
}
1072

1073
LUALIB_API int luaL_typerror(lua_State *L, int narg, const char *xname)
×
1074
{
1075
  lj_err_argtype(L, narg, xname);
×
1076
  return 0;  /* unreachable */
1077
}
1078

1079
LUALIB_API void luaL_where(lua_State *L, int level)
23✔
1080
{
1081
  int size;
23✔
1082
  cTValue *frame = lj_debug_frame(L, level, &size);
23✔
1083
  lj_debug_addloc(L, "", frame, size ? frame+size : NULL);
23✔
1084
}
23✔
1085

1086
LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...)
55✔
1087
{
1088
  const char *msg;
55✔
1089
  va_list argp;
55✔
1090
  va_start(argp, fmt);
55✔
1091
  msg = lj_strfmt_pushvf(L, fmt, argp);
55✔
1092
  va_end(argp);
55✔
1093
  lj_err_callermsg(L, msg);
55✔
1094
  return 0;  /* unreachable */
1095
}
1096

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc