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