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) { |