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.c194
1 files changed, 126 insertions, 68 deletions
diff --git a/src/lj_debug.c b/src/lj_debug.c
index a5ffff74..1c4bac43 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -8,6 +8,7 @@
8 8
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_str.h" 12#include "lj_str.h"
12#include "lj_tab.h" 13#include "lj_tab.h"
13#include "lj_state.h" 14#include "lj_state.h"
@@ -89,9 +90,17 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
89/* Get line number for a bytecode position. */ 90/* Get line number for a bytecode position. */
90BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc) 91BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc)
91{ 92{
92 BCLine *lineinfo = proto_lineinfo(pt); 93 const void *lineinfo = proto_lineinfo(pt);
93 if (pc < pt->sizebc && lineinfo) 94 if (pc < pt->sizebc && lineinfo) {
94 return lineinfo[pc]; 95 BCLine first = pt->firstline;
96 if (pc-- == 0) return first;
97 if (pt->numline < 256)
98 return first + (BCLine)((const uint8_t *)lineinfo)[pc];
99 else if (pt->numline < 65536)
100 return first + (BCLine)((const uint16_t *)lineinfo)[pc];
101 else
102 return first + (BCLine)((const uint32_t *)lineinfo)[pc];
103 }
95 return 0; 104 return 0;
96} 105}
97 106
@@ -109,14 +118,49 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
109 118
110/* -- Variable names ------------------------------------------------------ */ 119/* -- Variable names ------------------------------------------------------ */
111 120
121/* Read ULEB128 value. */
122static uint32_t debug_read_uleb128(const uint8_t **pp)
123{
124 const uint8_t *p = *pp;
125 uint32_t v = *p++;
126 if (LJ_UNLIKELY(v >= 0x80)) {
127 int sh = 0;
128 v &= 0x7f;
129 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
130 }
131 *pp = p;
132 return v;
133}
134
112/* Get name of a local variable from slot number and PC. */ 135/* Get name of a local variable from slot number and PC. */
113static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot) 136static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
114{ 137{
115 MSize i; 138 const uint8_t *p = proto_varinfo(pt);
116 VarInfo *vi = proto_varinfo(pt); 139 if (p) {
117 for (i = 0; i < pt->sizevarinfo && vi[i].startpc <= pc; i++) 140 BCPos lastpc = 0;
118 if (pc < vi[i].endpc && slot-- == 0) 141 for (;;) {
119 return strdata(gco2str(gcref(vi[i].name))); 142 const char *name = (const char *)p;
143 uint32_t vn = *p++;
144 BCPos startpc, endpc;
145 if (vn < VARNAME__MAX) {
146 if (vn == VARNAME_END) break; /* End of varinfo. */
147 } else {
148 while (*p++) ; /* Skip over variable name string. */
149 }
150 lastpc = startpc = lastpc + debug_read_uleb128(&p);
151 if (startpc > pc) break;
152 endpc = startpc + debug_read_uleb128(&p);
153 if (pc < endpc && slot-- == 0) {
154 if (vn < VARNAME__MAX) {
155#define VARNAMESTR(name, str) str "\0"
156 name = VARNAMEDEF(VARNAMESTR);
157#undef VARNAMESTR
158 if (--vn) while (*name++ || --vn) ;
159 }
160 return name;
161 }
162 }
163 }
120 return NULL; 164 return NULL;
121} 165}
122 166
@@ -141,7 +185,17 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
141} 185}
142 186
143/* Get name of upvalue. */ 187/* Get name of upvalue. */
144const char *lj_debug_uvname(cTValue *o, uint32_t idx, TValue **tvp) 188const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
189{
190 const uint8_t *p = proto_uvinfo(pt);
191 lua_assert(idx < pt->sizeuv);
192 if (!p) return "";
193 if (idx) while (*p++ || --idx) ;
194 return (const char *)p;
195}
196
197/* Get name and value of upvalue. */
198const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp)
145{ 199{
146 if (tvisfunc(o)) { 200 if (tvisfunc(o)) {
147 GCfunc *fn = funcV(o); 201 GCfunc *fn = funcV(o);
@@ -149,7 +203,7 @@ const char *lj_debug_uvname(cTValue *o, uint32_t idx, TValue **tvp)
149 GCproto *pt = funcproto(fn); 203 GCproto *pt = funcproto(fn);
150 if (idx < pt->sizeuv) { 204 if (idx < pt->sizeuv) {
151 *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv); 205 *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv);
152 return strdata(proto_uvname(pt, idx)); 206 return lj_debug_uvname(pt, idx);
153 } 207 }
154 } else { 208 } else {
155 if (idx < fn->c.nupvalues) { 209 if (idx < fn->c.nupvalues) {
@@ -194,7 +248,7 @@ restart:
194 } 248 }
195 return "field"; 249 return "field";
196 case BC_UGET: 250 case BC_UGET:
197 *name = strdata(proto_uvname(pt, bc_d(ins))); 251 *name = lj_debug_uvname(pt, bc_d(ins));
198 return "upvalue"; 252 return "upvalue";
199 default: 253 default:
200 return NULL; 254 return NULL;
@@ -234,25 +288,26 @@ const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name)
234/* -- Source code locations ----------------------------------------------- */ 288/* -- Source code locations ----------------------------------------------- */
235 289
236/* Generate shortened source name. */ 290/* Generate shortened source name. */
237void lj_debug_shortname(char *out, const char *src) 291void lj_debug_shortname(char *out, GCstr *str)
238{ 292{
293 const char *src = strdata(str);
239 if (*src == '=') { 294 if (*src == '=') {
240 strncpy(out, src+1, LUA_IDSIZE); /* remove first char */ 295 strncpy(out, src+1, LUA_IDSIZE); /* Remove first char. */
241 out[LUA_IDSIZE-1] = '\0'; /* ensures null termination */ 296 out[LUA_IDSIZE-1] = '\0'; /* Ensures null termination. */
242 } else if (*src == '@') { /* out = "source", or "...source" */ 297 } else if (*src == '@') { /* Output "source", or "...source". */
243 size_t l = strlen(++src); /* skip the `@' */ 298 size_t len = str->len-1;
244 if (l >= LUA_IDSIZE) { 299 src++; /* Skip the `@' */
245 src += l-(LUA_IDSIZE-4); /* get last part of file name */ 300 if (len >= LUA_IDSIZE) {
246 strcpy(out, "..."); 301 src += len-(LUA_IDSIZE-4); /* Get last part of file name. */
247 out += 3; 302 *out++ = '.'; *out++ = '.'; *out++ = '.';
248 } 303 }
249 strcpy(out, src); 304 strcpy(out, src);
250 } else { /* out = [string "string"] */ 305 } else { /* Output [string "string"]. */
251 size_t len; /* Length, up to first control char. */ 306 size_t len; /* Length, up to first control char. */
252 for (len = 0; len < LUA_IDSIZE-12; len++) 307 for (len = 0; len < LUA_IDSIZE-12; len++)
253 if (((const unsigned char *)src)[len] < ' ') break; 308 if (((const unsigned char *)src)[len] < ' ') break;
254 strcpy(out, "[string \""); out += 9; 309 strcpy(out, "[string \""); out += 9;
255 if (src[len] != '\0') { /* must truncate? */ 310 if (src[len] != '\0') { /* Must truncate? */
256 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15; 311 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
257 strncpy(out, src, len); out += len; 312 strncpy(out, src, len); out += len;
258 strcpy(out, "..."); out += 3; 313 strcpy(out, "..."); out += 3;
@@ -273,7 +328,7 @@ void lj_debug_addloc(lua_State *L, const char *msg,
273 BCLine line = debug_frameline(L, fn, nextframe); 328 BCLine line = debug_frameline(L, fn, nextframe);
274 if (line >= 0) { 329 if (line >= 0) {
275 char buf[LUA_IDSIZE]; 330 char buf[LUA_IDSIZE];
276 lj_debug_shortname(buf, strdata(proto_chunkname(funcproto(fn)))); 331 lj_debug_shortname(buf, proto_chunkname(funcproto(fn)));
277 lj_str_pushf(L, "%s:%d: %s", buf, line, msg); 332 lj_str_pushf(L, "%s:%d: %s", buf, line, msg);
278 return; 333 return;
279 } 334 }
@@ -286,27 +341,23 @@ void lj_debug_addloc(lua_State *L, const char *msg,
286void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc) 341void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
287{ 342{
288 GCstr *name = proto_chunkname(pt); 343 GCstr *name = proto_chunkname(pt);
289 if (name) { 344 const char *s = strdata(name);
290 const char *s = strdata(name); 345 MSize i, len = name->len;
291 MSize i, len = name->len; 346 BCLine line = lj_debug_line(pt, pc);
292 BCLine line = lj_debug_line(pt, pc); 347 if (*s == '@') {
293 if (*s == '@') { 348 s++; len--;
294 s++; len--; 349 for (i = len; i > 0; i--)
295 for (i = len; i > 0; i--) 350 if (s[i] == '/' || s[i] == '\\') {
296 if (s[i] == '/' || s[i] == '\\') { 351 s += i+1;
297 s += i+1; 352 break;
298 break; 353 }
299 } 354 lj_str_pushf(L, "%s:%d", s, line);
300 lj_str_pushf(L, "%s:%d", s, line); 355 } else if (len > 40) {
301 } else if (len > 40) { 356 lj_str_pushf(L, "%p:%d", pt, line);
302 lj_str_pushf(L, "%p:%d", pt, line); 357 } else if (*s == '=') {
303 } else if (*s == '=') { 358 lj_str_pushf(L, "%s:%d", s+1, line);
304 lj_str_pushf(L, "%s:%d", s+1, line);
305 } else {
306 lj_str_pushf(L, "\"%s\":%d", s, line);
307 }
308 } else { 359 } else {
309 lj_str_pushf(L, "%p:%u", pt, pc); 360 lj_str_pushf(L, "\"%s\":%d", s, line);
310 } 361 }
311} 362}
312 363
@@ -359,56 +410,63 @@ LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
359 lua_assert(fn->c.gct == ~LJ_TFUNC); 410 lua_assert(fn->c.gct == ~LJ_TFUNC);
360 } 411 }
361 for (; *what; what++) { 412 for (; *what; what++) {
362 switch (*what) { 413 if (*what == 'S') {
363 case 'S':
364 if (isluafunc(fn)) { 414 if (isluafunc(fn)) {
365 GCproto *pt = funcproto(fn); 415 GCproto *pt = funcproto(fn);
366 ar->source = strdata(proto_chunkname(pt)); 416 BCLine firstline = pt->firstline;
367 ar->linedefined = (int)proto_line(pt, 0); 417 GCstr *name = proto_chunkname(pt);
368 ar->lastlinedefined = (int)pt->lastlinedefined; 418 ar->source = strdata(name);
369 ar->what = ar->linedefined ? "Lua" : "main"; 419 lj_debug_shortname(ar->short_src, name);
420 ar->linedefined = (int)firstline;
421 ar->lastlinedefined = (int)(firstline + pt->numline);
422 ar->what = firstline ? "Lua" : "main";
370 } else { 423 } else {
371 ar->source = "=[C]"; 424 ar->source = "=[C]";
425 ar->short_src[0] = '[';
426 ar->short_src[1] = 'C';
427 ar->short_src[2] = ']';
428 ar->short_src[3] = '\0';
372 ar->linedefined = -1; 429 ar->linedefined = -1;
373 ar->lastlinedefined = -1; 430 ar->lastlinedefined = -1;
374 ar->what = "C"; 431 ar->what = "C";
375 } 432 }
376 lj_debug_shortname(ar->short_src, ar->source); 433 } else if (*what == 'l') {
377 break;
378 case 'l':
379 ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1; 434 ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1;
380 break; 435 } else if (*what == 'u') {
381 case 'u':
382 ar->nups = fn->c.nupvalues; 436 ar->nups = fn->c.nupvalues;
383 break; 437 } else if (*what == 'n') {
384 case 'n':
385 ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL; 438 ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL;
386 if (ar->namewhat == NULL) { 439 if (ar->namewhat == NULL) {
387 ar->namewhat = ""; 440 ar->namewhat = "";
388 ar->name = NULL; 441 ar->name = NULL;
389 } 442 }
390 break; 443 } else if (*what == 'f') {
391 case 'f':
392 setfuncV(L, L->top, fn); 444 setfuncV(L, L->top, fn);
393 incr_top(L); 445 incr_top(L);
394 break; 446 } else if (*what == 'L') {
395 case 'L':
396 if (isluafunc(fn)) { 447 if (isluafunc(fn)) {
397 GCtab *t = lj_tab_new(L, 0, 0); 448 GCtab *t = lj_tab_new(L, 0, 0);
398 GCproto *pt = funcproto(fn); 449 GCproto *pt = funcproto(fn);
399 BCLine *lineinfo = proto_lineinfo(pt); 450 const void *lineinfo = proto_lineinfo(pt);
400 MSize i, szl = pt->sizebc; 451 if (lineinfo) {
401 for (i = 1; i < szl; i++) 452 BCLine first = pt->firstline;
402 setboolV(lj_tab_setint(L, t, lineinfo[i]), 1); 453 int sz = pt->numline < 256 ? 1 : pt->numline < 65536 ? 2 : 4;
454 MSize i, szl = pt->sizebc-1;
455 for (i = 0; i < szl; i++) {
456 BCLine line = first +
457 (sz == 1 ? (BCLine)((const uint8_t *)lineinfo)[i] :
458 sz == 2 ? (BCLine)((const uint16_t *)lineinfo)[i] :
459 (BCLine)((const uint32_t *)lineinfo)[i]);
460 setboolV(lj_tab_setint(L, t, line), 1);
461 }
462 }
403 settabV(L, L->top, t); 463 settabV(L, L->top, t);
404 } else { 464 } else {
405 setnilV(L->top); 465 setnilV(L->top);
406 } 466 }
407 incr_top(L); 467 incr_top(L);
408 break; 468 } else {
409 default:
410 status = 0; /* Bad option. */ 469 status = 0; /* Bad option. */
411 break;
412 } 470 }
413 } 471 }
414 return status; 472 return status;