diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-08-12 17:01:44 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-08-12 17:01:44 -0300 |
commit | 0b65cb74cdf4ef6e6a33da6724610e506407df1a (patch) | |
tree | d2fba4506b0650cec94aeba62c719a255651ea21 | |
parent | ea46b750dceec7f6ddd3ae48ace391d5a1fd705e (diff) | |
download | lua-0b65cb74cdf4ef6e6a33da6724610e506407df1a.tar.gz lua-0b65cb74cdf4ef6e6a33da6724610e506407df1a.tar.bz2 lua-0b65cb74cdf4ef6e6a33da6724610e506407df1a.zip |
new implementation for 'getobjname': first search for relevant
instruction (new function 'findsetreg') and then try to build
a meaningful name
-rw-r--r-- | ldebug.c | 172 |
1 files changed, 87 insertions, 85 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 2.82 2011/06/02 19:31:40 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.83 2011/08/09 20:58:29 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -232,7 +232,11 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
232 | break; | 232 | break; |
233 | } | 233 | } |
234 | case 'n': { | 234 | case 'n': { |
235 | ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; | 235 | /* calling function is a known Lua function? */ |
236 | if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) | ||
237 | ar->namewhat = getfuncname(L, ci->previous, &ar->name); | ||
238 | else | ||
239 | ar->namewhat = NULL; | ||
236 | if (ar->namewhat == NULL) { | 240 | if (ar->namewhat == NULL) { |
237 | ar->namewhat = ""; /* not found */ | 241 | ar->namewhat = ""; /* not found */ |
238 | ar->name = NULL; | 242 | ar->name = NULL; |
@@ -286,17 +290,16 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
286 | ** ======================================================= | 290 | ** ======================================================= |
287 | */ | 291 | */ |
288 | 292 | ||
289 | static const char *getobjname (lua_State *L, CallInfo *ci, int reg, | 293 | static const char *getobjname (Proto *p, int lastpc, int reg, |
290 | const char **name); | 294 | const char **name); |
291 | 295 | ||
292 | 296 | ||
293 | /* | 297 | /* |
294 | ** find a "name" for the RK value 'c' | 298 | ** find a "name" for the RK value 'c' |
295 | */ | 299 | */ |
296 | static void kname (lua_State *L, CallInfo *ci, int c, int oreg, | 300 | static void kname (Proto *p, int pc, int c, const char **name) { |
297 | const char *what, const char **name) { | ||
298 | if (ISK(c)) { /* is 'c' a constant? */ | 301 | if (ISK(c)) { /* is 'c' a constant? */ |
299 | TValue *kvalue = &ci_func(ci)->p->k[INDEXK(c)]; | 302 | TValue *kvalue = &p->k[INDEXK(c)]; |
300 | if (ttisstring(kvalue)) { /* literal constant? */ | 303 | if (ttisstring(kvalue)) { /* literal constant? */ |
301 | *name = svalue(kvalue); /* it is its own name */ | 304 | *name = svalue(kvalue); /* it is its own name */ |
302 | return; | 305 | return; |
@@ -304,8 +307,7 @@ static void kname (lua_State *L, CallInfo *ci, int c, int oreg, | |||
304 | /* else no reasonable name found */ | 307 | /* else no reasonable name found */ |
305 | } | 308 | } |
306 | else { /* 'c' is a register */ | 309 | else { /* 'c' is a register */ |
307 | if (c != oreg) /* not the original register? */ | 310 | const char *what = getobjname(p, pc, c, name); /* search for 'c' */ |
308 | what = getobjname(L, ci, c, name); /* search for 'c' */ | ||
309 | if (what && *what == 'c') { /* found a constant name? */ | 311 | if (what && *what == 'c') { /* found a constant name? */ |
310 | return; /* 'name' already filled */ | 312 | return; /* 'name' already filled */ |
311 | } | 313 | } |
@@ -315,85 +317,30 @@ static void kname (lua_State *L, CallInfo *ci, int c, int oreg, | |||
315 | } | 317 | } |
316 | 318 | ||
317 | 319 | ||
318 | static const char *getobjname (lua_State *L, CallInfo *ci, int reg, | 320 | /* |
319 | const char **name) { | 321 | ** try to find last instruction before 'lastpc' that modified register 'reg' |
320 | Proto *p = ci_func(ci)->p; | 322 | */ |
321 | const char *what = NULL; | 323 | static int findsetreg (Proto *p, int lastpc, int reg) { |
322 | int lastpc = currentpc(ci); | ||
323 | int pc; | 324 | int pc; |
324 | *name = luaF_getlocalname(p, reg + 1, lastpc); | 325 | int setreg = -1; /* keep last instruction that changed 'reg' */ |
325 | if (*name) /* is a local? */ | ||
326 | return "local"; | ||
327 | /* else try symbolic execution */ | ||
328 | for (pc = 0; pc < lastpc; pc++) { | 326 | for (pc = 0; pc < lastpc; pc++) { |
329 | Instruction i = p->code[pc]; | 327 | Instruction i = p->code[pc]; |
330 | OpCode op = GET_OPCODE(i); | 328 | OpCode op = GET_OPCODE(i); |
331 | int a = GETARG_A(i); | 329 | int a = GETARG_A(i); |
332 | switch (op) { | 330 | switch (op) { |
333 | case OP_MOVE: { | ||
334 | if (reg == a) { | ||
335 | int b = GETARG_B(i); /* move from 'b' to 'a' */ | ||
336 | if (b < a) | ||
337 | what = getobjname(L, ci, b, name); /* get name for 'b' */ | ||
338 | else what = NULL; | ||
339 | } | ||
340 | break; | ||
341 | } | ||
342 | case OP_GETTABUP: | ||
343 | case OP_GETTABLE: { | ||
344 | if (reg == a) { | ||
345 | int k = GETARG_C(i); /* key index */ | ||
346 | int t = GETARG_B(i); | ||
347 | const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ | ||
348 | ? luaF_getlocalname(p, t + 1, pc) | ||
349 | : getstr(p->upvalues[t].name); | ||
350 | kname(L, ci, k, a, what, name); | ||
351 | what = (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; | ||
352 | } | ||
353 | break; | ||
354 | } | ||
355 | case OP_GETUPVAL: { | ||
356 | if (reg == a) { | ||
357 | int u = GETARG_B(i); /* upvalue index */ | ||
358 | TString *tn = p->upvalues[u].name; | ||
359 | *name = tn ? getstr(tn) : "?"; | ||
360 | what = "upvalue"; | ||
361 | } | ||
362 | break; | ||
363 | } | ||
364 | case OP_LOADK: | ||
365 | case OP_LOADKX: { | ||
366 | if (reg == a) { | ||
367 | int b = (op == OP_LOADK) ? GETARG_Bx(i) | ||
368 | : GETARG_Ax(p->code[pc + 1]); | ||
369 | if (ttisstring(&p->k[b])) { | ||
370 | what = "constant"; | ||
371 | *name = svalue(&p->k[b]); | ||
372 | } | ||
373 | } | ||
374 | break; | ||
375 | } | ||
376 | case OP_LOADNIL: { | 331 | case OP_LOADNIL: { |
377 | int b = GETARG_B(i); | 332 | int b = GETARG_B(i); |
378 | if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ | 333 | if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ |
379 | what = NULL; | 334 | setreg = pc; |
380 | break; | ||
381 | } | ||
382 | case OP_SELF: { | ||
383 | if (reg == a) { | ||
384 | int k = GETARG_C(i); /* key index */ | ||
385 | kname(L, ci, k, a, what, name); | ||
386 | what = "method"; | ||
387 | } | ||
388 | break; | 335 | break; |
389 | } | 336 | } |
390 | case OP_TFORCALL: { | 337 | case OP_TFORCALL: { |
391 | if (reg >= a + 2) what = NULL; /* affect all regs above its base */ | 338 | if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ |
392 | break; | 339 | break; |
393 | } | 340 | } |
394 | case OP_CALL: | 341 | case OP_CALL: |
395 | case OP_TAILCALL: { | 342 | case OP_TAILCALL: { |
396 | if (reg >= a) what = NULL; /* affect all registers above base */ | 343 | if (reg >= a) setreg = pc; /* affect all registers above base */ |
397 | break; | 344 | break; |
398 | } | 345 | } |
399 | case OP_JMP: { | 346 | case OP_JMP: { |
@@ -405,35 +352,89 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, | |||
405 | break; | 352 | break; |
406 | } | 353 | } |
407 | case OP_TEST: { | 354 | case OP_TEST: { |
408 | if (reg == a) what = NULL; /* jumped code can change 'a' */ | 355 | if (reg == a) setreg = pc; /* jumped code can change 'a' */ |
409 | break; | 356 | break; |
410 | } | 357 | } |
411 | default: | 358 | default: |
412 | if (testAMode(op) && reg == a) what = NULL; | 359 | if (testAMode(op) && reg == a) /* any instruction that set A */ |
360 | setreg = pc; | ||
413 | break; | 361 | break; |
414 | } | 362 | } |
415 | } | 363 | } |
416 | return what; | 364 | return setreg; |
365 | } | ||
366 | |||
367 | |||
368 | static const char *getobjname (Proto *p, int lastpc, int reg, | ||
369 | const char **name) { | ||
370 | int pc; | ||
371 | *name = luaF_getlocalname(p, reg + 1, lastpc); | ||
372 | if (*name) /* is a local? */ | ||
373 | return "local"; | ||
374 | /* else try symbolic execution */ | ||
375 | pc = findsetreg(p, lastpc, reg); | ||
376 | if (pc != -1) { /* could find instruction? */ | ||
377 | Instruction i = p->code[pc]; | ||
378 | OpCode op = GET_OPCODE(i); | ||
379 | int a = GETARG_A(i); | ||
380 | switch (op) { | ||
381 | case OP_MOVE: { | ||
382 | int b = GETARG_B(i); /* move from 'b' to 'a' */ | ||
383 | lua_assert(reg == a); | ||
384 | if (b < a) | ||
385 | return getobjname(p, pc, b, name); /* get name for 'b' */ | ||
386 | } | ||
387 | case OP_GETTABUP: | ||
388 | case OP_GETTABLE: { | ||
389 | int k = GETARG_C(i); /* key index */ | ||
390 | int t = GETARG_B(i); | ||
391 | const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ | ||
392 | ? luaF_getlocalname(p, t + 1, pc) | ||
393 | : getstr(p->upvalues[t].name); | ||
394 | kname(p, pc, k, name); | ||
395 | return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; | ||
396 | } | ||
397 | case OP_GETUPVAL: { | ||
398 | int u = GETARG_B(i); /* upvalue index */ | ||
399 | TString *tn = p->upvalues[u].name; | ||
400 | *name = tn ? getstr(tn) : "?"; | ||
401 | return "upvalue"; | ||
402 | } | ||
403 | case OP_LOADK: | ||
404 | case OP_LOADKX: { | ||
405 | int b = (op == OP_LOADK) ? GETARG_Bx(i) | ||
406 | : GETARG_Ax(p->code[pc + 1]); | ||
407 | if (ttisstring(&p->k[b])) { | ||
408 | *name = svalue(&p->k[b]); | ||
409 | return "constant"; | ||
410 | } | ||
411 | } | ||
412 | case OP_SELF: { | ||
413 | int k = GETARG_C(i); /* key index */ | ||
414 | kname(p, pc, k, name); | ||
415 | return "method"; | ||
416 | } | ||
417 | default: break; /* go through to return NULL */ | ||
418 | } | ||
419 | } | ||
420 | return NULL; /* could not find reasonable name */ | ||
417 | } | 421 | } |
418 | 422 | ||
419 | 423 | ||
420 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | 424 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { |
421 | TMS tm; | 425 | TMS tm; |
422 | Instruction i; | 426 | Proto *p = ci_func(ci)->p; /* calling function */ |
423 | if ((ci->callstatus & CIST_TAIL) || !isLua(ci->previous)) | 427 | int pc = currentpc(ci); /* calling instruction index */ |
424 | return NULL; /* calling function is not Lua (or is unknown) */ | 428 | Instruction i = p->code[pc]; /* calling instruction */ |
425 | ci = ci->previous; /* calling function */ | ||
426 | i = ci_func(ci)->p->code[currentpc(ci)]; | ||
427 | if (GET_OPCODE(i) == OP_EXTRAARG) /* extra argument? */ | ||
428 | i = ci_func(ci)->p->code[currentpc(ci) - 1]; /* get 'real' instruction */ | ||
429 | switch (GET_OPCODE(i)) { | 429 | switch (GET_OPCODE(i)) { |
430 | case OP_CALL: | 430 | case OP_CALL: |
431 | case OP_TAILCALL: | 431 | case OP_TAILCALL: /* get function name */ |
432 | return getobjname(L, ci, GETARG_A(i), name); | 432 | return getobjname(p, pc, GETARG_A(i), name); |
433 | case OP_TFORCALL: { | 433 | case OP_TFORCALL: { /* for iterator */ |
434 | *name = "for iterator"; | 434 | *name = "for iterator"; |
435 | return "for iterator"; | 435 | return "for iterator"; |
436 | } | 436 | } |
437 | /* all other instructions can call only through metamethods */ | ||
437 | case OP_SELF: | 438 | case OP_SELF: |
438 | case OP_GETTABUP: | 439 | case OP_GETTABUP: |
439 | case OP_GETTABLE: tm = TM_INDEX; break; | 440 | case OP_GETTABLE: tm = TM_INDEX; break; |
@@ -496,7 +497,8 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |||
496 | if (isLua(ci)) { | 497 | if (isLua(ci)) { |
497 | kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ | 498 | kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ |
498 | if (!kind && isinstack(ci, o)) /* no? try a register */ | 499 | if (!kind && isinstack(ci, o)) /* no? try a register */ |
499 | kind = getobjname(L, ci, cast_int(o - ci->u.l.base), &name); | 500 | kind = getobjname(ci_func(ci)->p, currentpc(ci), |
501 | cast_int(o - ci->u.l.base), &name); | ||
500 | } | 502 | } |
501 | if (kind) | 503 | if (kind) |
502 | luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", | 504 | luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", |