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)", |
