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 65ec26f0..112f5358 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. */
@@ -87,8 +88,7 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
87 if (frame_islua(f)) { 88 if (frame_islua(f)) {
88 f = frame_prevl(f); 89 f = frame_prevl(f);
89 } else { 90 } else {
90 if (frame_isc(f) || (LJ_HASFFI && frame_iscont(f) && 91 if (frame_isc(f) || (frame_iscont(f) && frame_iscont_fficb(f)))
91 (f-1)->u32.lo == LJ_CONT_FFI_CALLBACK))
92 cf = cframe_raw(cframe_prev(cf)); 92 cf = cframe_raw(cframe_prev(cf));
93 f = frame_prevd(f); 93 f = frame_prevd(f);
94 } 94 }
@@ -102,7 +102,7 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
102#if LJ_HASJIT 102#if LJ_HASJIT
103 if (pos > pt->sizebc) { /* Undo the effects of lj_trace_exit for JLOOP. */ 103 if (pos > pt->sizebc) { /* Undo the effects of lj_trace_exit for JLOOP. */
104 GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins)); 104 GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
105 lua_assert(bc_isret(bc_op(ins[-1]))); 105 lj_assertL(bc_isret(bc_op(ins[-1])), "return bytecode expected");
106 pos = proto_bcpos(pt, mref(T->startpc, const BCIns)); 106 pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
107 } 107 }
108#endif 108#endif
@@ -135,7 +135,7 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
135 BCPos pc = debug_framepc(L, fn, nextframe); 135 BCPos pc = debug_framepc(L, fn, nextframe);
136 if (pc != NO_BCPOS) { 136 if (pc != NO_BCPOS) {
137 GCproto *pt = funcproto(fn); 137 GCproto *pt = funcproto(fn);
138 lua_assert(pc <= pt->sizebc); 138 lj_assertL(pc <= pt->sizebc, "PC out of range");
139 return lj_debug_line(pt, pc); 139 return lj_debug_line(pt, pc);
140 } 140 }
141 return -1; 141 return -1;
@@ -143,38 +143,25 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
143 143
144/* -- Variable names ------------------------------------------------------ */ 144/* -- Variable names ------------------------------------------------------ */
145 145
146/* Read ULEB128 value. */
147static uint32_t debug_read_uleb128(const uint8_t **pp)
148{
149 const uint8_t *p = *pp;
150 uint32_t v = *p++;
151 if (LJ_UNLIKELY(v >= 0x80)) {
152 int sh = 0;
153 v &= 0x7f;
154 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
155 }
156 *pp = p;
157 return v;
158}
159
160/* Get name of a local variable from slot number and PC. */ 146/* Get name of a local variable from slot number and PC. */
161static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot) 147static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
162{ 148{
163 const uint8_t *p = proto_varinfo(pt); 149 const char *p = (const char *)proto_varinfo(pt);
164 if (p) { 150 if (p) {
165 BCPos lastpc = 0; 151 BCPos lastpc = 0;
166 for (;;) { 152 for (;;) {
167 const char *name = (const char *)p; 153 const char *name = p;
168 uint32_t vn = *p++; 154 uint32_t vn = *(const uint8_t *)p;
169 BCPos startpc, endpc; 155 BCPos startpc, endpc;
170 if (vn < VARNAME__MAX) { 156 if (vn < VARNAME__MAX) {
171 if (vn == VARNAME_END) break; /* End of varinfo. */ 157 if (vn == VARNAME_END) break; /* End of varinfo. */
172 } else { 158 } else {
173 while (*p++) ; /* Skip over variable name string. */ 159 do { p++; } while (*(const uint8_t *)p); /* Skip over variable name. */
174 } 160 }
175 lastpc = startpc = lastpc + debug_read_uleb128(&p); 161 p++;
162 lastpc = startpc = lastpc + lj_buf_ruleb128(&p);
176 if (startpc > pc) break; 163 if (startpc > pc) break;
177 endpc = startpc + debug_read_uleb128(&p); 164 endpc = startpc + lj_buf_ruleb128(&p);
178 if (pc < endpc && slot-- == 0) { 165 if (pc < endpc && slot-- == 0) {
179 if (vn < VARNAME__MAX) { 166 if (vn < VARNAME__MAX) {
180#define VARNAMESTR(name, str) str "\0" 167#define VARNAMESTR(name, str) str "\0"
@@ -199,7 +186,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
199 TValue *nextframe = size ? frame + size : NULL; 186 TValue *nextframe = size ? frame + size : NULL;
200 GCfunc *fn = frame_func(frame); 187 GCfunc *fn = frame_func(frame);
201 BCPos pc = debug_framepc(L, fn, nextframe); 188 BCPos pc = debug_framepc(L, fn, nextframe);
202 if (!nextframe) nextframe = L->top; 189 if (!nextframe) nextframe = L->top+LJ_FR2;
203 if ((int)slot1 < 0) { /* Negative slot number is for varargs. */ 190 if ((int)slot1 < 0) { /* Negative slot number is for varargs. */
204 if (pc != NO_BCPOS) { 191 if (pc != NO_BCPOS) {
205 GCproto *pt = funcproto(fn); 192 GCproto *pt = funcproto(fn);
@@ -209,7 +196,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
209 nextframe = frame; 196 nextframe = frame;
210 frame = frame_prevd(frame); 197 frame = frame_prevd(frame);
211 } 198 }
212 if (frame + slot1 < nextframe) { 199 if (frame + slot1+LJ_FR2 < nextframe) {
213 *name = "(*vararg)"; 200 *name = "(*vararg)";
214 return frame+slot1; 201 return frame+slot1;
215 } 202 }
@@ -220,7 +207,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
220 if (pc != NO_BCPOS && 207 if (pc != NO_BCPOS &&
221 (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL) 208 (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
222 ; 209 ;
223 else if (slot1 > 0 && frame + slot1 < nextframe) 210 else if (slot1 > 0 && frame + slot1+LJ_FR2 < nextframe)
224 *name = "(*temporary)"; 211 *name = "(*temporary)";
225 return frame+slot1; 212 return frame+slot1;
226} 213}
@@ -229,7 +216,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
229const char *lj_debug_uvname(GCproto *pt, uint32_t idx) 216const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
230{ 217{
231 const uint8_t *p = proto_uvinfo(pt); 218 const uint8_t *p = proto_uvinfo(pt);
232 lua_assert(idx < pt->sizeuv); 219 lj_assertX(idx < pt->sizeuv, "bad upvalue index");
233 if (!p) return ""; 220 if (!p) return "";
234 if (idx) while (*p++ || --idx) ; 221 if (idx) while (*p++ || --idx) ;
235 return (const char *)p; 222 return (const char *)p;
@@ -286,7 +273,7 @@ restart:
286 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins)))); 273 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
287 if (ip > proto_bc(pt)) { 274 if (ip > proto_bc(pt)) {
288 BCIns insp = ip[-1]; 275 BCIns insp = ip[-1];
289 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 && 276 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1+LJ_FR2 &&
290 bc_d(insp) == bc_b(ins)) 277 bc_d(insp) == bc_b(ins))
291 return "method"; 278 return "method";
292 } 279 }
@@ -303,12 +290,12 @@ restart:
303} 290}
304 291
305/* Deduce function name from caller of a frame. */ 292/* Deduce function name from caller of a frame. */
306const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name) 293const char *lj_debug_funcname(lua_State *L, cTValue *frame, const char **name)
307{ 294{
308 TValue *pframe; 295 cTValue *pframe;
309 GCfunc *fn; 296 GCfunc *fn;
310 BCPos pc; 297 BCPos pc;
311 if (frame <= tvref(L->stack)) 298 if (frame <= tvref(L->stack)+LJ_FR2)
312 return NULL; 299 return NULL;
313 if (frame_isvarg(frame)) 300 if (frame_isvarg(frame))
314 frame = frame_prevd(frame); 301 frame = frame_prevd(frame);
@@ -334,7 +321,7 @@ const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name)
334/* -- Source code locations ----------------------------------------------- */ 321/* -- Source code locations ----------------------------------------------- */
335 322
336/* Generate shortened source name. */ 323/* Generate shortened source name. */
337void lj_debug_shortname(char *out, GCstr *str) 324void lj_debug_shortname(char *out, GCstr *str, BCLine line)
338{ 325{
339 const char *src = strdata(str); 326 const char *src = strdata(str);
340 if (*src == '=') { 327 if (*src == '=') {
@@ -348,11 +335,11 @@ void lj_debug_shortname(char *out, GCstr *str)
348 *out++ = '.'; *out++ = '.'; *out++ = '.'; 335 *out++ = '.'; *out++ = '.'; *out++ = '.';
349 } 336 }
350 strcpy(out, src); 337 strcpy(out, src);
351 } else { /* Output [string "string"]. */ 338 } else { /* Output [string "string"] or [builtin:name]. */
352 size_t len; /* Length, up to first control char. */ 339 size_t len; /* Length, up to first control char. */
353 for (len = 0; len < LUA_IDSIZE-12; len++) 340 for (len = 0; len < LUA_IDSIZE-12; len++)
354 if (((const unsigned char *)src)[len] < ' ') break; 341 if (((const unsigned char *)src)[len] < ' ') break;
355 strcpy(out, "[string \""); out += 9; 342 strcpy(out, line == ~(BCLine)0 ? "[builtin:" : "[string \""); out += 9;
356 if (src[len] != '\0') { /* Must truncate? */ 343 if (src[len] != '\0') { /* Must truncate? */
357 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15; 344 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
358 strncpy(out, src, len); out += len; 345 strncpy(out, src, len); out += len;
@@ -360,7 +347,7 @@ void lj_debug_shortname(char *out, GCstr *str)
360 } else { 347 } else {
361 strcpy(out, src); out += len; 348 strcpy(out, src); out += len;
362 } 349 }
363 strcpy(out, "\"]"); 350 strcpy(out, line == ~(BCLine)0 ? "]" : "\"]");
364 } 351 }
365} 352}
366 353
@@ -373,14 +360,15 @@ void lj_debug_addloc(lua_State *L, const char *msg,
373 if (isluafunc(fn)) { 360 if (isluafunc(fn)) {
374 BCLine line = debug_frameline(L, fn, nextframe); 361 BCLine line = debug_frameline(L, fn, nextframe);
375 if (line >= 0) { 362 if (line >= 0) {
363 GCproto *pt = funcproto(fn);
376 char buf[LUA_IDSIZE]; 364 char buf[LUA_IDSIZE];
377 lj_debug_shortname(buf, proto_chunkname(funcproto(fn))); 365 lj_debug_shortname(buf, proto_chunkname(pt), pt->firstline);
378 lj_str_pushf(L, "%s:%d: %s", buf, line, msg); 366 lj_strfmt_pushf(L, "%s:%d: %s", buf, line, msg);
379 return; 367 return;
380 } 368 }
381 } 369 }
382 } 370 }
383 lj_str_pushf(L, "%s", msg); 371 lj_strfmt_pushf(L, "%s", msg);
384} 372}
385 373
386/* Push location string for a bytecode position to Lua stack. */ 374/* Push location string for a bytecode position to Lua stack. */
@@ -390,20 +378,22 @@ void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
390 const char *s = strdata(name); 378 const char *s = strdata(name);
391 MSize i, len = name->len; 379 MSize i, len = name->len;
392 BCLine line = lj_debug_line(pt, pc); 380 BCLine line = lj_debug_line(pt, pc);
393 if (*s == '@') { 381 if (pt->firstline == ~(BCLine)0) {
382 lj_strfmt_pushf(L, "builtin:%s", s);
383 } else if (*s == '@') {
394 s++; len--; 384 s++; len--;
395 for (i = len; i > 0; i--) 385 for (i = len; i > 0; i--)
396 if (s[i] == '/' || s[i] == '\\') { 386 if (s[i] == '/' || s[i] == '\\') {
397 s += i+1; 387 s += i+1;
398 break; 388 break;
399 } 389 }
400 lj_str_pushf(L, "%s:%d", s, line); 390 lj_strfmt_pushf(L, "%s:%d", s, line);
401 } else if (len > 40) { 391 } else if (len > 40) {
402 lj_str_pushf(L, "%p:%d", pt, line); 392 lj_strfmt_pushf(L, "%p:%d", pt, line);
403 } else if (*s == '=') { 393 } else if (*s == '=') {
404 lj_str_pushf(L, "%s:%d", s+1, line); 394 lj_strfmt_pushf(L, "%s:%d", s+1, line);
405 } else { 395 } else {
406 lj_str_pushf(L, "\"%s\":%d", s, line); 396 lj_strfmt_pushf(L, "\"%s\":%d", s, line);
407 } 397 }
408} 398}
409 399
@@ -451,13 +441,14 @@ int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext)
451 } else { 441 } else {
452 uint32_t offset = (uint32_t)ar->i_ci & 0xffff; 442 uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
453 uint32_t size = (uint32_t)ar->i_ci >> 16; 443 uint32_t size = (uint32_t)ar->i_ci >> 16;
454 lua_assert(offset != 0); 444 lj_assertL(offset != 0, "bad frame offset");
455 frame = tvref(L->stack) + offset; 445 frame = tvref(L->stack) + offset;
456 if (size) nextframe = frame + size; 446 if (size) nextframe = frame + size;
457 lua_assert(frame <= tvref(L->maxstack) && 447 lj_assertL(frame <= tvref(L->maxstack) &&
458 (!nextframe || nextframe <= tvref(L->maxstack))); 448 (!nextframe || nextframe <= tvref(L->maxstack)),
449 "broken frame chain");
459 fn = frame_func(frame); 450 fn = frame_func(frame);
460 lua_assert(fn->c.gct == ~LJ_TFUNC); 451 lj_assertL(fn->c.gct == ~LJ_TFUNC, "bad frame function");
461 } 452 }
462 for (; *what; what++) { 453 for (; *what; what++) {
463 if (*what == 'S') { 454 if (*what == 'S') {
@@ -466,7 +457,7 @@ int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext)
466 BCLine firstline = pt->firstline; 457 BCLine firstline = pt->firstline;
467 GCstr *name = proto_chunkname(pt); 458 GCstr *name = proto_chunkname(pt);
468 ar->source = strdata(name); 459 ar->source = strdata(name);
469 lj_debug_shortname(ar->short_src, name); 460 lj_debug_shortname(ar->short_src, name, pt->firstline);
470 ar->linedefined = (int)firstline; 461 ar->linedefined = (int)firstline;
471 ar->lastlinedefined = (int)(firstline + pt->numline); 462 ar->lastlinedefined = (int)(firstline + pt->numline);
472 ar->what = (firstline || !pt->numline) ? "Lua" : "main"; 463 ar->what = (firstline || !pt->numline) ? "Lua" : "main";
@@ -556,6 +547,111 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
556 } 547 }
557} 548}
558 549
550#if LJ_HASPROFILE
551/* Put the chunkname into a buffer. */
552static int debug_putchunkname(SBuf *sb, GCproto *pt, int pathstrip)
553{
554 GCstr *name = proto_chunkname(pt);
555 const char *p = strdata(name);
556 if (pt->firstline == ~(BCLine)0) {
557 lj_buf_putmem(sb, "[builtin:", 9);
558 lj_buf_putstr(sb, name);
559 lj_buf_putb(sb, ']');
560 return 0;
561 }
562 if (*p == '=' || *p == '@') {
563 MSize len = name->len-1;
564 p++;
565 if (pathstrip) {
566 int i;
567 for (i = len-1; i >= 0; i--)
568 if (p[i] == '/' || p[i] == '\\') {
569 len -= i+1;
570 p = p+i+1;
571 break;
572 }
573 }
574 lj_buf_putmem(sb, p, len);
575 } else {
576 lj_buf_putmem(sb, "[string]", 8);
577 }
578 return 1;
579}
580
581/* Put a compact stack dump into a buffer. */
582void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt, int depth)
583{
584 int level = 0, dir = 1, pathstrip = 1;
585 MSize lastlen = 0;
586 if (depth < 0) { level = ~depth; depth = dir = -1; } /* Reverse frames. */
587 while (level != depth) { /* Loop through all frame. */
588 int size;
589 cTValue *frame = lj_debug_frame(L, level, &size);
590 if (frame) {
591 cTValue *nextframe = size ? frame+size : NULL;
592 GCfunc *fn = frame_func(frame);
593 const uint8_t *p = (const uint8_t *)fmt;
594 int c;
595 while ((c = *p++)) {
596 switch (c) {
597 case 'p': /* Preserve full path. */
598 pathstrip = 0;
599 break;
600 case 'F': case 'f': { /* Dump function name. */
601 const char *name;
602 const char *what = lj_debug_funcname(L, frame, &name);
603 if (what) {
604 if (c == 'F' && isluafunc(fn)) { /* Dump module:name for 'F'. */
605 GCproto *pt = funcproto(fn);
606 if (pt->firstline != ~(BCLine)0) { /* Not a bytecode builtin. */
607 debug_putchunkname(sb, pt, pathstrip);
608 lj_buf_putb(sb, ':');
609 }
610 }
611 lj_buf_putmem(sb, name, (MSize)strlen(name));
612 break;
613 } /* else: can't derive a name, dump module:line. */
614 }
615 /* fallthrough */
616 case 'l': /* Dump module:line. */
617 if (isluafunc(fn)) {
618 GCproto *pt = funcproto(fn);
619 if (debug_putchunkname(sb, pt, pathstrip)) {
620 /* Regular Lua function. */
621 BCLine line = c == 'l' ? debug_frameline(L, fn, nextframe) :
622 pt->firstline;
623 lj_buf_putb(sb, ':');
624 lj_strfmt_putint(sb, line >= 0 ? line : pt->firstline);
625 }
626 } else if (isffunc(fn)) { /* Dump numbered builtins. */
627 lj_buf_putmem(sb, "[builtin#", 9);
628 lj_strfmt_putint(sb, fn->c.ffid);
629 lj_buf_putb(sb, ']');
630 } else { /* Dump C function address. */
631 lj_buf_putb(sb, '@');
632 lj_strfmt_putptr(sb, fn->c.f);
633 }
634 break;
635 case 'Z': /* Zap trailing separator. */
636 lastlen = sbuflen(sb);
637 break;
638 default:
639 lj_buf_putb(sb, c);
640 break;
641 }
642 }
643 } else if (dir == 1) {
644 break;
645 } else {
646 level -= size; /* Reverse frame order: quickly skip missing level. */
647 }
648 level += dir;
649 }
650 if (lastlen)
651 sb->w = sb->b + lastlen; /* Zap trailing separator. */
652}
653#endif
654
559/* Number of frames for the leading and trailing part of a traceback. */ 655/* Number of frames for the leading and trailing part of a traceback. */
560#define TRACEBACK_LEVELS1 12 656#define TRACEBACK_LEVELS1 12
561#define TRACEBACK_LEVELS2 10 657#define TRACEBACK_LEVELS2 10