|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
-** $Id: ldebug.c,v 2.48 2009/04/27 18:58:31 roberto Exp roberto $
|
|
|
|
|
|
+** $Id: ldebug.c,v 2.49 2009/04/30 17:42:21 roberto Exp roberto $
|
|
** Debug Interface
|
|
** Debug Interface
|
|
** See Copyright Notice in lua.h
|
|
** See Copyright Notice in lua.h
|
|
*/
|
|
*/
|
|
@@ -269,137 +269,109 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
-static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
|
|
|
|
- int pc;
|
|
|
|
- int last; /* stores position of last instruction that changed `reg' */
|
|
|
|
- last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
|
|
|
|
|
|
+static const char *kname (Proto *p, int c) {
|
|
|
|
+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
|
|
|
|
+ return svalue(&p->k[INDEXK(c)]);
|
|
|
|
+ else
|
|
|
|
+ return "?";
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static const char *getobjname (lua_State *L, CallInfo *ci, int reg,
|
|
|
|
+ const char **name) {
|
|
|
|
+ Proto *p;
|
|
|
|
+ int lastpc, pc;
|
|
|
|
+ const char *what = NULL;
|
|
|
|
+ if (!isLua(ci)) /* is not a Lua function? */
|
|
|
|
+ return NULL; /* cannot find name for it */
|
|
|
|
+ p = ci_func(ci)->l.p;
|
|
|
|
+ lastpc = currentpc(ci);
|
|
|
|
+ *name = luaF_getlocalname(p, reg + 1, lastpc);
|
|
|
|
+ if (*name) /* is a local? */
|
|
|
|
+ return "local";
|
|
|
|
+ /* else try symbolic execution */
|
|
for (pc = 0; pc < lastpc; pc++) {
|
|
for (pc = 0; pc < lastpc; pc++) {
|
|
- Instruction i = pt->code[pc];
|
|
|
|
|
|
+ Instruction i = p->code[pc];
|
|
OpCode op = GET_OPCODE(i);
|
|
OpCode op = GET_OPCODE(i);
|
|
int a = GETARG_A(i);
|
|
int a = GETARG_A(i);
|
|
- int b = 0;
|
|
|
|
- int c = 0;
|
|
|
|
- switch (getOpMode(op)) {
|
|
|
|
- case iABC: {
|
|
|
|
- b = GETARG_B(i);
|
|
|
|
- c = GETARG_C(i);
|
|
|
|
|
|
+ switch (op) {
|
|
|
|
+ case OP_GETGLOBAL: {
|
|
|
|
+ if (reg == a) {
|
|
|
|
+ int g = GETARG_Bx(i); /* global index */
|
|
|
|
+ lua_assert(ttisstring(&p->k[g]));
|
|
|
|
+ *name = svalue(&p->k[g]);
|
|
|
|
+ what = "global";
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case OP_MOVE: {
|
|
|
|
+ if (reg == a) {
|
|
|
|
+ int b = GETARG_B(i); /* move from 'b' to 'a' */
|
|
|
|
+ if (b < a)
|
|
|
|
+ what = getobjname(L, ci, b, name); /* get name for 'b' */
|
|
|
|
+ else what = NULL;
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case iABx: {
|
|
|
|
- b = GETARG_Bx(i);
|
|
|
|
|
|
+ case OP_GETTABLE: {
|
|
|
|
+ if (reg == a) {
|
|
|
|
+ int k = GETARG_C(i); /* key index */
|
|
|
|
+ *name = kname(p, k);
|
|
|
|
+ what = "field";
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case iAsBx: {
|
|
|
|
- b = GETARG_sBx(i);
|
|
|
|
|
|
+ case OP_GETUPVAL: {
|
|
|
|
+ if (reg == a) {
|
|
|
|
+ int u = GETARG_B(i); /* upvalue index */
|
|
|
|
+ *name = p->upvalues ? getstr(p->upvalues[u]) : "?";
|
|
|
|
+ what = "upvalue";
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case iAx: break;
|
|
|
|
- }
|
|
|
|
- if (testAMode(op)) {
|
|
|
|
- if (a == reg) last = pc; /* change register `a' */
|
|
|
|
- }
|
|
|
|
- switch (op) {
|
|
|
|
case OP_LOADNIL: {
|
|
case OP_LOADNIL: {
|
|
- if (a <= reg && reg <= b)
|
|
|
|
- last = pc; /* set registers from `a' to `b' */
|
|
|
|
|
|
+ int b = GETARG_B(i); /* move from 'b' to 'a' */
|
|
|
|
+ if (a <= reg && reg <= b) /* set registers from 'a' to 'b' */
|
|
|
|
+ what = NULL;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case OP_SELF: {
|
|
case OP_SELF: {
|
|
- if (reg == a+1) last = pc;
|
|
|
|
|
|
+ if (reg == a) {
|
|
|
|
+ int k = GETARG_C(i); /* key index */
|
|
|
|
+ *name = kname(p, k);
|
|
|
|
+ what = "method";
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case OP_TFORCALL: {
|
|
case OP_TFORCALL: {
|
|
- if (reg >= a+2) last = pc; /* affect all regs above its base */
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- case OP_TFORLOOP:
|
|
|
|
- case OP_FORLOOP:
|
|
|
|
- case OP_FORPREP:
|
|
|
|
- case OP_JMP: {
|
|
|
|
- int dest = pc+1+b;
|
|
|
|
- /* not full check and jump is forward and do not skip `lastpc'? */
|
|
|
|
- if (reg != NO_REG && pc < dest && dest <= lastpc)
|
|
|
|
- pc += b; /* do the jump */
|
|
|
|
|
|
+ if (reg >= a + 2) what = NULL; /* affect all regs above its base */
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case OP_CALL:
|
|
case OP_CALL:
|
|
case OP_TAILCALL: {
|
|
case OP_TAILCALL: {
|
|
- if (reg >= a) last = pc; /* affect all registers above base */
|
|
|
|
|
|
+ if (reg >= a) what = NULL; /* affect all registers above base */
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case OP_CLOSURE: {
|
|
|
|
- int nup = pt->p[b]->nups;
|
|
|
|
- pc += nup; /* do not 'execute' pseudo-instructions */
|
|
|
|
|
|
+ case OP_JMP: {
|
|
|
|
+ int b = GETARG_sBx(i);
|
|
|
|
+ int dest = pc + 1 + b;
|
|
|
|
+ /* jump is forward and do not skip `lastpc'? */
|
|
|
|
+ if (pc < dest && dest <= lastpc)
|
|
|
|
+ pc += b; /* do the jump */
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case OP_VARARG: {
|
|
|
|
- b--; /* ??? */
|
|
|
|
|
|
+ case OP_CLOSURE: {
|
|
|
|
+ int nup = p->p[GETARG_Bx(i)]->nups;
|
|
|
|
+ pc += nup; /* do not 'execute' pseudo-instructions */
|
|
|
|
+ lua_assert(pc <= lastpc);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- default: break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return pt->code[last];
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#undef check
|
|
|
|
-#undef checkreg
|
|
|
|
-
|
|
|
|
-/* }====================================================== */
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-static const char *kname (Proto *p, int c) {
|
|
|
|
- if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
|
|
|
|
- return svalue(&p->k[INDEXK(c)]);
|
|
|
|
- else
|
|
|
|
- return "?";
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
|
|
|
|
- const char **name) {
|
|
|
|
- if (isLua(ci)) { /* a Lua function? */
|
|
|
|
- Proto *p = ci_func(ci)->l.p;
|
|
|
|
- int pc = currentpc(ci);
|
|
|
|
- Instruction i;
|
|
|
|
- *name = luaF_getlocalname(p, stackpos+1, pc);
|
|
|
|
- if (*name) /* is a local? */
|
|
|
|
- return "local";
|
|
|
|
- i = symbexec(p, pc, stackpos); /* try symbolic execution */
|
|
|
|
- lua_assert(pc != -1);
|
|
|
|
- switch (GET_OPCODE(i)) {
|
|
|
|
- case OP_GETGLOBAL: {
|
|
|
|
- int g = GETARG_Bx(i); /* global index */
|
|
|
|
- lua_assert(ttisstring(&p->k[g]));
|
|
|
|
- *name = svalue(&p->k[g]);
|
|
|
|
- return "global";
|
|
|
|
- }
|
|
|
|
- case OP_MOVE: {
|
|
|
|
- int a = GETARG_A(i);
|
|
|
|
- int b = GETARG_B(i); /* move from `b' to `a' */
|
|
|
|
- if (b < a)
|
|
|
|
- return getobjname(L, ci, b, name); /* get name for `b' */
|
|
|
|
|
|
+ default:
|
|
|
|
+ if (testAMode(op) && reg == a) what = NULL;
|
|
break;
|
|
break;
|
|
- }
|
|
|
|
- case OP_GETTABLE: {
|
|
|
|
- int k = GETARG_C(i); /* key index */
|
|
|
|
- *name = kname(p, k);
|
|
|
|
- return "field";
|
|
|
|
- }
|
|
|
|
- case OP_GETUPVAL: {
|
|
|
|
- int u = GETARG_B(i); /* upvalue index */
|
|
|
|
- *name = p->upvalues ? getstr(p->upvalues[u]) : "?";
|
|
|
|
- return "upvalue";
|
|
|
|
- }
|
|
|
|
- case OP_SELF: {
|
|
|
|
- int k = GETARG_C(i); /* key index */
|
|
|
|
- *name = kname(p, k);
|
|
|
|
- return "method";
|
|
|
|
- }
|
|
|
|
- default: break;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return NULL; /* no useful name found */
|
|
|
|
|
|
+ return what;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -439,6 +411,9 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
|
return "metamethod";
|
|
return "metamethod";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* }====================================================== */
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
/* only ANSI way to check whether a pointer points to an array */
|
|
/* only ANSI way to check whether a pointer points to an array */
|
|
static int isinstack (CallInfo *ci, const TValue *o) {
|
|
static int isinstack (CallInfo *ci, const TValue *o) {
|