root/lj_debug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lj_debug_frame
  2. debug_framepc
  3. lj_debug_line
  4. debug_frameline
  5. debug_varname
  6. debug_localname
  7. lj_debug_uvname
  8. lj_debug_uvnamev
  9. lj_debug_slotname
  10. lj_debug_funcname
  11. lj_debug_shortname
  12. lj_debug_addloc
  13. lj_debug_pushloc
  14. lua_getlocal
  15. lua_setlocal
  16. lj_debug_getinfo
  17. lua_getinfo
  18. lua_getstack
  19. debug_putchunkname
  20. lj_debug_dumpstack
  21. luaL_traceback

   1 /*
   2 ** Debugging and introspection.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 */
   5 
   6 #define lj_debug_c
   7 #define LUA_CORE
   8 
   9 #include "lj_obj.h"
  10 #include "lj_err.h"
  11 #include "lj_debug.h"
  12 #include "lj_buf.h"
  13 #include "lj_tab.h"
  14 #include "lj_state.h"
  15 #include "lj_frame.h"
  16 #include "lj_bc.h"
  17 #include "lj_strfmt.h"
  18 #if LJ_HASJIT
  19 #include "lj_jit.h"
  20 #endif
  21 
  22 /* -- Frames -------------------------------------------------------------- */
  23 
  24 /* Get frame corresponding to a level. */
  25 cTValue *lj_debug_frame(lua_State *L, int level, int *size)
  26 {
  27   cTValue *frame, *nextframe, *bot = tvref(L->stack)+LJ_FR2;
  28   /* Traverse frames backwards. */
  29   for (nextframe = frame = L->base-1; frame > bot; ) {
  30     if (frame_gc(frame) == obj2gco(L))
  31       level++;  /* Skip dummy frames. See lj_err_optype_call(). */
  32     if (level-- == 0) {
  33       *size = (int)(nextframe - frame);
  34       return frame;  /* Level found. */
  35     }
  36     nextframe = frame;
  37     if (frame_islua(frame)) {
  38       frame = frame_prevl(frame);
  39     } else {
  40       if (frame_isvarg(frame))
  41         level++;  /* Skip vararg pseudo-frame. */
  42       frame = frame_prevd(frame);
  43     }
  44   }
  45   *size = level;
  46   return NULL;  /* Level not found. */
  47 }
  48 
  49 /* Invalid bytecode position. */
  50 #define NO_BCPOS        (~(BCPos)0)
  51 
  52 /* Return bytecode position for function/frame or NO_BCPOS. */
  53 static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
  54 {
  55   const BCIns *ins;
  56   GCproto *pt;
  57   BCPos pos;
  58   lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD);
  59   if (!isluafunc(fn)) {  /* Cannot derive a PC for non-Lua functions. */
  60     return NO_BCPOS;
  61   } else if (nextframe == NULL) {  /* Lua function on top. */
  62     void *cf = cframe_raw(L->cframe);
  63     if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
  64       return NO_BCPOS;
  65     ins = cframe_pc(cf);  /* Only happens during error/hook handling. */
  66   } else {
  67     if (frame_islua(nextframe)) {
  68       ins = frame_pc(nextframe);
  69     } else if (frame_iscont(nextframe)) {
  70       ins = frame_contpc(nextframe);
  71     } else {
  72       /* Lua function below errfunc/gc/hook: find cframe to get the PC. */
  73       void *cf = cframe_raw(L->cframe);
  74       TValue *f = L->base-1;
  75       for (;;) {
  76         if (cf == NULL)
  77           return NO_BCPOS;
  78         while (cframe_nres(cf) < 0) {
  79           if (f >= restorestack(L, -cframe_nres(cf)))
  80             break;
  81           cf = cframe_raw(cframe_prev(cf));
  82           if (cf == NULL)
  83             return NO_BCPOS;
  84         }
  85         if (f < nextframe)
  86           break;
  87         if (frame_islua(f)) {
  88           f = frame_prevl(f);
  89         } else {
  90           if (frame_isc(f) || (frame_iscont(f) && frame_iscont_fficb(f)))
  91             cf = cframe_raw(cframe_prev(cf));
  92           f = frame_prevd(f);
  93         }
  94       }
  95       ins = cframe_pc(cf);
  96     }
  97   }
  98   pt = funcproto(fn);
  99   pos = proto_bcpos(pt, ins) - 1;
 100 #if LJ_HASJIT
 101   if (pos > pt->sizebc) {  /* Undo the effects of lj_trace_exit for JLOOP. */
 102     GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
 103     lua_assert(bc_isret(bc_op(ins[-1])));
 104     pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
 105   }
 106 #endif
 107   return pos;
 108 }
 109 
 110 /* -- Line numbers -------------------------------------------------------- */
 111 
 112 /* Get line number for a bytecode position. */
 113 BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc)
 114 {
 115   const void *lineinfo = proto_lineinfo(pt);
 116   if (pc <= pt->sizebc && lineinfo) {
 117     BCLine first = pt->firstline;
 118     if (pc == pt->sizebc) return first + pt->numline;
 119     if (pc-- == 0) return first;
 120     if (pt->numline < 256)
 121       return first + (BCLine)((const uint8_t *)lineinfo)[pc];
 122     else if (pt->numline < 65536)
 123       return first + (BCLine)((const uint16_t *)lineinfo)[pc];
 124     else
 125       return first + (BCLine)((const uint32_t *)lineinfo)[pc];
 126   }
 127   return 0;
 128 }
 129 
 130 /* Get line number for function/frame. */
 131 static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
 132 {
 133   BCPos pc = debug_framepc(L, fn, nextframe);
 134   if (pc != NO_BCPOS) {
 135     GCproto *pt = funcproto(fn);
 136     lua_assert(pc <= pt->sizebc);
 137     return lj_debug_line(pt, pc);
 138   }
 139   return -1;
 140 }
 141 
 142 /* -- Variable names ------------------------------------------------------ */
 143 
 144 /* Get name of a local variable from slot number and PC. */
 145 static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
 146 {
 147   const char *p = (const char *)proto_varinfo(pt);
 148   if (p) {
 149     BCPos lastpc = 0;
 150     for (;;) {
 151       const char *name = p;
 152       uint32_t vn = *(const uint8_t *)p;
 153       BCPos startpc, endpc;
 154       if (vn < VARNAME__MAX) {
 155         if (vn == VARNAME_END) break;  /* End of varinfo. */
 156       } else {
 157         do { p++; } while (*(const uint8_t *)p);  /* Skip over variable name. */
 158       }
 159       p++;
 160       lastpc = startpc = lastpc + lj_buf_ruleb128(&p);
 161       if (startpc > pc) break;
 162       endpc = startpc + lj_buf_ruleb128(&p);
 163       if (pc < endpc && slot-- == 0) {
 164         if (vn < VARNAME__MAX) {
 165 #define VARNAMESTR(name, str)   str "\0"
 166           name = VARNAMEDEF(VARNAMESTR);
 167 #undef VARNAMESTR
 168           if (--vn) while (*name++ || --vn) ;
 169         }
 170         return name;
 171       }
 172     }
 173   }
 174   return NULL;
 175 }
 176 
 177 /* Get name of local variable from 1-based slot number and function/frame. */
 178 static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
 179                                const char **name, BCReg slot1)
 180 {
 181   uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
 182   uint32_t size = (uint32_t)ar->i_ci >> 16;
 183   TValue *frame = tvref(L->stack) + offset;
 184   TValue *nextframe = size ? frame + size : NULL;
 185   GCfunc *fn = frame_func(frame);
 186   BCPos pc = debug_framepc(L, fn, nextframe);
 187   if (!nextframe) nextframe = L->top+LJ_FR2;
 188   if ((int)slot1 < 0) {  /* Negative slot number is for varargs. */
 189     if (pc != NO_BCPOS) {
 190       GCproto *pt = funcproto(fn);
 191       if ((pt->flags & PROTO_VARARG)) {
 192         slot1 = pt->numparams + (BCReg)(-(int)slot1);
 193         if (frame_isvarg(frame)) {  /* Vararg frame has been set up? (pc!=0) */
 194           nextframe = frame;
 195           frame = frame_prevd(frame);
 196         }
 197         if (frame + slot1+LJ_FR2 < nextframe) {
 198           *name = "(*vararg)";
 199           return frame+slot1;
 200         }
 201       }
 202     }
 203     return NULL;
 204   }
 205   if (pc != NO_BCPOS &&
 206       (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
 207     ;
 208   else if (slot1 > 0 && frame + slot1+LJ_FR2 < nextframe)
 209     *name = "(*temporary)";
 210   return frame+slot1;
 211 }
 212 
 213 /* Get name of upvalue. */
 214 const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
 215 {
 216   const uint8_t *p = proto_uvinfo(pt);
 217   lua_assert(idx < pt->sizeuv);
 218   if (!p) return "";
 219   if (idx) while (*p++ || --idx) ;
 220   return (const char *)p;
 221 }
 222 
 223 /* Get name and value of upvalue. */
 224 const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp)
 225 {
 226   if (tvisfunc(o)) {
 227     GCfunc *fn = funcV(o);
 228     if (isluafunc(fn)) {
 229       GCproto *pt = funcproto(fn);
 230       if (idx < pt->sizeuv) {
 231         *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv);
 232         return lj_debug_uvname(pt, idx);
 233       }
 234     } else {
 235       if (idx < fn->c.nupvalues) {
 236         *tvp = &fn->c.upvalue[idx];
 237         return "";
 238       }
 239     }
 240   }
 241   return NULL;
 242 }
 243 
 244 /* Deduce name of an object from slot number and PC. */
 245 const char *lj_debug_slotname(GCproto *pt, const BCIns *ip, BCReg slot,
 246                               const char **name)
 247 {
 248   const char *lname;
 249 restart:
 250   lname = debug_varname(pt, proto_bcpos(pt, ip), slot);
 251   if (lname != NULL) { *name = lname; return "local"; }
 252   while (--ip > proto_bc(pt)) {
 253     BCIns ins = *ip;
 254     BCOp op = bc_op(ins);
 255     BCReg ra = bc_a(ins);
 256     if (bcmode_a(op) == BCMbase) {
 257       if (slot >= ra && (op != BC_KNIL || slot <= bc_d(ins)))
 258         return NULL;
 259     } else if (bcmode_a(op) == BCMdst && ra == slot) {
 260       switch (bc_op(ins)) {
 261       case BC_MOV:
 262         if (ra == slot) { slot = bc_d(ins); goto restart; }
 263         break;
 264       case BC_GGET:
 265         *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_d(ins))));
 266         return "global";
 267       case BC_TGETS:
 268         *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
 269         if (ip > proto_bc(pt)) {
 270           BCIns insp = ip[-1];
 271           if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1+LJ_FR2 &&
 272               bc_d(insp) == bc_b(ins))
 273             return "method";
 274         }
 275         return "field";
 276       case BC_UGET:
 277         *name = lj_debug_uvname(pt, bc_d(ins));
 278         return "upvalue";
 279       default:
 280         return NULL;
 281       }
 282     }
 283   }
 284   return NULL;
 285 }
 286 
 287 /* Deduce function name from caller of a frame. */
 288 const char *lj_debug_funcname(lua_State *L, cTValue *frame, const char **name)
 289 {
 290   cTValue *pframe;
 291   GCfunc *fn;
 292   BCPos pc;
 293   if (frame <= tvref(L->stack)+LJ_FR2)
 294     return NULL;
 295   if (frame_isvarg(frame))
 296     frame = frame_prevd(frame);
 297   pframe = frame_prev(frame);
 298   fn = frame_func(pframe);
 299   pc = debug_framepc(L, fn, frame);
 300   if (pc != NO_BCPOS) {
 301     GCproto *pt = funcproto(fn);
 302     const BCIns *ip = &proto_bc(pt)[check_exp(pc < pt->sizebc, pc)];
 303     MMS mm = bcmode_mm(bc_op(*ip));
 304     if (mm == MM_call) {
 305       BCReg slot = bc_a(*ip);
 306       if (bc_op(*ip) == BC_ITERC) slot -= 3;
 307       return lj_debug_slotname(pt, ip, slot, name);
 308     } else if (mm != MM__MAX) {
 309       *name = strdata(mmname_str(G(L), mm));
 310       return "metamethod";
 311     }
 312   }
 313   return NULL;
 314 }
 315 
 316 /* -- Source code locations ----------------------------------------------- */
 317 
 318 /* Generate shortened source name. */
 319 void lj_debug_shortname(char *out, GCstr *str, BCLine line)
 320 {
 321   const char *src = strdata(str);
 322   if (*src == '=') {
 323     strncpy(out, src+1, LUA_IDSIZE);  /* Remove first char. */
 324     out[LUA_IDSIZE-1] = '\0';  /* Ensures null termination. */
 325   } else if (*src == '@') {  /* Output "source", or "...source". */
 326     size_t len = str->len-1;
 327     src++;  /* Skip the `@' */
 328     if (len >= LUA_IDSIZE) {
 329       src += len-(LUA_IDSIZE-4);  /* Get last part of file name. */
 330       *out++ = '.'; *out++ = '.'; *out++ = '.';
 331     }
 332     strcpy(out, src);
 333   } else {  /* Output [string "string"] or [builtin:name]. */
 334     size_t len;  /* Length, up to first control char. */
 335     for (len = 0; len < LUA_IDSIZE-12; len++)
 336       if (((const unsigned char *)src)[len] < ' ') break;
 337     strcpy(out, line == ~(BCLine)0 ? "[builtin:" : "[string \""); out += 9;
 338     if (src[len] != '\0') {  /* Must truncate? */
 339       if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
 340       strncpy(out, src, len); out += len;
 341       strcpy(out, "..."); out += 3;
 342     } else {
 343       strcpy(out, src); out += len;
 344     }
 345     strcpy(out, line == ~(BCLine)0 ? "]" : "\"]");
 346   }
 347 }
 348 
 349 /* Add current location of a frame to error message. */
 350 void lj_debug_addloc(lua_State *L, const char *msg,
 351                      cTValue *frame, cTValue *nextframe)
 352 {
 353   if (frame) {
 354     GCfunc *fn = frame_func(frame);
 355     if (isluafunc(fn)) {
 356       BCLine line = debug_frameline(L, fn, nextframe);
 357       if (line >= 0) {
 358         GCproto *pt = funcproto(fn);
 359         char buf[LUA_IDSIZE];
 360         lj_debug_shortname(buf, proto_chunkname(pt), pt->firstline);
 361         lj_strfmt_pushf(L, "%s:%d: %s", buf, line, msg);
 362         return;
 363       }
 364     }
 365   }
 366   lj_strfmt_pushf(L, "%s", msg);
 367 }
 368 
 369 /* Push location string for a bytecode position to Lua stack. */
 370 void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
 371 {
 372   GCstr *name = proto_chunkname(pt);
 373   const char *s = strdata(name);
 374   MSize i, len = name->len;
 375   BCLine line = lj_debug_line(pt, pc);
 376   if (pt->firstline == ~(BCLine)0) {
 377     lj_strfmt_pushf(L, "builtin:%s", s);
 378   } else if (*s == '@') {
 379     s++; len--;
 380     for (i = len; i > 0; i--)
 381       if (s[i] == '/' || s[i] == '\\') {
 382         s += i+1;
 383         break;
 384       }
 385     lj_strfmt_pushf(L, "%s:%d", s, line);
 386   } else if (len > 40) {
 387     lj_strfmt_pushf(L, "%p:%d", pt, line);
 388   } else if (*s == '=') {
 389     lj_strfmt_pushf(L, "%s:%d", s+1, line);
 390   } else {
 391     lj_strfmt_pushf(L, "\"%s\":%d", s, line);
 392   }
 393 }
 394 
 395 /* -- Public debug API ---------------------------------------------------- */
 396 
 397 /* lua_getupvalue() and lua_setupvalue() are in lj_api.c. */
 398 
 399 LUA_API const char *lua_getlocal(lua_State *L, const lua_Debug *ar, int n)
 400 {
 401   const char *name = NULL;
 402   if (ar) {
 403     TValue *o = debug_localname(L, ar, &name, (BCReg)n);
 404     if (name) {
 405       copyTV(L, L->top, o);
 406       incr_top(L);
 407     }
 408   } else if (tvisfunc(L->top-1) && isluafunc(funcV(L->top-1))) {
 409     name = debug_varname(funcproto(funcV(L->top-1)), 0, (BCReg)n-1);
 410   }
 411   return name;
 412 }
 413 
 414 LUA_API const char *lua_setlocal(lua_State *L, const lua_Debug *ar, int n)
 415 {
 416   const char *name = NULL;
 417   TValue *o = debug_localname(L, ar, &name, (BCReg)n);
 418   if (name)
 419     copyTV(L, o, L->top-1);
 420   L->top--;
 421   return name;
 422 }
 423 
 424 int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext)
 425 {
 426   int opt_f = 0, opt_L = 0;
 427   TValue *frame = NULL;
 428   TValue *nextframe = NULL;
 429   GCfunc *fn;
 430   if (*what == '>') {
 431     TValue *func = L->top - 1;
 432     api_check(L, tvisfunc(func));
 433     fn = funcV(func);
 434     L->top--;
 435     what++;
 436   } else {
 437     uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
 438     uint32_t size = (uint32_t)ar->i_ci >> 16;
 439     lua_assert(offset != 0);
 440     frame = tvref(L->stack) + offset;
 441     if (size) nextframe = frame + size;
 442     lua_assert(frame <= tvref(L->maxstack) &&
 443                (!nextframe || nextframe <= tvref(L->maxstack)));
 444     fn = frame_func(frame);
 445     lua_assert(fn->c.gct == ~LJ_TFUNC);
 446   }
 447   for (; *what; what++) {
 448     if (*what == 'S') {
 449       if (isluafunc(fn)) {
 450         GCproto *pt = funcproto(fn);
 451         BCLine firstline = pt->firstline;
 452         GCstr *name = proto_chunkname(pt);
 453         ar->source = strdata(name);
 454         lj_debug_shortname(ar->short_src, name, pt->firstline);
 455         ar->linedefined = (int)firstline;
 456         ar->lastlinedefined = (int)(firstline + pt->numline);
 457         ar->what = (firstline || !pt->numline) ? "Lua" : "main";
 458       } else {
 459         ar->source = "=[C]";
 460         ar->short_src[0] = '[';
 461         ar->short_src[1] = 'C';
 462         ar->short_src[2] = ']';
 463         ar->short_src[3] = '\0';
 464         ar->linedefined = -1;
 465         ar->lastlinedefined = -1;
 466         ar->what = "C";
 467       }
 468     } else if (*what == 'l') {
 469       ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1;
 470     } else if (*what == 'u') {
 471       ar->nups = fn->c.nupvalues;
 472       if (ext) {
 473         if (isluafunc(fn)) {
 474           GCproto *pt = funcproto(fn);
 475           ar->nparams = pt->numparams;
 476           ar->isvararg = !!(pt->flags & PROTO_VARARG);
 477         } else {
 478           ar->nparams = 0;
 479           ar->isvararg = 1;
 480         }
 481       }
 482     } else if (*what == 'n') {
 483       ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL;
 484       if (ar->namewhat == NULL) {
 485         ar->namewhat = "";
 486         ar->name = NULL;
 487       }
 488     } else if (*what == 'f') {
 489       opt_f = 1;
 490     } else if (*what == 'L') {
 491       opt_L = 1;
 492     } else {
 493       return 0;  /* Bad option. */
 494     }
 495   }
 496   if (opt_f) {
 497     setfuncV(L, L->top, fn);
 498     incr_top(L);
 499   }
 500   if (opt_L) {
 501     if (isluafunc(fn)) {
 502       GCtab *t = lj_tab_new(L, 0, 0);
 503       GCproto *pt = funcproto(fn);
 504       const void *lineinfo = proto_lineinfo(pt);
 505       if (lineinfo) {
 506         BCLine first = pt->firstline;
 507         int sz = pt->numline < 256 ? 1 : pt->numline < 65536 ? 2 : 4;
 508         MSize i, szl = pt->sizebc-1;
 509         for (i = 0; i < szl; i++) {
 510           BCLine line = first +
 511             (sz == 1 ? (BCLine)((const uint8_t *)lineinfo)[i] :
 512              sz == 2 ? (BCLine)((const uint16_t *)lineinfo)[i] :
 513              (BCLine)((const uint32_t *)lineinfo)[i]);
 514           setboolV(lj_tab_setint(L, t, line), 1);
 515         }
 516       }
 517       settabV(L, L->top, t);
 518     } else {
 519       setnilV(L->top);
 520     }
 521     incr_top(L);
 522   }
 523   return 1;  /* Ok. */
 524 }
 525 
 526 LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
 527 {
 528   return lj_debug_getinfo(L, what, (lj_Debug *)ar, 0);
 529 }
 530 
 531 LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
 532 {
 533   int size;
 534   cTValue *frame = lj_debug_frame(L, level, &size);
 535   if (frame) {
 536     ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
 537     return 1;
 538   } else {
 539     ar->i_ci = level - size;
 540     return 0;
 541   }
 542 }
 543 
 544 #if LJ_HASPROFILE
 545 /* Put the chunkname into a buffer. */
 546 static int debug_putchunkname(SBuf *sb, GCproto *pt, int pathstrip)
 547 {
 548   GCstr *name = proto_chunkname(pt);
 549   const char *p = strdata(name);
 550   if (pt->firstline == ~(BCLine)0) {
 551     lj_buf_putmem(sb, "[builtin:", 9);
 552     lj_buf_putstr(sb, name);
 553     lj_buf_putb(sb, ']');
 554     return 0;
 555   }
 556   if (*p == '=' || *p == '@') {
 557     MSize len = name->len-1;
 558     p++;
 559     if (pathstrip) {
 560       int i;
 561       for (i = len-1; i >= 0; i--)
 562         if (p[i] == '/' || p[i] == '\\') {
 563           len -= i+1;
 564           p = p+i+1;
 565           break;
 566         }
 567     }
 568     lj_buf_putmem(sb, p, len);
 569   } else {
 570     lj_buf_putmem(sb, "[string]", 8);
 571   }
 572   return 1;
 573 }
 574 
 575 /* Put a compact stack dump into a buffer. */
 576 void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt, int depth)
 577 {
 578   int level = 0, dir = 1, pathstrip = 1;
 579   MSize lastlen = 0;
 580   if (depth < 0) { level = ~depth; depth = dir = -1; }  /* Reverse frames. */
 581   while (level != depth) {  /* Loop through all frame. */
 582     int size;
 583     cTValue *frame = lj_debug_frame(L, level, &size);
 584     if (frame) {
 585       cTValue *nextframe = size ? frame+size : NULL;
 586       GCfunc *fn = frame_func(frame);
 587       const uint8_t *p = (const uint8_t *)fmt;
 588       int c;
 589       while ((c = *p++)) {
 590         switch (c) {
 591         case 'p':  /* Preserve full path. */
 592           pathstrip = 0;
 593           break;
 594         case 'F': case 'f': {  /* Dump function name. */
 595           const char *name;
 596           const char *what = lj_debug_funcname(L, frame, &name);
 597           if (what) {
 598             if (c == 'F' && isluafunc(fn)) {  /* Dump module:name for 'F'. */
 599               GCproto *pt = funcproto(fn);
 600               if (pt->firstline != ~(BCLine)0) {  /* Not a bytecode builtin. */
 601                 debug_putchunkname(sb, pt, pathstrip);
 602                 lj_buf_putb(sb, ':');
 603               }
 604             }
 605             lj_buf_putmem(sb, name, (MSize)strlen(name));
 606             break;
 607           }  /* else: can't derive a name, dump module:line. */
 608           }
 609           /* fallthrough */
 610         case 'l':  /* Dump module:line. */
 611           if (isluafunc(fn)) {
 612             GCproto *pt = funcproto(fn);
 613             if (debug_putchunkname(sb, pt, pathstrip)) {
 614               /* Regular Lua function. */
 615               BCLine line = c == 'l' ? debug_frameline(L, fn, nextframe) :
 616                                        pt->firstline;
 617               lj_buf_putb(sb, ':');
 618               lj_strfmt_putint(sb, line >= 0 ? line : pt->firstline);
 619             }
 620           } else if (isffunc(fn)) {  /* Dump numbered builtins. */
 621             lj_buf_putmem(sb, "[builtin#", 9);
 622             lj_strfmt_putint(sb, fn->c.ffid);
 623             lj_buf_putb(sb, ']');
 624           } else {  /* Dump C function address. */
 625             lj_buf_putb(sb, '@');
 626             lj_strfmt_putptr(sb, fn->c.f);
 627           }
 628           break;
 629         case 'Z':  /* Zap trailing separator. */
 630           lastlen = sbuflen(sb);
 631           break;
 632         default:
 633           lj_buf_putb(sb, c);
 634           break;
 635         }
 636       }
 637     } else if (dir == 1) {
 638       break;
 639     } else {
 640       level -= size;  /* Reverse frame order: quickly skip missing level. */
 641     }
 642     level += dir;
 643   }
 644   if (lastlen)
 645     setsbufP(sb, sbufB(sb) + lastlen);  /* Zap trailing separator. */
 646 }
 647 #endif
 648 
 649 /* Number of frames for the leading and trailing part of a traceback. */
 650 #define TRACEBACK_LEVELS1       12
 651 #define TRACEBACK_LEVELS2       10
 652 
 653 LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
 654                                 int level)
 655 {
 656   int top = (int)(L->top - L->base);
 657   int lim = TRACEBACK_LEVELS1;
 658   lua_Debug ar;
 659   if (msg) lua_pushfstring(L, "%s\n", msg);
 660   lua_pushliteral(L, "stack traceback:");
 661   while (lua_getstack(L1, level++, &ar)) {
 662     GCfunc *fn;
 663     if (level > lim) {
 664       if (!lua_getstack(L1, level + TRACEBACK_LEVELS2, &ar)) {
 665         level--;
 666       } else {
 667         lua_pushliteral(L, "\n\t...");
 668         lua_getstack(L1, -10, &ar);
 669         level = ar.i_ci - TRACEBACK_LEVELS2;
 670       }
 671       lim = 2147483647;
 672       continue;
 673     }
 674     lua_getinfo(L1, "Snlf", &ar);
 675     fn = funcV(L1->top-1); L1->top--;
 676     if (isffunc(fn) && !*ar.namewhat)
 677       lua_pushfstring(L, "\n\t[builtin#%d]:", fn->c.ffid);
 678     else
 679       lua_pushfstring(L, "\n\t%s:", ar.short_src);
 680     if (ar.currentline > 0)
 681       lua_pushfstring(L, "%d:", ar.currentline);
 682     if (*ar.namewhat) {
 683       lua_pushfstring(L, " in function " LUA_QS, ar.name);
 684     } else {
 685       if (*ar.what == 'm') {
 686         lua_pushliteral(L, " in main chunk");
 687       } else if (*ar.what == 'C') {
 688         lua_pushfstring(L, " at %p", fn->c.f);
 689       } else {
 690         lua_pushfstring(L, " in function <%s:%d>",
 691                         ar.short_src, ar.linedefined);
 692       }
 693     }
 694     if ((int)(L->top - L->base) - top >= 15)
 695       lua_concat(L, (int)(L->top - L->base) - top);
 696   }
 697   lua_concat(L, (int)(L->top - L->base) - top);
 698 }
 699 

/* [<][>][^][v][top][bottom][index][help] */