lj_debug.c 20 KB

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