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

tarantool / luajit / 6145668764

11 Sep 2023 11:17AM UTC coverage: 88.224% (-0.04%) from 88.259%
6145668764

push

github

fckxorg
Fix frame for more types of on-trace error messages.

Thanks to Maxim Kokryashkin.

(cherry-picked from commit d5bbf9cdb)

This patch fixes the same issue with frame, as the previous
one, but now for the table overflow error in the `err_msgv`
function. The test for the problem uses the table of GC
finalizers, although they are not required to reproduce the
issue. They only used to make the test as simple as possible.

Resolves tarantool/tarantool#562
Part of tarantool/tarantool#8825

5339 of 5971 branches covered (0.0%)

Branch coverage included in aggregate %.

3 of 3 new or added lines in 1 file covered. (100.0%)

20479 of 23293 relevant lines covered (87.92%)

2738247.52 hits per line

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

89.3
/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)
26,863✔
99
{
100
  lj_func_closeuv(L, top);
26,863✔
101
  if (top < L->top-1) {
26,863✔
102
    copyTV(L, top, L->top-1);
26,111✔
103
    L->top = top+1;
26,111✔
104
  }
105
  lj_state_relimitstack(L);
26,863✔
106
}
26,863✔
107

108
/* Unwind until stop frame. Optionally cleanup frames. */
109
static void *err_unwind(lua_State *L, void *stopcf, int errcode)
53,746✔
110
{
111
  TValue *frame = L->base-1;
53,746✔
112
  void *cf = L->cframe;
53,746✔
113
  while (cf) {
318,778✔
114
    int32_t nres = cframe_nres(cframe_raw(cf));
318,778✔
115
    if (nres < 0) {  /* C frame without Lua frame? */
318,778✔
116
      TValue *top = restorestack(L, -nres);
26,910✔
117
      if (frame < top) {  /* Frame reached? */
26,910✔
118
        if (errcode) {
26,910✔
119
          L->base = frame+1;
13,455✔
120
          L->cframe = cframe_prev(cf);
13,455✔
121
          unwindstack(L, top);
13,455✔
122
        }
123
        return cf;
26,910✔
124
      }
125
    }
126
    if (frame <= tvref(L->stack)+LJ_FR2)
291,868✔
127
      break;
128
    switch (frame_typep(frame)) {
291,868✔
129
    case FRAME_LUA:  /* Lua frame. */
262,237✔
130
    case FRAME_LUAP:
131
      frame = frame_prevl(frame);
262,237✔
132
      break;
262,237✔
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. */
64✔
153
      if (cframe_canyield(cf)) {  /* Resume? */
64✔
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) {
44✔
162
        L->base = frame_prevd(frame) + 1;
22✔
163
        L->cframe = cframe_prev(cf);
22✔
164
        unwindstack(L, frame - LJ_FR2);
22✔
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,756✔
175
    case FRAME_PCALLH:  /* FF pcall() frame inside hook. */
176
      if (errcode) {
26,756✔
177
        if (errcode == LUA_YIELD) {
13,378✔
178
          frame = frame_prevd(frame);
×
179
          break;
×
180
        }
181
        if (frame_typep(frame) == FRAME_PCALL)
13,378✔
182
          hook_leave(G(L));
13,377✔
183
        L->base = frame_prevd(frame) + 1;
13,378✔
184
        L->cframe = cf;
13,378✔
185
        unwindstack(L, L->base);
13,378✔
186
      }
187
      return (void *)((intptr_t)cf | CFRAME_UNWIND_FF);
26,756✔
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,
53,746✔
415
  uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx)
416
{
417
  void *cf;
53,746✔
418
  lua_State *L;
53,746✔
419
  if (version != 1)
53,746✔
420
    return _URC_FATAL_PHASE1_ERROR;
421
  cf = (void *)_Unwind_GetCFA(ctx);
53,746✔
422
  L = cframe_L(cf);
53,746✔
423
  if ((actions & _UA_SEARCH_PHASE)) {
53,746✔
424
#if LJ_UNWIND_EXT
425
    if (err_unwind(L, cf, 0) == NULL)
26,873✔
426
      return _URC_CONTINUE_UNWIND;
427
#endif
428
    if (!LJ_UEXCLASS_CHECK(uexclass)) {
26,865✔
429
      setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
×
430
    }
431
    return _URC_HANDLER_FOUND;
26,865✔
432
  }
433
  if ((actions & _UA_CLEANUP_PHASE)) {
26,873✔
434
    int errcode;
26,873✔
435
    if (LJ_UEXCLASS_CHECK(uexclass)) {
26,873✔
436
      errcode = LJ_UEXCLASS_ERRCODE(uexclass);
26,873✔
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);
26,873✔
444
    if ((actions & _UA_FORCE_UNWIND)) {
26,873✔
445
      return _URC_CONTINUE_UNWIND;
446
    } else if (cf) {
26,873✔
447
      _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode);
26,865✔
448
      _Unwind_SetIP(ctx, (uintptr_t)(cframe_unwind_ff(cf) ?
26,865✔
449
                                     lj_vm_unwind_ff_eh :
450
                                     lj_vm_unwind_c_eh));
451
      return _URC_INSTALL_CONTEXT;
26,865✔
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,
6✔
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))
6✔
501
    return _URC_FATAL_PHASE1_ERROR;
502
  if ((actions & _UA_SEARCH_PHASE)) {
6✔
503
    return _URC_HANDLER_FOUND;
504
  }
505
  if ((actions & _UA_CLEANUP_PHASE)) {
3✔
506
    global_State *g = *(global_State **)(uex+1);
3✔
507
    ExitNo exitno;
3✔
508
    uintptr_t addr = _Unwind_GetIP(ctx);  /* Return address _after_ call. */
3✔
509
    uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno);
3✔
510
    lj_assertG(tvref(g->jit_base), "unexpected throw across mcode frame");
3✔
511
    if (stub) {  /* Jump to side exit to unwind the trace. */
3✔
512
      G2J(g)->exitcode = LJ_UEXCLASS_ERRCODE(uexclass);
3✔
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);
3✔
519
#endif
520
      return _URC_INSTALL_CONTEXT;
3✔
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)
320✔
582
{
583
  void **handler;
320✔
584
  memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template));
320✔
585
  handler = (void *)err_unwind_jit;
320✔
586
  memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler));
320✔
587
  *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) =
320✔
588
    (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base));
320✔
589
  __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER);
320✔
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);
320✔
598
}
599

600
void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info)
317✔
601
{
602
  UNUSED(base); UNUSED(sz);
317✔
603
  __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER);
317✔
604
}
317✔
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)
26,868✔
723
{
724
  memset(&static_uex, 0, sizeof(static_uex));
26,868✔
725
  static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode);
26,868✔
726
  static_uex.g = g;
26,868✔
727
  _Unwind_RaiseException(&static_uex.ex);
26,868✔
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)
26,868✔
738
{
739
  global_State *g = G(L);
26,868✔
740
  lj_trace_abort(g);
26,868✔
741
  L->status = LUA_OK;
26,868✔
742
#if LJ_UNWIND_EXT
743
  err_raise_ext(g, errcode);
26,868✔
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)
261✔
771
{
772
  return lj_str_newz(L, err2msg(em));
261✔
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 (LJ_HASJIT) {
1✔
781
    TValue *base = tvref(G(L)->jit_base);
1✔
782
    if (base) L->base = base;
1✔
783
  }
784
  if (curr_funcisL(L)) L->top = curr_topL(L);
1✔
785
  setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM));
1✔
786
  lj_err_throw(L, LUA_ERRMEM);
1✔
787
}
788

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

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

862
#if LJ_HASJIT
863
LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode)
4✔
864
{
865
  if (errcode == LUA_ERRRUN)
4✔
866
    lj_err_run(L);
4✔
867
  else
868
    lj_err_throw(L, errcode);
×
869
}
870
#endif
871

872
/* Formatted runtime error message. */
873
LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...)
13,098✔
874
{
875
  const char *msg;
13,098✔
876
  va_list argp;
13,098✔
877
  va_start(argp, em);
13,098✔
878
  if (LJ_HASJIT) {
13,098✔
879
    TValue *base = tvref(G(L)->jit_base);
13,098✔
880
    if (base) L->base = base;
13,098✔
881
  }
882
  if (curr_funcisL(L)) L->top = curr_topL(L);
13,098✔
883
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
13,098✔
884
  va_end(argp);
13,098✔
885
  lj_debug_addloc(L, msg, L->base-1, NULL);
13,098✔
886
  lj_err_run(L);
13,098✔
887
}
888

889
/* Non-vararg variant for better calling conventions. */
890
LJ_NOINLINE void lj_err_msg(lua_State *L, ErrMsg em)
26✔
891
{
892
  err_msgv(L, em);
26✔
893
}
894

895
/* Lexer error. */
896
LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok,
12,702✔
897
                            BCLine line, ErrMsg em, va_list argp)
898
{
899
  char buff[LUA_IDSIZE];
12,702✔
900
  const char *msg;
12,702✔
901
  lj_debug_shortname(buff, src, line);
12,702✔
902
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
12,702✔
903
  msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg);
12,702✔
904
  if (tok)
12,702✔
905
    lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok);
12,675✔
906
  lj_err_throw(L, LUA_ERRSYNTAX);
12,702✔
907
}
908

909
/* Typecheck error for operands. */
910
LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm)
1,487✔
911
{
912
  const char *tname = lj_typename(o);
1,487✔
913
  const char *opname = err2msg(opm);
1,487✔
914
  if (curr_funcisL(L)) {
1,487✔
915
    GCproto *pt = curr_proto(L);
1,487✔
916
    const BCIns *pc = cframe_Lpc(L) - 1;
1,487✔
917
    const char *oname = NULL;
1,487✔
918
    const char *kind = lj_debug_slotname(pt, pc, (BCReg)(o-L->base), &oname);
1,487✔
919
    if (kind)
1,487✔
920
      err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname);
423✔
921
  }
922
  err_msgv(L, LJ_ERR_BADOPRV, opname, tname);
1,064✔
923
}
924

925
/* Typecheck error for ordered comparisons. */
926
LJ_NOINLINE void lj_err_comp(lua_State *L, cTValue *o1, cTValue *o2)
78✔
927
{
928
  const char *t1 = lj_typename(o1);
78✔
929
  const char *t2 = lj_typename(o2);
78✔
930
  err_msgv(L, t1 == t2 ? LJ_ERR_BADCMPV : LJ_ERR_BADCMPT, t1, t2);
78✔
931
  /* This assumes the two "boolean" entries are commoned by the C compiler. */
932
}
933

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

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

981
/* Formatted error in context of caller. */
982
LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...)
17✔
983
{
984
  const char *msg;
17✔
985
  va_list argp;
17✔
986
  va_start(argp, em);
17✔
987
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
17✔
988
  va_end(argp);
17✔
989
  lj_err_callermsg(L, msg);
17✔
990
}
991

992
/* Error in context of caller. */
993
LJ_NOINLINE void lj_err_caller(lua_State *L, ErrMsg em)
44✔
994
{
995
  lj_err_callermsg(L, err2msg(em));
44✔
996
}
997

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

1013
/* Formatted argument error. */
1014
LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...)
4✔
1015
{
1016
  const char *msg;
4✔
1017
  va_list argp;
4✔
1018
  va_start(argp, em);
4✔
1019
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
4✔
1020
  va_end(argp);
4✔
1021
  err_argmsg(L, narg, msg);
4✔
1022
}
1023

1024
/* Argument error. */
1025
LJ_NOINLINE void lj_err_arg(lua_State *L, int narg, ErrMsg em)
30✔
1026
{
1027
  err_argmsg(L, narg, err2msg(em));
30✔
1028
}
1029

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

1053
/* Typecheck error for arguments. */
1054
LJ_NOINLINE void lj_err_argt(lua_State *L, int narg, int tt)
69✔
1055
{
1056
  lj_err_argtype(L, narg, lj_obj_typename[tt+1]);
69✔
1057
}
1058

1059
/* -- Public error handling API ------------------------------------------- */
1060

1061
LUA_API lua_CFunction lua_atpanic(lua_State *L, lua_CFunction panicf)
×
1062
{
1063
  lua_CFunction old = G(L)->panic;
×
1064
  G(L)->panic = panicf;
×
1065
  return old;
×
1066
}
1067

1068
/* Forwarders for the public API (C calling convention and no LJ_NORET). */
1069
LUA_API int lua_error(lua_State *L)
77✔
1070
{
1071
  lj_err_run(L);
77✔
1072
  return 0;  /* unreachable */
1073
}
1074

1075
LUALIB_API int luaL_argerror(lua_State *L, int narg, const char *msg)
2✔
1076
{
1077
  err_argmsg(L, narg, msg);
2✔
1078
  return 0;  /* unreachable */
1079
}
1080

1081
LUALIB_API int luaL_typerror(lua_State *L, int narg, const char *xname)
×
1082
{
1083
  lj_err_argtype(L, narg, xname);
×
1084
  return 0;  /* unreachable */
1085
}
1086

1087
LUALIB_API void luaL_where(lua_State *L, int level)
21✔
1088
{
1089
  int size;
21✔
1090
  cTValue *frame = lj_debug_frame(L, level, &size);
21✔
1091
  lj_debug_addloc(L, "", frame, size ? frame+size : NULL);
21✔
1092
}
21✔
1093

1094
LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...)
56✔
1095
{
1096
  const char *msg;
56✔
1097
  va_list argp;
56✔
1098
  va_start(argp, fmt);
56✔
1099
  msg = lj_strfmt_pushvf(L, fmt, argp);
56✔
1100
  va_end(argp);
56✔
1101
  lj_err_callermsg(L, msg);
56✔
1102
  return 0;  /* unreachable */
1103
}
1104

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

© 2025 Coveralls, Inc