aboutsummaryrefslogtreecommitdiff
path: root/src/lj_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_debug.c')
-rw-r--r--src/lj_debug.c204
1 files changed, 150 insertions, 54 deletions
diff --git a/src/lj_debug.c b/src/lj_debug.c
index afa94384..03d86651 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -9,12 +9,12 @@
9#include "lj_obj.h" 9#include "lj_obj.h"
10#include "lj_err.h" 10#include "lj_err.h"
11#include "lj_debug.h" 11#include "lj_debug.h"
12#include "lj_str.h" 12#include "lj_buf.h"
13#include "lj_tab.h" 13#include "lj_tab.h"
14#include "lj_state.h" 14#include "lj_state.h"
15#include "lj_frame.h" 15#include "lj_frame.h"
16#include "lj_bc.h" 16#include "lj_bc.h"
17#include "lj_vm.h" 17#include "lj_strfmt.h"
18#if LJ_HASJIT 18#if LJ_HASJIT
19#include "lj_jit.h" 19#include "lj_jit.h"
20#endif 20#endif
@@ -24,11 +24,11 @@
24/* Get frame corresponding to a level. */ 24/* Get frame corresponding to a level. */
25cTValue *lj_debug_frame(lua_State *L, int level, int *size) 25cTValue *lj_debug_frame(lua_State *L, int level, int *size)
26{ 26{
27 cTValue *frame, *nextframe, *bot = tvref(L->stack); 27 cTValue *frame, *nextframe, *bot = tvref(L->stack)+LJ_FR2;
28 /* Traverse frames backwards. */ 28 /* Traverse frames backwards. */
29 for (nextframe = frame = L->base-1; frame > bot; ) { 29 for (nextframe = frame = L->base-1; frame > bot; ) {
30 if (frame_gc(frame) == obj2gco(L)) 30 if (frame_gc(frame) == obj2gco(L))
31 level++; /* Skip dummy frames. See lj_meta_call(). */ 31 level++; /* Skip dummy frames. See lj_err_optype_call(). */
32 if (level-- == 0) { 32 if (level-- == 0) {
33 *size = (int)(nextframe - frame); 33 *size = (int)(nextframe - frame);
34 return frame; /* Level found. */ 34 return frame; /* Level found. */
@@ -55,7 +55,8 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
55 const BCIns *ins; 55 const BCIns *ins;
56 GCproto *pt; 56 GCproto *pt;
57 BCPos pos; 57 BCPos pos;
58 lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD); 58 lj_assertL(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD,
59 "function or frame expected");
59 if (!isluafunc(fn)) { /* Cannot derive a PC for non-Lua functions. */ 60 if (!isluafunc(fn)) { /* Cannot derive a PC for non-Lua functions. */
60 return NO_BCPOS; 61 return NO_BCPOS;
61 } else if (nextframe == NULL) { /* Lua function on top. */ 62 } else if (nextframe == NULL) { /* Lua function on top. */
@@ -88,8 +89,7 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
88 if (frame_islua(f)) { 89 if (frame_islua(f)) {
89 f = frame_prevl(f); 90 f = frame_prevl(f);
90 } else { 91 } else {
91 if (frame_isc(f) || (LJ_HASFFI && frame_iscont(f) && 92 if (frame_isc(f) || (frame_iscont(f) && frame_iscont_fficb(f)))
92 (f-1)->u32.lo == LJ_CONT_FFI_CALLBACK))
93 cf = cframe_raw(cframe_prev(cf)); 93 cf = cframe_raw(cframe_prev(cf));
94 f = frame_prevd(f); 94 f = frame_prevd(f);
95 } 95 }
@@ -107,7 +107,7 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
107 GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins)); 107 GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
108 pos = proto_bcpos(pt, mref(T->startpc, const BCIns)); 108 pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
109 } else { 109 } else {
110 pos = NO_BCPOS; /* Punt in case of stack overflow. */ 110 pos = NO_BCPOS; /* Punt in case of stack overflow for stitched trace. */
111 } 111 }
112 } 112 }
113#endif 113#endif
@@ -140,7 +140,7 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
140 BCPos pc = debug_framepc(L, fn, nextframe); 140 BCPos pc = debug_framepc(L, fn, nextframe);
141 if (pc != NO_BCPOS) { 141 if (pc != NO_BCPOS) {
142 GCproto *pt = funcproto(fn); 142 GCproto *pt = funcproto(fn);
143 lua_assert(pc <= pt->sizebc); 143 lj_assertL(pc <= pt->sizebc, "PC out of range");
144 return lj_debug_line(pt, pc); 144 return lj_debug_line(pt, pc);
145 } 145 }
146 return -1; 146 return -1;
@@ -148,38 +148,25 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
148 148
149/* -- Variable names ------------------------------------------------------ */ 149/* -- Variable names ------------------------------------------------------ */
150 150
151/* Read ULEB128 value. */
152static uint32_t debug_read_uleb128(const uint8_t **pp)
153{
154 const uint8_t *p = *pp;
155 uint32_t v = *p++;
156 if (LJ_UNLIKELY(v >= 0x80)) {
157 int sh = 0;
158 v &= 0x7f;
159 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
160 }
161 *pp = p;
162 return v;
163}
164
165/* Get name of a local variable from slot number and PC. */ 151/* Get name of a local variable from slot number and PC. */
166static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot) 152static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
167{ 153{
168 const uint8_t *p = proto_varinfo(pt); 154 const char *p = (const char *)proto_varinfo(pt);
169 if (p) { 155 if (p) {
170 BCPos lastpc = 0; 156 BCPos lastpc = 0;
171 for (;;) { 157 for (;;) {
172 const char *name = (const char *)p; 158 const char *name = p;
173 uint32_t vn = *p++; 159 uint32_t vn = *(const uint8_t *)p;
174 BCPos startpc, endpc; 160 BCPos startpc, endpc;
175 if (vn < VARNAME__MAX) { 161 if (vn < VARNAME__MAX) {
176 if (vn == VARNAME_END) break; /* End of varinfo. */ 162 if (vn == VARNAME_END) break; /* End of varinfo. */
177 } else { 163 } else {
178 while (*p++) ; /* Skip over variable name string. */ 164 do { p++; } while (*(const uint8_t *)p); /* Skip over variable name. */
179 } 165 }
180 lastpc = startpc = lastpc + debug_read_uleb128(&p); 166 p++;
167 lastpc = startpc = lastpc + lj_buf_ruleb128(&p);
181 if (startpc > pc) break; 168 if (startpc > pc) break;
182 endpc = startpc + debug_read_uleb128(&p); 169 endpc = startpc + lj_buf_ruleb128(&p);
183 if (pc < endpc && slot-- == 0) { 170 if (pc < endpc && slot-- == 0) {
184 if (vn < VARNAME__MAX) { 171 if (vn < VARNAME__MAX) {
185#define VARNAMESTR(name, str) str "\0" 172#define VARNAMESTR(name, str) str "\0"
@@ -204,7 +191,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
204 TValue *nextframe = size ? frame + size : NULL; 191 TValue *nextframe = size ? frame + size : NULL;
205 GCfunc *fn = frame_func(frame); 192 GCfunc *fn = frame_func(frame);
206 BCPos pc = debug_framepc(L, fn, nextframe); 193 BCPos pc = debug_framepc(L, fn, nextframe);
207 if (!nextframe) nextframe = L->top; 194 if (!nextframe) nextframe = L->top+LJ_FR2;
208 if ((int)slot1 < 0) { /* Negative slot number is for varargs. */ 195 if ((int)slot1 < 0) { /* Negative slot number is for varargs. */
209 if (pc != NO_BCPOS) { 196 if (pc != NO_BCPOS) {
210 GCproto *pt = funcproto(fn); 197 GCproto *pt = funcproto(fn);
@@ -214,7 +201,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
214 nextframe = frame; 201 nextframe = frame;
215 frame = frame_prevd(frame); 202 frame = frame_prevd(frame);
216 } 203 }
217 if (frame + slot1 < nextframe) { 204 if (frame + slot1+LJ_FR2 < nextframe) {
218 *name = "(*vararg)"; 205 *name = "(*vararg)";
219 return frame+slot1; 206 return frame+slot1;
220 } 207 }
@@ -225,7 +212,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
225 if (pc != NO_BCPOS && 212 if (pc != NO_BCPOS &&
226 (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL) 213 (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
227 ; 214 ;
228 else if (slot1 > 0 && frame + slot1 < nextframe) 215 else if (slot1 > 0 && frame + slot1+LJ_FR2 < nextframe)
229 *name = "(*temporary)"; 216 *name = "(*temporary)";
230 return frame+slot1; 217 return frame+slot1;
231} 218}
@@ -234,7 +221,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
234const char *lj_debug_uvname(GCproto *pt, uint32_t idx) 221const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
235{ 222{
236 const uint8_t *p = proto_uvinfo(pt); 223 const uint8_t *p = proto_uvinfo(pt);
237 lua_assert(idx < pt->sizeuv); 224 lj_assertX(idx < pt->sizeuv, "bad upvalue index");
238 if (!p) return ""; 225 if (!p) return "";
239 if (idx) while (*p++ || --idx) ; 226 if (idx) while (*p++ || --idx) ;
240 return (const char *)p; 227 return (const char *)p;
@@ -291,7 +278,7 @@ restart:
291 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins)))); 278 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
292 if (ip > proto_bc(pt)) { 279 if (ip > proto_bc(pt)) {
293 BCIns insp = ip[-1]; 280 BCIns insp = ip[-1];
294 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 && 281 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1+LJ_FR2 &&
295 bc_d(insp) == bc_b(ins)) 282 bc_d(insp) == bc_b(ins))
296 return "method"; 283 return "method";
297 } 284 }
@@ -308,12 +295,12 @@ restart:
308} 295}
309 296
310/* Deduce function name from caller of a frame. */ 297/* Deduce function name from caller of a frame. */
311const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name) 298const char *lj_debug_funcname(lua_State *L, cTValue *frame, const char **name)
312{ 299{
313 TValue *pframe; 300 cTValue *pframe;
314 GCfunc *fn; 301 GCfunc *fn;
315 BCPos pc; 302 BCPos pc;
316 if (frame <= tvref(L->stack)) 303 if (frame <= tvref(L->stack)+LJ_FR2)
317 return NULL; 304 return NULL;
318 if (frame_isvarg(frame)) 305 if (frame_isvarg(frame))
319 frame = frame_prevd(frame); 306 frame = frame_prevd(frame);
@@ -339,7 +326,7 @@ const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name)
339/* -- Source code locations ----------------------------------------------- */ 326/* -- Source code locations ----------------------------------------------- */
340 327
341/* Generate shortened source name. */ 328/* Generate shortened source name. */
342void lj_debug_shortname(char *out, GCstr *str) 329void lj_debug_shortname(char *out, GCstr *str, BCLine line)
343{ 330{
344 const char *src = strdata(str); 331 const char *src = strdata(str);
345 if (*src == '=') { 332 if (*src == '=') {
@@ -353,11 +340,11 @@ void lj_debug_shortname(char *out, GCstr *str)
353 *out++ = '.'; *out++ = '.'; *out++ = '.'; 340 *out++ = '.'; *out++ = '.'; *out++ = '.';
354 } 341 }
355 strcpy(out, src); 342 strcpy(out, src);
356 } else { /* Output [string "string"]. */ 343 } else { /* Output [string "string"] or [builtin:name]. */
357 size_t len; /* Length, up to first control char. */ 344 size_t len; /* Length, up to first control char. */
358 for (len = 0; len < LUA_IDSIZE-12; len++) 345 for (len = 0; len < LUA_IDSIZE-12; len++)
359 if (((const unsigned char *)src)[len] < ' ') break; 346 if (((const unsigned char *)src)[len] < ' ') break;
360 strcpy(out, "[string \""); out += 9; 347 strcpy(out, line == ~(BCLine)0 ? "[builtin:" : "[string \""); out += 9;
361 if (src[len] != '\0') { /* Must truncate? */ 348 if (src[len] != '\0') { /* Must truncate? */
362 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15; 349 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
363 strncpy(out, src, len); out += len; 350 strncpy(out, src, len); out += len;
@@ -365,7 +352,7 @@ void lj_debug_shortname(char *out, GCstr *str)
365 } else { 352 } else {
366 strcpy(out, src); out += len; 353 strcpy(out, src); out += len;
367 } 354 }
368 strcpy(out, "\"]"); 355 strcpy(out, line == ~(BCLine)0 ? "]" : "\"]");
369 } 356 }
370} 357}
371 358
@@ -378,14 +365,15 @@ void lj_debug_addloc(lua_State *L, const char *msg,
378 if (isluafunc(fn)) { 365 if (isluafunc(fn)) {
379 BCLine line = debug_frameline(L, fn, nextframe); 366 BCLine line = debug_frameline(L, fn, nextframe);
380 if (line >= 0) { 367 if (line >= 0) {
368 GCproto *pt = funcproto(fn);
381 char buf[LUA_IDSIZE]; 369 char buf[LUA_IDSIZE];
382 lj_debug_shortname(buf, proto_chunkname(funcproto(fn))); 370 lj_debug_shortname(buf, proto_chunkname(pt), pt->firstline);
383 lj_str_pushf(L, "%s:%d: %s", buf, line, msg); 371 lj_strfmt_pushf(L, "%s:%d: %s", buf, line, msg);
384 return; 372 return;
385 } 373 }
386 } 374 }
387 } 375 }
388 lj_str_pushf(L, "%s", msg); 376 lj_strfmt_pushf(L, "%s", msg);
389} 377}
390 378
391/* Push location string for a bytecode position to Lua stack. */ 379/* Push location string for a bytecode position to Lua stack. */
@@ -395,20 +383,22 @@ void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
395 const char *s = strdata(name); 383 const char *s = strdata(name);
396 MSize i, len = name->len; 384 MSize i, len = name->len;
397 BCLine line = lj_debug_line(pt, pc); 385 BCLine line = lj_debug_line(pt, pc);
398 if (*s == '@') { 386 if (pt->firstline == ~(BCLine)0) {
387 lj_strfmt_pushf(L, "builtin:%s", s);
388 } else if (*s == '@') {
399 s++; len--; 389 s++; len--;
400 for (i = len; i > 0; i--) 390 for (i = len; i > 0; i--)
401 if (s[i] == '/' || s[i] == '\\') { 391 if (s[i] == '/' || s[i] == '\\') {
402 s += i+1; 392 s += i+1;
403 break; 393 break;
404 } 394 }
405 lj_str_pushf(L, "%s:%d", s, line); 395 lj_strfmt_pushf(L, "%s:%d", s, line);
406 } else if (len > 40) { 396 } else if (len > 40) {
407 lj_str_pushf(L, "%p:%d", pt, line); 397 lj_strfmt_pushf(L, "%p:%d", pt, line);
408 } else if (*s == '=') { 398 } else if (*s == '=') {
409 lj_str_pushf(L, "%s:%d", s+1, line); 399 lj_strfmt_pushf(L, "%s:%d", s+1, line);
410 } else { 400 } else {
411 lj_str_pushf(L, "\"%s\":%d", s, line); 401 lj_strfmt_pushf(L, "\"%s\":%d", s, line);
412 } 402 }
413} 403}
414 404
@@ -456,13 +446,14 @@ int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext)
456 } else { 446 } else {
457 uint32_t offset = (uint32_t)ar->i_ci & 0xffff; 447 uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
458 uint32_t size = (uint32_t)ar->i_ci >> 16; 448 uint32_t size = (uint32_t)ar->i_ci >> 16;
459 lua_assert(offset != 0); 449 lj_assertL(offset != 0, "bad frame offset");
460 frame = tvref(L->stack) + offset; 450 frame = tvref(L->stack) + offset;
461 if (size) nextframe = frame + size; 451 if (size) nextframe = frame + size;
462 lua_assert(frame <= tvref(L->maxstack) && 452 lj_assertL(frame <= tvref(L->maxstack) &&
463 (!nextframe || nextframe <= tvref(L->maxstack))); 453 (!nextframe || nextframe <= tvref(L->maxstack)),
454 "broken frame chain");
464 fn = frame_func(frame); 455 fn = frame_func(frame);
465 lua_assert(fn->c.gct == ~LJ_TFUNC); 456 lj_assertL(fn->c.gct == ~LJ_TFUNC, "bad frame function");
466 } 457 }
467 for (; *what; what++) { 458 for (; *what; what++) {
468 if (*what == 'S') { 459 if (*what == 'S') {
@@ -471,7 +462,7 @@ int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext)
471 BCLine firstline = pt->firstline; 462 BCLine firstline = pt->firstline;
472 GCstr *name = proto_chunkname(pt); 463 GCstr *name = proto_chunkname(pt);
473 ar->source = strdata(name); 464 ar->source = strdata(name);
474 lj_debug_shortname(ar->short_src, name); 465 lj_debug_shortname(ar->short_src, name, pt->firstline);
475 ar->linedefined = (int)firstline; 466 ar->linedefined = (int)firstline;
476 ar->lastlinedefined = (int)(firstline + pt->numline); 467 ar->lastlinedefined = (int)(firstline + pt->numline);
477 ar->what = (firstline || !pt->numline) ? "Lua" : "main"; 468 ar->what = (firstline || !pt->numline) ? "Lua" : "main";
@@ -561,6 +552,111 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
561 } 552 }
562} 553}
563 554
555#if LJ_HASPROFILE
556/* Put the chunkname into a buffer. */
557static int debug_putchunkname(SBuf *sb, GCproto *pt, int pathstrip)
558{
559 GCstr *name = proto_chunkname(pt);
560 const char *p = strdata(name);
561 if (pt->firstline == ~(BCLine)0) {
562 lj_buf_putmem(sb, "[builtin:", 9);
563 lj_buf_putstr(sb, name);
564 lj_buf_putb(sb, ']');
565 return 0;
566 }
567 if (*p == '=' || *p == '@') {
568 MSize len = name->len-1;
569 p++;
570 if (pathstrip) {
571 int i;
572 for (i = len-1; i >= 0; i--)
573 if (p[i] == '/' || p[i] == '\\') {
574 len -= i+1;
575 p = p+i+1;
576 break;
577 }
578 }
579 lj_buf_putmem(sb, p, len);
580 } else {
581 lj_buf_putmem(sb, "[string]", 8);
582 }
583 return 1;
584}
585
586/* Put a compact stack dump into a buffer. */
587void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt, int depth)
588{
589 int level = 0, dir = 1, pathstrip = 1;
590 MSize lastlen = 0;
591 if (depth < 0) { level = ~depth; depth = dir = -1; } /* Reverse frames. */
592 while (level != depth) { /* Loop through all frame. */
593 int size;
594 cTValue *frame = lj_debug_frame(L, level, &size);
595 if (frame) {
596 cTValue *nextframe = size ? frame+size : NULL;
597 GCfunc *fn = frame_func(frame);
598 const uint8_t *p = (const uint8_t *)fmt;
599 int c;
600 while ((c = *p++)) {
601 switch (c) {
602 case 'p': /* Preserve full path. */
603 pathstrip = 0;
604 break;
605 case 'F': case 'f': { /* Dump function name. */
606 const char *name;
607 const char *what = lj_debug_funcname(L, frame, &name);
608 if (what) {
609 if (c == 'F' && isluafunc(fn)) { /* Dump module:name for 'F'. */
610 GCproto *pt = funcproto(fn);
611 if (pt->firstline != ~(BCLine)0) { /* Not a bytecode builtin. */
612 debug_putchunkname(sb, pt, pathstrip);
613 lj_buf_putb(sb, ':');
614 }
615 }
616 lj_buf_putmem(sb, name, (MSize)strlen(name));
617 break;
618 } /* else: can't derive a name, dump module:line. */
619 }
620 /* fallthrough */
621 case 'l': /* Dump module:line. */
622 if (isluafunc(fn)) {
623 GCproto *pt = funcproto(fn);
624 if (debug_putchunkname(sb, pt, pathstrip)) {
625 /* Regular Lua function. */
626 BCLine line = c == 'l' ? debug_frameline(L, fn, nextframe) :
627 pt->firstline;
628 lj_buf_putb(sb, ':');
629 lj_strfmt_putint(sb, line >= 0 ? line : pt->firstline);
630 }
631 } else if (isffunc(fn)) { /* Dump numbered builtins. */
632 lj_buf_putmem(sb, "[builtin#", 9);
633 lj_strfmt_putint(sb, fn->c.ffid);
634 lj_buf_putb(sb, ']');
635 } else { /* Dump C function address. */
636 lj_buf_putb(sb, '@');
637 lj_strfmt_putptr(sb, fn->c.f);
638 }
639 break;
640 case 'Z': /* Zap trailing separator. */
641 lastlen = sbuflen(sb);
642 break;
643 default:
644 lj_buf_putb(sb, c);
645 break;
646 }
647 }
648 } else if (dir == 1) {
649 break;
650 } else {
651 level -= size; /* Reverse frame order: quickly skip missing level. */
652 }
653 level += dir;
654 }
655 if (lastlen)
656 sb->w = sb->b + lastlen; /* Zap trailing separator. */
657}
658#endif
659
564/* Number of frames for the leading and trailing part of a traceback. */ 660/* Number of frames for the leading and trailing part of a traceback. */
565#define TRACEBACK_LEVELS1 12 661#define TRACEBACK_LEVELS1 12
566#define TRACEBACK_LEVELS2 10 662#define TRACEBACK_LEVELS2 10