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

tarantool / luajit / 7262987147

19 Dec 2023 02:10PM UTC coverage: 88.225% (-0.4%) from 88.616%
7262987147

push

github

fckxorg
test: add tests for debugging extensions

This patch adds tests for LuaJIT debugging
extensions for lldb and gdb.

5336 of 5969 branches covered (0.0%)

Branch coverage included in aggregate %.

20475 of 23287 relevant lines covered (87.92%)

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

108
/* Unwind until stop frame. Optionally cleanup frames. */
109
static void *err_unwind(lua_State *L, void *stopcf, int errcode)
53,796✔
110
{
111
  TValue *frame = L->base-1;
53,796✔
112
  void *cf = L->cframe;
53,796✔
113
  while (cf) {
318,828✔
114
    int32_t nres = cframe_nres(cframe_raw(cf));
318,828✔
115
    if (nres < 0) {  /* C frame without Lua frame? */
318,828✔
116
      TValue *top = restorestack(L, -nres);
26,966✔
117
      if (frame < top) {  /* Frame reached? */
26,966✔
118
        if (errcode) {
26,966✔
119
          L->base = frame+1;
13,483✔
120
          L->cframe = cframe_prev(cf);
13,483✔
121
          unwindstack(L, top);
13,483✔
122
        }
123
        return cf;
26,966✔
124
      }
125
    }
126
    if (frame <= tvref(L->stack)+LJ_FR2)
291,862✔
127
      break;
128
    switch (frame_typep(frame)) {
291,862✔
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. */
62✔
153
      if (cframe_canyield(cf)) {  /* Resume? */
62✔
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) {
42✔
162
        L->base = frame_prevd(frame) + 1;
21✔
163
        L->cframe = cframe_prev(cf);
21✔
164
        unwindstack(L, frame - LJ_FR2);
21✔
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,752✔
175
    case FRAME_PCALLH:  /* FF pcall() frame inside hook. */
176
      if (errcode) {
26,752✔
177
        if (errcode == LUA_YIELD) {
13,376✔
178
          frame = frame_prevd(frame);
×
179
          break;
×
180
        }
181
        if (frame_typep(frame) == FRAME_PCALL)
13,376✔
182
          hook_leave(G(L));
13,375✔
183
        L->base = frame_prevd(frame) + 1;
13,376✔
184
        L->cframe = cf;
13,376✔
185
        unwindstack(L, L->base);
13,376✔
186
      }
187
      return (void *)((intptr_t)cf | CFRAME_UNWIND_FF);
26,752✔
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,796✔
415
  uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx)
416
{
417
  void *cf;
53,796✔
418
  lua_State *L;
53,796✔
419
  if (version != 1)
53,796✔
420
    return _URC_FATAL_PHASE1_ERROR;
421
  cf = (void *)_Unwind_GetCFA(ctx);
53,796✔
422
  L = cframe_L(cf);
53,796✔
423
  if ((actions & _UA_SEARCH_PHASE)) {
53,796✔
424
#if LJ_UNWIND_EXT
425
    if (err_unwind(L, cf, 0) == NULL)
26,898✔
426
      return _URC_CONTINUE_UNWIND;
427
#endif
428
    if (!LJ_UEXCLASS_CHECK(uexclass)) {
26,890✔
429
      setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
×
430
    }
431
    return _URC_HANDLER_FOUND;
26,890✔
432
  }
433
  if ((actions & _UA_CLEANUP_PHASE)) {
26,898✔
434
    int errcode;
26,898✔
435
    if (LJ_UEXCLASS_CHECK(uexclass)) {
26,898✔
436
      errcode = LJ_UEXCLASS_ERRCODE(uexclass);
26,898✔
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,898✔
444
    if ((actions & _UA_FORCE_UNWIND)) {
26,898✔
445
      return _URC_CONTINUE_UNWIND;
446
    } else if (cf) {
26,898✔
447
      _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode);
26,890✔
448
      _Unwind_SetIP(ctx, (uintptr_t)(cframe_unwind_ff(cf) ?
26,890✔
449
                                     lj_vm_unwind_ff_eh :
450
                                     lj_vm_unwind_c_eh));
451
      return _URC_INSTALL_CONTEXT;
26,890✔
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)
321✔
582
{
583
  void **handler;
321✔
584
  memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template));
321✔
585
  handler = (void *)err_unwind_jit;
321✔
586
  memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler));
321✔
587
  *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) =
321✔
588
    (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base));
321✔
589
  __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER);
321✔
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);
321✔
598
}
599

600
void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info)
318✔
601
{
602
  UNUSED(base); UNUSED(sz);
318✔
603
  __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER);
318✔
604
}
318✔
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,891✔
723
{
724
  memset(&static_uex, 0, sizeof(static_uex));
26,891✔
725
  static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode);
26,891✔
726
  static_uex.g = g;
26,891✔
727
  _Unwind_RaiseException(&static_uex.ex);
26,891✔
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,891✔
738
{
739
  global_State *g = G(L);
26,891✔
740
  lj_trace_abort(g);
26,891✔
741
  L->status = LUA_OK;
26,891✔
742
#if LJ_UNWIND_EXT
743
  err_raise_ext(g, errcode);
26,891✔
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)
257✔
771
{
772
  return lj_str_newz(L, err2msg(em));
257✔
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,409✔
787
{
788
  cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2;
13,409✔
789
  void *cf = L->cframe;
13,409✔
790
  while (frame > bot && cf) {
145,944✔
791
    while (cframe_nres(cframe_raw(cf)) < 0) {  /* cframe without frame? */
145,935✔
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,931✔
801
    case FRAME_LUA:
131,120✔
802
    case FRAME_LUAP:
803
      frame = frame_prevl(frame);
131,120✔
804
      break;
131,120✔
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:
31✔
817
      if (cframe_canyield(cf)) return 0;
31✔
818
      if (cframe_errfunc(cf) >= 0)
23✔
819
        return cframe_errfunc(cf);
10✔
820
      cf = cframe_prev(cf);
13✔
821
      frame = frame_prevd(frame);
13✔
822
      break;
13✔
823
    case FRAME_PCALL:
13,378✔
824
    case FRAME_PCALLH:
825
      if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall)
13,378✔
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,410✔
838
{
839
  ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L);
13,410✔
840
  if (ef) {
13,409✔
841
    TValue *errfunc = restorestack(L, ef);
21✔
842
    TValue *top = L->top;
21✔
843
    lj_trace_abort(G(L));
21✔
844
    if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) {
21✔
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;
18✔
849
    copyTV(L, top+LJ_FR2, top-1);
18✔
850
    copyTV(L, top-1, errfunc);
18✔
851
    if (LJ_FR2) setnilV(top++);
18✔
852
    L->top = top+1;
18✔
853
    lj_vm_call(L, top, 1+1);  /* Stack: |errfunc|msg| -> |msg| */
18✔
854
  }
855
  lj_err_throw(L, LUA_ERRRUN);
13,404✔
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,096✔
870
{
871
  const char *msg;
13,096✔
872
  va_list argp;
13,096✔
873
  va_start(argp, em);
13,096✔
874
  if (curr_funcisL(L)) L->top = curr_topL(L);
13,096✔
875
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
13,096✔
876
  va_end(argp);
13,096✔
877
  lj_debug_addloc(L, msg, L->base-1, NULL);
13,096✔
878
  lj_err_run(L);
13,096✔
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,487✔
903
{
904
  const char *tname = lj_typename(o);
1,487✔
905
  const char *opname = err2msg(opm);
1,487✔
906
  if (curr_funcisL(L)) {
1,487✔
907
    GCproto *pt = curr_proto(L);
1,487✔
908
    const BCIns *pc = cframe_Lpc(L) - 1;
1,487✔
909
    const char *oname = NULL;
1,487✔
910
    const char *kind = lj_debug_slotname(pt, pc, (BCReg)(o-L->base), &oname);
1,487✔
911
    if (kind)
1,487✔
912
      err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname);
423✔
913
  }
914
  err_msgv(L, LJ_ERR_BADOPRV, opname, tname);
1,064✔
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,713✔
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,713✔
934
  if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) {
11,713✔
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);
206✔
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)
77✔
1062
{
1063
  lj_err_run(L);
77✔
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)
21✔
1080
{
1081
  int size;
21✔
1082
  cTValue *frame = lj_debug_frame(L, level, &size);
21✔
1083
  lj_debug_addloc(L, "", frame, size ? frame+size : NULL);
21✔
1084
}
21✔
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

© 2025 Coveralls, Inc