aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/src/lj_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/src/lj_debug.c')
-rw-r--r--libraries/luajit-2.0/src/lj_debug.c502
1 files changed, 0 insertions, 502 deletions
diff --git a/libraries/luajit-2.0/src/lj_debug.c b/libraries/luajit-2.0/src/lj_debug.c
deleted file mode 100644
index 89434aa..0000000
--- a/libraries/luajit-2.0/src/lj_debug.c
+++ /dev/null
@@ -1,502 +0,0 @@
1/*
2** Debugging and introspection.
3** Copyright (C) 2005-2011 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_str.h"
13#include "lj_tab.h"
14#include "lj_state.h"
15#include "lj_frame.h"
16#include "lj_bc.h"
17#if LJ_HASJIT
18#include "lj_jit.h"
19#endif
20
21/* -- Frames -------------------------------------------------------------- */
22
23/* Get frame corresponding to a level. */
24cTValue *lj_debug_frame(lua_State *L, int level, int *size)
25{
26 cTValue *frame, *nextframe, *bot = tvref(L->stack);
27 /* Traverse frames backwards. */
28 for (nextframe = frame = L->base-1; frame > bot; ) {
29 if (frame_gc(frame) == obj2gco(L))
30 level++; /* Skip dummy frames. See lj_meta_call(). */
31 if (level-- == 0) {
32 *size = (int)(nextframe - frame);
33 return frame; /* Level found. */
34 }
35 nextframe = frame;
36 if (frame_islua(frame)) {
37 frame = frame_prevl(frame);
38 } else {
39 if (frame_isvarg(frame))
40 level++; /* Skip vararg pseudo-frame. */
41 frame = frame_prevd(frame);
42 }
43 }
44 *size = level;
45 return NULL; /* Level not found. */
46}
47
48/* Invalid bytecode position. */
49#define NO_BCPOS (~(BCPos)0)
50
51/* Return bytecode position for function/frame or NO_BCPOS. */
52static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
53{
54 const BCIns *ins;
55 GCproto *pt;
56 BCPos pos;
57 lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD);
58 if (!isluafunc(fn)) { /* Cannot derive a PC for non-Lua functions. */
59 return NO_BCPOS;
60 } else if (nextframe == NULL) { /* Lua function on top. */
61 void *cf = cframe_raw(L->cframe);
62 if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
63 return NO_BCPOS;
64 ins = cframe_pc(cf); /* Only happens during error/hook handling. */
65 } else {
66 if (frame_islua(nextframe)) {
67 ins = frame_pc(nextframe);
68 } else if (frame_iscont(nextframe)) {
69 ins = frame_contpc(nextframe);
70 } else {
71 /* Lua function below errfunc/gc/hook: find cframe to get the PC. */
72 void *cf = cframe_raw(L->cframe);
73 TValue *f = L->base-1;
74 if (cf == NULL)
75 return NO_BCPOS;
76 while (f > nextframe) {
77 if (frame_islua(f)) {
78 f = frame_prevl(f);
79 } else {
80 if (frame_isc(f))
81 cf = cframe_raw(cframe_prev(cf));
82 f = frame_prevd(f);
83 }
84 }
85 if (cframe_prev(cf))
86 cf = cframe_raw(cframe_prev(cf));
87 ins = cframe_pc(cf);
88 }
89 }
90 pt = funcproto(fn);
91 pos = proto_bcpos(pt, ins) - 1;
92#if LJ_HASJIT
93 if (pos > pt->sizebc) { /* Undo the effects of lj_trace_exit for JLOOP. */
94 GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
95 lua_assert(bc_isret(bc_op(ins[-1])));
96 pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
97 }
98#endif
99 return pos;
100}
101
102/* -- Line numbers -------------------------------------------------------- */
103
104/* Get line number for a bytecode position. */
105BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc)
106{
107 const void *lineinfo = proto_lineinfo(pt);
108 if (pc <= pt->sizebc && lineinfo) {
109 BCLine first = pt->firstline;
110 if (pc == pt->sizebc) return first + pt->numline;
111 if (pc-- == 0) return first;
112 if (pt->numline < 256)
113 return first + (BCLine)((const uint8_t *)lineinfo)[pc];
114 else if (pt->numline < 65536)
115 return first + (BCLine)((const uint16_t *)lineinfo)[pc];
116 else
117 return first + (BCLine)((const uint32_t *)lineinfo)[pc];
118 }
119 return 0;
120}
121
122/* Get line number for function/frame. */
123static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
124{
125 BCPos pc = debug_framepc(L, fn, nextframe);
126 if (pc != NO_BCPOS) {
127 GCproto *pt = funcproto(fn);
128 lua_assert(pc <= pt->sizebc);
129 return lj_debug_line(pt, pc);
130 }
131 return -1;
132}
133
134/* -- Variable names ------------------------------------------------------ */
135
136/* Read ULEB128 value. */
137static uint32_t debug_read_uleb128(const uint8_t **pp)
138{
139 const uint8_t *p = *pp;
140 uint32_t v = *p++;
141 if (LJ_UNLIKELY(v >= 0x80)) {
142 int sh = 0;
143 v &= 0x7f;
144 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
145 }
146 *pp = p;
147 return v;
148}
149
150/* Get name of a local variable from slot number and PC. */
151static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
152{
153 const uint8_t *p = proto_varinfo(pt);
154 if (p) {
155 BCPos lastpc = 0;
156 for (;;) {
157 const char *name = (const char *)p;
158 uint32_t vn = *p++;
159 BCPos startpc, endpc;
160 if (vn < VARNAME__MAX) {
161 if (vn == VARNAME_END) break; /* End of varinfo. */
162 } else {
163 while (*p++) ; /* Skip over variable name string. */
164 }
165 lastpc = startpc = lastpc + debug_read_uleb128(&p);
166 if (startpc > pc) break;
167 endpc = startpc + debug_read_uleb128(&p);
168 if (pc < endpc && slot-- == 0) {
169 if (vn < VARNAME__MAX) {
170#define VARNAMESTR(name, str) str "\0"
171 name = VARNAMEDEF(VARNAMESTR);
172#undef VARNAMESTR
173 if (--vn) while (*name++ || --vn) ;
174 }
175 return name;
176 }
177 }
178 }
179 return NULL;
180}
181
182/* Get name of local variable from 1-based slot number and function/frame. */
183static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
184 const char **name, BCReg slot1)
185{
186 uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
187 uint32_t size = (uint32_t)ar->i_ci >> 16;
188 TValue *frame = tvref(L->stack) + offset;
189 TValue *nextframe = size ? frame + size : NULL;
190 GCfunc *fn = frame_func(frame);
191 BCPos pc = debug_framepc(L, fn, nextframe);
192 if (pc != NO_BCPOS &&
193 (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
194 ;
195 else if (slot1 > 0 && frame + slot1 < (nextframe ? nextframe : L->top))
196 *name = "(*temporary)";
197 else
198 *name = NULL;
199 return frame+slot1;
200}
201
202/* Get name of upvalue. */
203const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
204{
205 const uint8_t *p = proto_uvinfo(pt);
206 lua_assert(idx < pt->sizeuv);
207 if (!p) return "";
208 if (idx) while (*p++ || --idx) ;
209 return (const char *)p;
210}
211
212/* Get name and value of upvalue. */
213const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp)
214{
215 if (tvisfunc(o)) {
216 GCfunc *fn = funcV(o);
217 if (isluafunc(fn)) {
218 GCproto *pt = funcproto(fn);
219 if (idx < pt->sizeuv) {
220 *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv);
221 return lj_debug_uvname(pt, idx);
222 }
223 } else {
224 if (idx < fn->c.nupvalues) {
225 *tvp = &fn->c.upvalue[idx];
226 return "";
227 }
228 }
229 }
230 return NULL;
231}
232
233/* Deduce name of an object from slot number and PC. */
234const char *lj_debug_slotname(GCproto *pt, const BCIns *ip, BCReg slot,
235 const char **name)
236{
237 const char *lname;
238restart:
239 lname = debug_varname(pt, proto_bcpos(pt, ip), slot);
240 if (lname != NULL) { *name = lname; return "local"; }
241 while (--ip > proto_bc(pt)) {
242 BCIns ins = *ip;
243 BCOp op = bc_op(ins);
244 BCReg ra = bc_a(ins);
245 if (bcmode_a(op) == BCMbase) {
246 if (slot >= ra && (op != BC_KNIL || slot <= bc_d(ins)))
247 return NULL;
248 } else if (bcmode_a(op) == BCMdst && ra == slot) {
249 switch (bc_op(ins)) {
250 case BC_MOV:
251 if (ra == slot) { slot = bc_d(ins); goto restart; }
252 break;
253 case BC_GGET:
254 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_d(ins))));
255 return "global";
256 case BC_TGETS:
257 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
258 if (ip > proto_bc(pt)) {
259 BCIns insp = ip[-1];
260 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 &&
261 bc_d(insp) == bc_b(ins))
262 return "method";
263 }
264 return "field";
265 case BC_UGET:
266 *name = lj_debug_uvname(pt, bc_d(ins));
267 return "upvalue";
268 default:
269 return NULL;
270 }
271 }
272 }
273 return NULL;
274}
275
276/* Deduce function name from caller of a frame. */
277const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name)
278{
279 TValue *pframe;
280 GCfunc *fn;
281 BCPos pc;
282 if (frame_isvarg(frame))
283 frame = frame_prevd(frame);
284 pframe = frame_prev(frame);
285 fn = frame_func(pframe);
286 pc = debug_framepc(L, fn, frame);
287 if (pc != NO_BCPOS) {
288 GCproto *pt = funcproto(fn);
289 const BCIns *ip = &proto_bc(pt)[check_exp(pc < pt->sizebc, pc)];
290 MMS mm = bcmode_mm(bc_op(*ip));
291 if (mm == MM_call) {
292 BCReg slot = bc_a(*ip);
293 if (bc_op(*ip) == BC_ITERC) slot -= 3;
294 return lj_debug_slotname(pt, ip, slot, name);
295 } else if (mm != MM__MAX) {
296 *name = strdata(mmname_str(G(L), mm));
297 return "metamethod";
298 }
299 }
300 return NULL;
301}
302
303/* -- Source code locations ----------------------------------------------- */
304
305/* Generate shortened source name. */
306void lj_debug_shortname(char *out, GCstr *str)
307{
308 const char *src = strdata(str);
309 if (*src == '=') {
310 strncpy(out, src+1, LUA_IDSIZE); /* Remove first char. */
311 out[LUA_IDSIZE-1] = '\0'; /* Ensures null termination. */
312 } else if (*src == '@') { /* Output "source", or "...source". */
313 size_t len = str->len-1;
314 src++; /* Skip the `@' */
315 if (len >= LUA_IDSIZE) {
316 src += len-(LUA_IDSIZE-4); /* Get last part of file name. */
317 *out++ = '.'; *out++ = '.'; *out++ = '.';
318 }
319 strcpy(out, src);
320 } else { /* Output [string "string"]. */
321 size_t len; /* Length, up to first control char. */
322 for (len = 0; len < LUA_IDSIZE-12; len++)
323 if (((const unsigned char *)src)[len] < ' ') break;
324 strcpy(out, "[string \""); out += 9;
325 if (src[len] != '\0') { /* Must truncate? */
326 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
327 strncpy(out, src, len); out += len;
328 strcpy(out, "..."); out += 3;
329 } else {
330 strcpy(out, src); out += len;
331 }
332 strcpy(out, "\"]");
333 }
334}
335
336/* Add current location of a frame to error message. */
337void lj_debug_addloc(lua_State *L, const char *msg,
338 cTValue *frame, cTValue *nextframe)
339{
340 if (frame) {
341 GCfunc *fn = frame_func(frame);
342 if (isluafunc(fn)) {
343 BCLine line = debug_frameline(L, fn, nextframe);
344 if (line >= 0) {
345 char buf[LUA_IDSIZE];
346 lj_debug_shortname(buf, proto_chunkname(funcproto(fn)));
347 lj_str_pushf(L, "%s:%d: %s", buf, line, msg);
348 return;
349 }
350 }
351 }
352 lj_str_pushf(L, "%s", msg);
353}
354
355/* Push location string for a bytecode position to Lua stack. */
356void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
357{
358 GCstr *name = proto_chunkname(pt);
359 const char *s = strdata(name);
360 MSize i, len = name->len;
361 BCLine line = lj_debug_line(pt, pc);
362 if (*s == '@') {
363 s++; len--;
364 for (i = len; i > 0; i--)
365 if (s[i] == '/' || s[i] == '\\') {
366 s += i+1;
367 break;
368 }
369 lj_str_pushf(L, "%s:%d", s, line);
370 } else if (len > 40) {
371 lj_str_pushf(L, "%p:%d", pt, line);
372 } else if (*s == '=') {
373 lj_str_pushf(L, "%s:%d", s+1, line);
374 } else {
375 lj_str_pushf(L, "\"%s\":%d", s, line);
376 }
377}
378
379/* -- Public debug API ---------------------------------------------------- */
380
381/* lua_getupvalue() and lua_setupvalue() are in lj_api.c. */
382
383LUA_API const char *lua_getlocal(lua_State *L, const lua_Debug *ar, int n)
384{
385 const char *name;
386 TValue *o = debug_localname(L, ar, &name, (BCReg)n);
387 if (name) {
388 copyTV(L, L->top, o);
389 incr_top(L);
390 }
391 return name;
392}
393
394LUA_API const char *lua_setlocal(lua_State *L, const lua_Debug *ar, int n)
395{
396 const char *name;
397 TValue *o = debug_localname(L, ar, &name, (BCReg)n);
398 if (name)
399 copyTV(L, o, L->top-1);
400 L->top--;
401 return name;
402}
403
404LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
405{
406 int status = 1;
407 TValue *frame = NULL;
408 TValue *nextframe = NULL;
409 GCfunc *fn;
410 if (*what == '>') {
411 TValue *func = L->top - 1;
412 api_check(L, tvisfunc(func));
413 fn = funcV(func);
414 L->top--;
415 what++;
416 } else {
417 uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
418 uint32_t size = (uint32_t)ar->i_ci >> 16;
419 lua_assert(offset != 0);
420 frame = tvref(L->stack) + offset;
421 if (size) nextframe = frame + size;
422 lua_assert(frame <= tvref(L->maxstack) &&
423 (!nextframe || nextframe <= tvref(L->maxstack)));
424 fn = frame_func(frame);
425 lua_assert(fn->c.gct == ~LJ_TFUNC);
426 }
427 for (; *what; what++) {
428 if (*what == 'S') {
429 if (isluafunc(fn)) {
430 GCproto *pt = funcproto(fn);
431 BCLine firstline = pt->firstline;
432 GCstr *name = proto_chunkname(pt);
433 ar->source = strdata(name);
434 lj_debug_shortname(ar->short_src, name);
435 ar->linedefined = (int)firstline;
436 ar->lastlinedefined = (int)(firstline + pt->numline);
437 ar->what = firstline ? "Lua" : "main";
438 } else {
439 ar->source = "=[C]";
440 ar->short_src[0] = '[';
441 ar->short_src[1] = 'C';
442 ar->short_src[2] = ']';
443 ar->short_src[3] = '\0';
444 ar->linedefined = -1;
445 ar->lastlinedefined = -1;
446 ar->what = "C";
447 }
448 } else if (*what == 'l') {
449 ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1;
450 } else if (*what == 'u') {
451 ar->nups = fn->c.nupvalues;
452 } else if (*what == 'n') {
453 ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL;
454 if (ar->namewhat == NULL) {
455 ar->namewhat = "";
456 ar->name = NULL;
457 }
458 } else if (*what == 'f') {
459 setfuncV(L, L->top, fn);
460 incr_top(L);
461 } else if (*what == 'L') {
462 if (isluafunc(fn)) {
463 GCtab *t = lj_tab_new(L, 0, 0);
464 GCproto *pt = funcproto(fn);
465 const void *lineinfo = proto_lineinfo(pt);
466 if (lineinfo) {
467 BCLine first = pt->firstline;
468 int sz = pt->numline < 256 ? 1 : pt->numline < 65536 ? 2 : 4;
469 MSize i, szl = pt->sizebc-1;
470 for (i = 0; i < szl; i++) {
471 BCLine line = first +
472 (sz == 1 ? (BCLine)((const uint8_t *)lineinfo)[i] :
473 sz == 2 ? (BCLine)((const uint16_t *)lineinfo)[i] :
474 (BCLine)((const uint32_t *)lineinfo)[i]);
475 setboolV(lj_tab_setint(L, t, line), 1);
476 }
477 }
478 settabV(L, L->top, t);
479 } else {
480 setnilV(L->top);
481 }
482 incr_top(L);
483 } else {
484 status = 0; /* Bad option. */
485 }
486 }
487 return status;
488}
489
490LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
491{
492 int size;
493 cTValue *frame = lj_debug_frame(L, level, &size);
494 if (frame) {
495 ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
496 return 1;
497 } else {
498 ar->i_ci = level - size;
499 return 0;
500 }
501}
502