diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-05-04 15:26:21 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-05-04 15:26:21 -0300 |
| commit | e67dc3a22722837a968122a77d9e0398d103378d (patch) | |
| tree | 340bacd04077407bcaea210a1511a58df67c1bfc | |
| parent | 0cc3add9f80efa62722b085a281aa449e9a0112c (diff) | |
| download | lua-e67dc3a22722837a968122a77d9e0398d103378d.tar.gz lua-e67dc3a22722837a968122a77d9e0398d103378d.tar.bz2 lua-e67dc3a22722837a968122a77d9e0398d103378d.zip | |
'symbexec' merged with 'getobjname' (as only use for symbolic execution
now is to find a "good" name for an object)
| -rw-r--r-- | ldebug.c | 181 |
1 files changed, 78 insertions, 103 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.c,v 2.48 2009/04/27 18:58:31 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.49 2009/04/30 17:42:21 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 | */ |
| @@ -269,137 +269,109 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
| 269 | */ | 269 | */ |
| 270 | 270 | ||
| 271 | 271 | ||
| 272 | static Instruction symbexec (const Proto *pt, int lastpc, int reg) { | 272 | static const char *kname (Proto *p, int c) { |
| 273 | int pc; | 273 | if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) |
| 274 | int last; /* stores position of last instruction that changed `reg' */ | 274 | return svalue(&p->k[INDEXK(c)]); |
| 275 | last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ | 275 | else |
| 276 | return "?"; | ||
| 277 | } | ||
| 278 | |||
| 279 | |||
| 280 | static const char *getobjname (lua_State *L, CallInfo *ci, int reg, | ||
| 281 | const char **name) { | ||
| 282 | Proto *p; | ||
| 283 | int lastpc, pc; | ||
| 284 | const char *what = NULL; | ||
| 285 | if (!isLua(ci)) /* is not a Lua function? */ | ||
| 286 | return NULL; /* cannot find name for it */ | ||
| 287 | p = ci_func(ci)->l.p; | ||
| 288 | lastpc = currentpc(ci); | ||
| 289 | *name = luaF_getlocalname(p, reg + 1, lastpc); | ||
| 290 | if (*name) /* is a local? */ | ||
| 291 | return "local"; | ||
| 292 | /* else try symbolic execution */ | ||
| 276 | for (pc = 0; pc < lastpc; pc++) { | 293 | for (pc = 0; pc < lastpc; pc++) { |
| 277 | Instruction i = pt->code[pc]; | 294 | Instruction i = p->code[pc]; |
| 278 | OpCode op = GET_OPCODE(i); | 295 | OpCode op = GET_OPCODE(i); |
| 279 | int a = GETARG_A(i); | 296 | int a = GETARG_A(i); |
| 280 | int b = 0; | 297 | switch (op) { |
| 281 | int c = 0; | 298 | case OP_GETGLOBAL: { |
| 282 | switch (getOpMode(op)) { | 299 | if (reg == a) { |
| 283 | case iABC: { | 300 | int g = GETARG_Bx(i); /* global index */ |
| 284 | b = GETARG_B(i); | 301 | lua_assert(ttisstring(&p->k[g])); |
| 285 | c = GETARG_C(i); | 302 | *name = svalue(&p->k[g]); |
| 303 | what = "global"; | ||
| 304 | } | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | case OP_MOVE: { | ||
| 308 | if (reg == a) { | ||
| 309 | int b = GETARG_B(i); /* move from 'b' to 'a' */ | ||
| 310 | if (b < a) | ||
| 311 | what = getobjname(L, ci, b, name); /* get name for 'b' */ | ||
| 312 | else what = NULL; | ||
| 313 | } | ||
| 286 | break; | 314 | break; |
| 287 | } | 315 | } |
| 288 | case iABx: { | 316 | case OP_GETTABLE: { |
| 289 | b = GETARG_Bx(i); | 317 | if (reg == a) { |
| 318 | int k = GETARG_C(i); /* key index */ | ||
| 319 | *name = kname(p, k); | ||
| 320 | what = "field"; | ||
| 321 | } | ||
| 290 | break; | 322 | break; |
| 291 | } | 323 | } |
| 292 | case iAsBx: { | 324 | case OP_GETUPVAL: { |
| 293 | b = GETARG_sBx(i); | 325 | if (reg == a) { |
| 326 | int u = GETARG_B(i); /* upvalue index */ | ||
| 327 | *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; | ||
| 328 | what = "upvalue"; | ||
| 329 | } | ||
| 294 | break; | 330 | break; |
| 295 | } | 331 | } |
| 296 | case iAx: break; | ||
| 297 | } | ||
| 298 | if (testAMode(op)) { | ||
| 299 | if (a == reg) last = pc; /* change register `a' */ | ||
| 300 | } | ||
| 301 | switch (op) { | ||
| 302 | case OP_LOADNIL: { | 332 | case OP_LOADNIL: { |
| 303 | if (a <= reg && reg <= b) | 333 | int b = GETARG_B(i); /* move from 'b' to 'a' */ |
| 304 | last = pc; /* set registers from `a' to `b' */ | 334 | if (a <= reg && reg <= b) /* set registers from 'a' to 'b' */ |
| 335 | what = NULL; | ||
| 305 | break; | 336 | break; |
| 306 | } | 337 | } |
| 307 | case OP_SELF: { | 338 | case OP_SELF: { |
| 308 | if (reg == a+1) last = pc; | 339 | if (reg == a) { |
| 340 | int k = GETARG_C(i); /* key index */ | ||
| 341 | *name = kname(p, k); | ||
| 342 | what = "method"; | ||
| 343 | } | ||
| 309 | break; | 344 | break; |
| 310 | } | 345 | } |
| 311 | case OP_TFORCALL: { | 346 | case OP_TFORCALL: { |
| 312 | if (reg >= a+2) last = pc; /* affect all regs above its base */ | 347 | if (reg >= a + 2) what = NULL; /* affect all regs above its base */ |
| 313 | break; | ||
| 314 | } | ||
| 315 | case OP_TFORLOOP: | ||
| 316 | case OP_FORLOOP: | ||
| 317 | case OP_FORPREP: | ||
| 318 | case OP_JMP: { | ||
| 319 | int dest = pc+1+b; | ||
| 320 | /* not full check and jump is forward and do not skip `lastpc'? */ | ||
| 321 | if (reg != NO_REG && pc < dest && dest <= lastpc) | ||
| 322 | pc += b; /* do the jump */ | ||
| 323 | break; | 348 | break; |
| 324 | } | 349 | } |
| 325 | case OP_CALL: | 350 | case OP_CALL: |
| 326 | case OP_TAILCALL: { | 351 | case OP_TAILCALL: { |
| 327 | if (reg >= a) last = pc; /* affect all registers above base */ | 352 | if (reg >= a) what = NULL; /* affect all registers above base */ |
| 328 | break; | 353 | break; |
| 329 | } | 354 | } |
| 330 | case OP_CLOSURE: { | 355 | case OP_JMP: { |
| 331 | int nup = pt->p[b]->nups; | 356 | int b = GETARG_sBx(i); |
| 332 | pc += nup; /* do not 'execute' pseudo-instructions */ | 357 | int dest = pc + 1 + b; |
| 358 | /* jump is forward and do not skip `lastpc'? */ | ||
| 359 | if (pc < dest && dest <= lastpc) | ||
| 360 | pc += b; /* do the jump */ | ||
| 333 | break; | 361 | break; |
| 334 | } | 362 | } |
| 335 | case OP_VARARG: { | 363 | case OP_CLOSURE: { |
| 336 | b--; /* ??? */ | 364 | int nup = p->p[GETARG_Bx(i)]->nups; |
| 365 | pc += nup; /* do not 'execute' pseudo-instructions */ | ||
| 366 | lua_assert(pc <= lastpc); | ||
| 337 | break; | 367 | break; |
| 338 | } | 368 | } |
| 339 | default: break; | 369 | default: |
| 340 | } | 370 | if (testAMode(op) && reg == a) what = NULL; |
| 341 | } | ||
| 342 | return pt->code[last]; | ||
| 343 | } | ||
| 344 | |||
| 345 | #undef check | ||
| 346 | #undef checkreg | ||
| 347 | |||
| 348 | /* }====================================================== */ | ||
| 349 | |||
| 350 | |||
| 351 | static const char *kname (Proto *p, int c) { | ||
| 352 | if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) | ||
| 353 | return svalue(&p->k[INDEXK(c)]); | ||
| 354 | else | ||
| 355 | return "?"; | ||
| 356 | } | ||
| 357 | |||
| 358 | |||
| 359 | static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, | ||
| 360 | const char **name) { | ||
| 361 | if (isLua(ci)) { /* a Lua function? */ | ||
| 362 | Proto *p = ci_func(ci)->l.p; | ||
| 363 | int pc = currentpc(ci); | ||
| 364 | Instruction i; | ||
| 365 | *name = luaF_getlocalname(p, stackpos+1, pc); | ||
| 366 | if (*name) /* is a local? */ | ||
| 367 | return "local"; | ||
| 368 | i = symbexec(p, pc, stackpos); /* try symbolic execution */ | ||
| 369 | lua_assert(pc != -1); | ||
| 370 | switch (GET_OPCODE(i)) { | ||
| 371 | case OP_GETGLOBAL: { | ||
| 372 | int g = GETARG_Bx(i); /* global index */ | ||
| 373 | lua_assert(ttisstring(&p->k[g])); | ||
| 374 | *name = svalue(&p->k[g]); | ||
| 375 | return "global"; | ||
| 376 | } | ||
| 377 | case OP_MOVE: { | ||
| 378 | int a = GETARG_A(i); | ||
| 379 | int b = GETARG_B(i); /* move from `b' to `a' */ | ||
| 380 | if (b < a) | ||
| 381 | return getobjname(L, ci, b, name); /* get name for `b' */ | ||
| 382 | break; | 371 | break; |
| 383 | } | ||
| 384 | case OP_GETTABLE: { | ||
| 385 | int k = GETARG_C(i); /* key index */ | ||
| 386 | *name = kname(p, k); | ||
| 387 | return "field"; | ||
| 388 | } | ||
| 389 | case OP_GETUPVAL: { | ||
| 390 | int u = GETARG_B(i); /* upvalue index */ | ||
| 391 | *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; | ||
| 392 | return "upvalue"; | ||
| 393 | } | ||
| 394 | case OP_SELF: { | ||
| 395 | int k = GETARG_C(i); /* key index */ | ||
| 396 | *name = kname(p, k); | ||
| 397 | return "method"; | ||
| 398 | } | ||
| 399 | default: break; | ||
| 400 | } | 372 | } |
| 401 | } | 373 | } |
| 402 | return NULL; /* no useful name found */ | 374 | return what; |
| 403 | } | 375 | } |
| 404 | 376 | ||
| 405 | 377 | ||
| @@ -439,6 +411,9 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | |||
| 439 | return "metamethod"; | 411 | return "metamethod"; |
| 440 | } | 412 | } |
| 441 | 413 | ||
| 414 | /* }====================================================== */ | ||
| 415 | |||
| 416 | |||
| 442 | 417 | ||
| 443 | /* only ANSI way to check whether a pointer points to an array */ | 418 | /* only ANSI way to check whether a pointer points to an array */ |
| 444 | static int isinstack (CallInfo *ci, const TValue *o) { | 419 | static int isinstack (CallInfo *ci, const TValue *o) { |
