summaryrefslogtreecommitdiff
path: root/src/lj_err.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_err.c')
-rw-r--r--src/lj_err.c392
1 files changed, 10 insertions, 382 deletions
diff --git a/src/lj_err.c b/src/lj_err.c
index 61178805..8d37af6a 100644
--- a/src/lj_err.c
+++ b/src/lj_err.c
@@ -1,9 +1,6 @@
1/* 1/*
2** Error handling and debugging API. 2** Error handling.
3** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h 3** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
4**
5** Portions taken verbatim or adapted from the Lua interpreter.
6** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7*/ 4*/
8 5
9#define lj_err_c 6#define lj_err_c
@@ -11,12 +8,11 @@
11 8
12#include "lj_obj.h" 9#include "lj_obj.h"
13#include "lj_err.h" 10#include "lj_err.h"
11#include "lj_debug.h"
14#include "lj_str.h" 12#include "lj_str.h"
15#include "lj_tab.h"
16#include "lj_func.h" 13#include "lj_func.h"
17#include "lj_state.h" 14#include "lj_state.h"
18#include "lj_frame.h" 15#include "lj_frame.h"
19#include "lj_bc.h"
20#include "lj_ff.h" 16#include "lj_ff.h"
21#include "lj_trace.h" 17#include "lj_trace.h"
22#include "lj_vm.h" 18#include "lj_vm.h"
@@ -78,355 +74,6 @@ LJ_DATADEF const char *lj_err_allmsg =
78#include "lj_errmsg.h" 74#include "lj_errmsg.h"
79; 75;
80 76
81/* -- Frame and function introspection ------------------------------------ */
82
83static BCPos currentpc(lua_State *L, GCfunc *fn, cTValue *nextframe)
84{
85 const BCIns *ins;
86 lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD);
87 if (!isluafunc(fn)) { /* Cannot derive a PC for non-Lua functions. */
88 return ~(BCPos)0;
89 } else if (nextframe == NULL) { /* Lua function on top. */
90 void *cf = cframe_raw(L->cframe);
91 if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
92 return ~(BCPos)0;
93 ins = cframe_pc(cf); /* Only happens during error/hook handling. */
94 } else {
95 if (frame_islua(nextframe)) {
96 ins = frame_pc(nextframe);
97 } else if (frame_iscont(nextframe)) {
98 ins = frame_contpc(nextframe);
99 } else {
100 /* Lua function below errfunc/gc/hook: find cframe to get the PC. */
101 void *cf = cframe_raw(L->cframe);
102 TValue *f = L->base-1;
103 if (cf == NULL)
104 return ~(BCPos)0;
105 while (f > nextframe) {
106 if (frame_islua(f)) {
107 f = frame_prevl(f);
108 } else {
109 if (frame_isc(f))
110 cf = cframe_raw(cframe_prev(cf));
111 f = frame_prevd(f);
112 }
113 }
114 if (cframe_prev(cf))
115 cf = cframe_raw(cframe_prev(cf));
116 ins = cframe_pc(cf);
117 }
118 }
119 return proto_bcpos(funcproto(fn), ins) - 1;
120}
121
122static BCLine currentline(lua_State *L, GCfunc *fn, cTValue *nextframe)
123{
124 BCPos pc = currentpc(L, fn, nextframe);
125 if (pc != ~(BCPos)0) {
126 GCproto *pt = funcproto(fn);
127 lua_assert(pc < pt->sizebc);
128 return proto_line(pt, pc);
129 } else {
130 return -1;
131 }
132}
133
134static const char *getvarname(const GCproto *pt, BCPos pc, BCReg slot)
135{
136 MSize i;
137 VarInfo *vi = proto_varinfo(pt);
138 for (i = 0; i < pt->sizevarinfo && vi[i].startpc <= pc; i++)
139 if (pc < vi[i].endpc && slot-- == 0)
140 return strdata(gco2str(gcref(vi[i].name)));
141 return NULL;
142}
143
144static const char *getobjname(GCproto *pt, const BCIns *ip, BCReg slot,
145 const char **name)
146{
147 const char *lname;
148restart:
149 lname = getvarname(pt, proto_bcpos(pt, ip), slot);
150 if (lname != NULL) { *name = lname; return "local"; }
151 while (--ip > proto_bc(pt)) {
152 BCIns ins = *ip;
153 BCOp op = bc_op(ins);
154 BCReg ra = bc_a(ins);
155 if (bcmode_a(op) == BCMbase) {
156 if (slot >= ra && (op != BC_KNIL || slot <= bc_d(ins)))
157 return NULL;
158 } else if (bcmode_a(op) == BCMdst && ra == slot) {
159 switch (bc_op(ins)) {
160 case BC_MOV:
161 if (ra == slot) { slot = bc_d(ins); goto restart; }
162 break;
163 case BC_GGET:
164 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_d(ins))));
165 return "global";
166 case BC_TGETS:
167 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
168 if (ip > proto_bc(pt)) {
169 BCIns insp = ip[-1];
170 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 &&
171 bc_d(insp) == bc_b(ins))
172 return "method";
173 }
174 return "field";
175 case BC_UGET:
176 *name = strdata(proto_uvname(pt, bc_d(ins)));
177 return "upvalue";
178 default:
179 return NULL;
180 }
181 }
182 }
183 return NULL;
184}
185
186static const char *getfuncname(lua_State *L, TValue *frame, const char **name)
187{
188 MMS mm;
189 const BCIns *ip;
190 TValue *pframe;
191 GCfunc *fn;
192 BCPos pc;
193 if (frame_isvarg(frame))
194 frame = frame_prevd(frame);
195 pframe = frame_prev(frame);
196 fn = frame_func(pframe);
197 pc = currentpc(L, fn, frame);
198 if (pc == ~(BCPos)0)
199 return NULL;
200 lua_assert(pc < funcproto(fn)->sizebc);
201 ip = &proto_bc(funcproto(fn))[pc];
202 mm = bcmode_mm(bc_op(*ip));
203 if (mm == MM_call) {
204 BCReg slot = bc_a(*ip);
205 if (bc_op(*ip) == BC_ITERC) slot -= 3;
206 return getobjname(funcproto(fn), ip, slot, name);
207 } else if (mm != MM__MAX) {
208 *name = strdata(mmname_str(G(L), mm));
209 return "metamethod";
210 } else {
211 return NULL;
212 }
213}
214
215void lj_err_pushloc(lua_State *L, GCproto *pt, BCPos pc)
216{
217 GCstr *name = proto_chunkname(pt);
218 if (name) {
219 const char *s = strdata(name);
220 MSize i, len = name->len;
221 BCLine line = pc < pt->sizebc ? proto_line(pt, pc) : 0;
222 if (*s == '@') {
223 s++; len--;
224 for (i = len; i > 0; i--)
225 if (s[i] == '/' || s[i] == '\\') {
226 s += i+1;
227 break;
228 }
229 lj_str_pushf(L, "%s:%d", s, line);
230 } else if (len > 40) {
231 lj_str_pushf(L, "%p:%d", pt, line);
232 } else if (*s == '=') {
233 lj_str_pushf(L, "%s:%d", s+1, line);
234 } else {
235 lj_str_pushf(L, "\"%s\":%d", s, line);
236 }
237 } else {
238 lj_str_pushf(L, "%p:%u", pt, pc);
239 }
240}
241
242static void err_chunkid(char *out, const char *src)
243{
244 if (*src == '=') {
245 strncpy(out, src+1, LUA_IDSIZE); /* remove first char */
246 out[LUA_IDSIZE-1] = '\0'; /* ensures null termination */
247 } else if (*src == '@') { /* out = "source", or "...source" */
248 size_t l = strlen(++src); /* skip the `@' */
249 if (l >= LUA_IDSIZE) {
250 src += l-(LUA_IDSIZE-4); /* get last part of file name */
251 strcpy(out, "...");
252 out += 3;
253 }
254 strcpy(out, src);
255 } else { /* out = [string "string"] */
256 size_t len; /* Length, up to first control char. */
257 for (len = 0; len < LUA_IDSIZE-12; len++)
258 if (((const unsigned char *)src)[len] < ' ') break;
259 strcpy(out, "[string \""); out += 9;
260 if (src[len] != '\0') { /* must truncate? */
261 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
262 strncpy(out, src, len); out += len;
263 strcpy(out, "..."); out += 3;
264 } else {
265 strcpy(out, src); out += len;
266 }
267 strcpy(out, "\"]");
268 }
269}
270
271/* -- Public debug API ---------------------------------------------------- */
272
273static TValue *findlocal(lua_State *L, const lua_Debug *ar,
274 const char **name, BCReg slot)
275{
276 uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
277 uint32_t size = (uint32_t)ar->i_ci >> 16;
278 TValue *frame = tvref(L->stack) + offset;
279 TValue *nextframe = size ? frame + size : NULL;
280 GCfunc *fn = frame_func(frame);
281 BCPos pc = currentpc(L, fn, nextframe);
282 if (pc != ~(BCPos)0 &&
283 (*name = getvarname(funcproto(fn), pc, slot-1)) != NULL)
284 ;
285 else if (slot > 0 && frame + slot < (nextframe ? nextframe : L->top))
286 *name = "(*temporary)";
287 else
288 *name = NULL;
289 return frame+slot;
290}
291
292LUA_API const char *lua_getlocal(lua_State *L, const lua_Debug *ar, int n)
293{
294 const char *name;
295 TValue *o = findlocal(L, ar, &name, (BCReg)n);
296 if (name) {
297 copyTV(L, L->top, o);
298 incr_top(L);
299 }
300 return name;
301}
302
303
304LUA_API const char *lua_setlocal(lua_State *L, const lua_Debug *ar, int n)
305{
306 const char *name;
307 TValue *o = findlocal(L, ar, &name, (BCReg)n);
308 if (name)
309 copyTV(L, o, L->top-1);
310 L->top--;
311 return name;
312}
313
314LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
315{
316 int status = 1;
317 TValue *frame = NULL;
318 TValue *nextframe = NULL;
319 GCfunc *fn;
320 if (*what == '>') {
321 TValue *func = L->top - 1;
322 api_check(L, tvisfunc(func));
323 fn = funcV(func);
324 L->top--;
325 what++;
326 } else {
327 uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
328 uint32_t size = (uint32_t)ar->i_ci >> 16;
329 lua_assert(offset != 0);
330 frame = tvref(L->stack) + offset;
331 if (size) nextframe = frame + size;
332 lua_assert(frame <= tvref(L->maxstack) &&
333 (!nextframe || nextframe <= tvref(L->maxstack)));
334 fn = frame_func(frame);
335 lua_assert(fn->c.gct == ~LJ_TFUNC);
336 }
337 for (; *what; what++) {
338 switch (*what) {
339 case 'S':
340 if (isluafunc(fn)) {
341 GCproto *pt = funcproto(fn);
342 ar->source = strdata(proto_chunkname(pt));
343 ar->linedefined = (int)proto_line(pt, 0);
344 ar->lastlinedefined = (int)pt->lastlinedefined;
345 ar->what = (ar->linedefined == 0) ? "main" : "Lua";
346 } else {
347 ar->source = "=[C]";
348 ar->linedefined = -1;
349 ar->lastlinedefined = -1;
350 ar->what = "C";
351 }
352 err_chunkid(ar->short_src, ar->source);
353 break;
354 case 'l':
355 ar->currentline = frame ? currentline(L, fn, nextframe) : -1;
356 break;
357 case 'u':
358 ar->nups = fn->c.nupvalues;
359 break;
360 case 'n':
361 ar->namewhat = frame ? getfuncname(L, frame, &ar->name) : NULL;
362 if (ar->namewhat == NULL) {
363 ar->namewhat = "";
364 ar->name = NULL;
365 }
366 break;
367 case 'f':
368 setfuncV(L, L->top, fn);
369 incr_top(L);
370 break;
371 case 'L':
372 if (isluafunc(fn)) {
373 GCtab *t = lj_tab_new(L, 0, 0);
374 GCproto *pt = funcproto(fn);
375 BCLine *lineinfo = proto_lineinfo(pt);
376 MSize i, szl = pt->sizebc;
377 for (i = 1; i < szl; i++)
378 setboolV(lj_tab_setint(L, t, lineinfo[i]), 1);
379 settabV(L, L->top, t);
380 } else {
381 setnilV(L->top);
382 }
383 incr_top(L);
384 break;
385 default:
386 status = 0; /* Bad option. */
387 break;
388 }
389 }
390 return status;
391}
392
393cTValue *lj_err_getframe(lua_State *L, int level, int *size)
394{
395 cTValue *frame, *nextframe, *bot = tvref(L->stack);
396 /* Traverse frames backwards. */
397 for (nextframe = frame = L->base-1; frame > bot; ) {
398 if (frame_gc(frame) == obj2gco(L))
399 level++; /* Skip dummy frames. See lj_meta_call(). */
400 if (level-- == 0) {
401 *size = (int)(nextframe - frame);
402 return frame; /* Level found. */
403 }
404 nextframe = frame;
405 if (frame_islua(frame)) {
406 frame = frame_prevl(frame);
407 } else {
408 if (frame_isvarg(frame))
409 level++; /* Skip vararg pseudo-frame. */
410 frame = frame_prevd(frame);
411 }
412 }
413 *size = level;
414 return NULL; /* Level not found. */
415}
416
417LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
418{
419 int size;
420 cTValue *frame = lj_err_getframe(L, level, &size);
421 if (frame) {
422 ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
423 return 1;
424 } else {
425 ar->i_ci = level - size;
426 return 0;
427 }
428}
429
430/* -- Internal frame unwinding -------------------------------------------- */ 77/* -- Internal frame unwinding -------------------------------------------- */
431 78
432/* Unwind Lua stack and move error message to new top. */ 79/* Unwind Lua stack and move error message to new top. */
@@ -854,25 +501,6 @@ LJ_NOINLINE void lj_err_run(lua_State *L)
854 lj_err_throw(L, LUA_ERRRUN); 501 lj_err_throw(L, LUA_ERRRUN);
855} 502}
856 503
857/* Add location to error message. */
858LJ_NOINLINE static void err_loc(lua_State *L, const char *msg,
859 cTValue *frame, cTValue *nextframe)
860{
861 if (frame) {
862 GCfunc *fn = frame_func(frame);
863 if (isluafunc(fn)) {
864 char buff[LUA_IDSIZE];
865 BCLine line = currentline(L, fn, nextframe);
866 if (line >= 0) {
867 err_chunkid(buff, strdata(proto_chunkname(funcproto(fn))));
868 lj_str_pushf(L, "%s:%d: %s", buff, line, msg);
869 return;
870 }
871 }
872 }
873 lj_str_pushf(L, "%s", msg);
874}
875
876/* Formatted runtime error message. */ 504/* Formatted runtime error message. */
877LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) 505LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...)
878{ 506{
@@ -882,7 +510,7 @@ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...)
882 if (curr_funcisL(L)) L->top = curr_topL(L); 510 if (curr_funcisL(L)) L->top = curr_topL(L);
883 msg = lj_str_pushvf(L, err2msg(em), argp); 511 msg = lj_str_pushvf(L, err2msg(em), argp);
884 va_end(argp); 512 va_end(argp);
885 err_loc(L, msg, L->base-1, NULL); 513 lj_debug_addloc(L, msg, L->base-1, NULL);
886 lj_err_run(L); 514 lj_err_run(L);
887} 515}
888 516
@@ -898,7 +526,7 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, const char *src, const char *tok,
898{ 526{
899 char buff[LUA_IDSIZE]; 527 char buff[LUA_IDSIZE];
900 const char *msg; 528 const char *msg;
901 err_chunkid(buff, src); 529 lj_debug_shortname(buff, src);
902 msg = lj_str_pushvf(L, err2msg(em), argp); 530 msg = lj_str_pushvf(L, err2msg(em), argp);
903 msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); 531 msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg);
904 if (tok) 532 if (tok)
@@ -910,12 +538,12 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, const char *src, const char *tok,
910LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm) 538LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm)
911{ 539{
912 const char *tname = typename(o); 540 const char *tname = typename(o);
913 const char *oname = NULL;
914 const char *opname = err2msg(opm); 541 const char *opname = err2msg(opm);
915 if (curr_funcisL(L)) { 542 if (curr_funcisL(L)) {
916 GCproto *pt = curr_proto(L); 543 GCproto *pt = curr_proto(L);
917 const BCIns *pc = cframe_Lpc(L) - 1; 544 const BCIns *pc = cframe_Lpc(L) - 1;
918 const char *kind = getobjname(pt, pc, (BCReg)(o - L->base), &oname); 545 const char *oname = NULL;
546 const char *kind = lj_debug_slotname(pt, pc, (BCReg)(o-L->base), &oname);
919 if (kind) 547 if (kind)
920 err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname); 548 err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname);
921 } 549 }
@@ -967,7 +595,7 @@ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg)
967 } 595 }
968#endif 596#endif
969 } 597 }
970 err_loc(L, msg, pframe, frame); 598 lj_debug_addloc(L, msg, pframe, frame);
971 lj_err_run(L); 599 lj_err_run(L);
972} 600}
973 601
@@ -993,7 +621,7 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg,
993 const char *msg) 621 const char *msg)
994{ 622{
995 const char *fname = "?"; 623 const char *fname = "?";
996 const char *ftype = getfuncname(L, L->base - 1, &fname); 624 const char *ftype = lj_debug_funcname(L, L->base - 1, &fname);
997 if (narg < 0 && narg > LUA_REGISTRYINDEX) 625 if (narg < 0 && narg > LUA_REGISTRYINDEX)
998 narg = (int)(L->top - L->base) + narg + 1; 626 narg = (int)(L->top - L->base) + narg + 1;
999 if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ 627 if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */
@@ -1066,8 +694,8 @@ LUALIB_API int luaL_typerror(lua_State *L, int narg, const char *xname)
1066LUALIB_API void luaL_where(lua_State *L, int level) 694LUALIB_API void luaL_where(lua_State *L, int level)
1067{ 695{
1068 int size; 696 int size;
1069 cTValue *frame = lj_err_getframe(L, level, &size); 697 cTValue *frame = lj_debug_frame(L, level, &size);
1070 err_loc(L, "", frame, size ? frame+size : NULL); 698 lj_debug_addloc(L, "", frame, size ? frame+size : NULL);
1071} 699}
1072 700
1073LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) 701LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...)