lj_debug.c (19859B)
1 /* 2 ** Debugging and introspection. 3 ** Copyright (C) 2005-2016 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