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.c111
1 files changed, 108 insertions, 3 deletions
diff --git a/src/lj_debug.c b/src/lj_debug.c
index 24efd2ff..8166fcc0 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -28,7 +28,7 @@ cTValue *lj_debug_frame(lua_State *L, int level, int *size)
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. */
@@ -278,9 +278,9 @@ restart:
278} 278}
279 279
280/* Deduce function name from caller of a frame. */ 280/* Deduce function name from caller of a frame. */
281const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name) 281const char *lj_debug_funcname(lua_State *L, cTValue *frame, const char **name)
282{ 282{
283 TValue *pframe; 283 cTValue *pframe;
284 GCfunc *fn; 284 GCfunc *fn;
285 BCPos pc; 285 BCPos pc;
286 if (frame <= tvref(L->stack)) 286 if (frame <= tvref(L->stack))
@@ -534,6 +534,111 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
534 } 534 }
535} 535}
536 536
537#if LJ_HASPROFILE
538/* Put the chunkname into a buffer. */
539static int debug_putchunkname(SBuf *sb, GCproto *pt, int pathstrip)
540{
541 GCstr *name = proto_chunkname(pt);
542 const char *p = strdata(name);
543 if (pt->firstline == ~(BCLine)0) {
544 lj_buf_putmem(sb, "[builtin:", 9);
545 lj_buf_putstr(sb, name);
546 lj_buf_putb(sb, ']');
547 return 0;
548 }
549 if (*p == '=' || *p == '@') {
550 MSize len = name->len-1;
551 p++;
552 if (pathstrip) {
553 int i;
554 for (i = len-1; i >= 0; i--)
555 if (p[i] == '/' || p[i] == '\\') {
556 len -= i+1;
557 p = p+i+1;
558 break;
559 }
560 }
561 lj_buf_putmem(sb, p, len);
562 } else {
563 lj_buf_putmem(sb, "[string]", 9);
564 }
565 return 1;
566}
567
568/* Put a compact stack dump into a buffer. */
569void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt, int depth)
570{
571 int level = 0, dir = 1, pathstrip = 1;
572 MSize lastlen = 0;
573 if (depth < 0) { level = ~depth; depth = dir = -1; } /* Reverse frames. */
574 while (level != depth) { /* Loop through all frame. */
575 int size;
576 cTValue *frame = lj_debug_frame(L, level, &size);
577 if (frame) {
578 cTValue *nextframe = size ? frame+size : NULL;
579 GCfunc *fn = frame_func(frame);
580 const uint8_t *p = (const uint8_t *)fmt;
581 int c;
582 while ((c = *p++)) {
583 switch (c) {
584 case 'p': /* Preserve full path. */
585 pathstrip = 0;
586 break;
587 case 'F': case 'f': { /* Dump function name. */
588 const char *name;
589 const char *what = lj_debug_funcname(L, frame, &name);
590 if (what) {
591 if (c == 'F' && isluafunc(fn)) { /* Dump module:name for 'F'. */
592 GCproto *pt = funcproto(fn);
593 if (pt->firstline != ~(BCLine)0) { /* Not a bytecode builtin. */
594 debug_putchunkname(sb, pt, pathstrip);
595 lj_buf_putb(sb, ':');
596 }
597 }
598 lj_buf_putmem(sb, name, (MSize)strlen(name));
599 break;
600 } /* else: can't derive a name, dump module:line. */
601 }
602 /* fallthrough */
603 case 'l': /* Dump module:line. */
604 if (isluafunc(fn)) {
605 GCproto *pt = funcproto(fn);
606 if (debug_putchunkname(sb, pt, pathstrip)) {
607 /* Regular Lua function. */
608 BCLine line = c == 'l' ? debug_frameline(L, fn, nextframe) :
609 pt->firstline;
610 lj_buf_putb(sb, ':');
611 lj_strfmt_putint(sb, line >= 0 ? line : pt->firstline);
612 }
613 } else if (isffunc(fn)) { /* Dump numbered builtins. */
614 lj_buf_putmem(sb, "[builtin#", 9);
615 lj_strfmt_putint(sb, fn->c.ffid);
616 lj_buf_putb(sb, ']');
617 } else { /* Dump C function address. */
618 lj_buf_putb(sb, '@');
619 lj_strfmt_putptr(sb, fn->c.f);
620 }
621 break;
622 case 'Z': /* Zap trailing separator. */
623 lastlen = sbuflen(sb);
624 break;
625 default:
626 lj_buf_putb(sb, c);
627 break;
628 }
629 }
630 } else if (dir == 1) {
631 break;
632 } else {
633 level -= size; /* Reverse frame order: quickly skip missing level. */
634 }
635 level += dir;
636 }
637 if (lastlen)
638 setsbufP(sb, sbufB(sb) + lastlen); /* Zap trailing separator. */
639}
640#endif
641
537/* Number of frames for the leading and trailing part of a traceback. */ 642/* Number of frames for the leading and trailing part of a traceback. */
538#define TRACEBACK_LEVELS1 12 643#define TRACEBACK_LEVELS1 12
539#define TRACEBACK_LEVELS2 10 644#define TRACEBACK_LEVELS2 10