aboutsummaryrefslogtreecommitdiff
path: root/ldebug.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldebug.c')
-rw-r--r--ldebug.c127
1 files changed, 5 insertions, 122 deletions
diff --git a/ldebug.c b/ldebug.c
index 0e9d6282..5e93bdd8 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.47 2009/04/17 22:00:01 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.48 2009/04/27 18:58:31 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*/
@@ -264,89 +264,33 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
264 264
265/* 265/*
266** {====================================================== 266** {======================================================
267** Symbolic Execution and code checker 267** Symbolic Execution
268** ======================================================= 268** =======================================================
269*/ 269*/
270 270
271#define check(x) if (!(x)) return 0;
272
273#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize)
274
275
276
277static int precheck (const Proto *pt) {
278 check(pt->maxstacksize <= MAXSTACK);
279 check(pt->numparams <= pt->maxstacksize);
280 check(pt->sizeupvalues == pt->nups || pt->sizeupvalues == 0);
281 check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
282 check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
283 return 1;
284}
285
286
287#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
288
289int luaG_checkopenop (Instruction i) {
290 switch (GET_OPCODE(i)) {
291 case OP_CALL:
292 case OP_TAILCALL:
293 case OP_RETURN:
294 case OP_SETLIST: {
295 check(GETARG_B(i) == 0);
296 return 1;
297 }
298 default: return 0; /* invalid instruction after an open call */
299 }
300}
301
302
303static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
304 switch (mode) {
305 case OpArgN: check(r == 0); break;
306 case OpArgU: break;
307 case OpArgR: checkreg(pt, r); break;
308 case OpArgK:
309 check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
310 break;
311 }
312 return 1;
313}
314
315 271
316static Instruction symbexec (const Proto *pt, int lastpc, int reg) { 272static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
317 int pc; 273 int pc;
318 int last; /* stores position of last instruction that changed `reg' */ 274 int last; /* stores position of last instruction that changed `reg' */
319 last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ 275 last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
320 check(precheck(pt));
321 for (pc = 0; pc < lastpc; pc++) { 276 for (pc = 0; pc < lastpc; pc++) {
322 Instruction i = pt->code[pc]; 277 Instruction i = pt->code[pc];
323 OpCode op = GET_OPCODE(i); 278 OpCode op = GET_OPCODE(i);
324 int a = GETARG_A(i); 279 int a = GETARG_A(i);
325 int b = 0; 280 int b = 0;
326 int c = 0; 281 int c = 0;
327 check(op < NUM_OPCODES);
328 switch (getOpMode(op)) { 282 switch (getOpMode(op)) {
329 case iABC: { 283 case iABC: {
330 checkreg(pt, a);
331 b = GETARG_B(i); 284 b = GETARG_B(i);
332 c = GETARG_C(i); 285 c = GETARG_C(i);
333 check(checkArgMode(pt, b, getBMode(op)));
334 check(checkArgMode(pt, c, getCMode(op)));
335 break; 286 break;
336 } 287 }
337 case iABx: { 288 case iABx: {
338 checkreg(pt, a);
339 b = GETARG_Bx(i); 289 b = GETARG_Bx(i);
340 if (getBMode(op) == OpArgK) check(b < pt->sizek);
341 break; 290 break;
342 } 291 }
343 case iAsBx: { 292 case iAsBx: {
344 checkreg(pt, a);
345 b = GETARG_sBx(i); 293 b = GETARG_sBx(i);
346 if (getBMode(op) == OpArgR) {
347 int dest = pc+1+b;
348 check(0 <= dest && dest < pt->sizecode);
349 }
350 break; 294 break;
351 } 295 }
352 case iAx: break; 296 case iAx: break;
@@ -354,49 +298,23 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
354 if (testAMode(op)) { 298 if (testAMode(op)) {
355 if (a == reg) last = pc; /* change register `a' */ 299 if (a == reg) last = pc; /* change register `a' */
356 } 300 }
357 if (testTMode(op))
358 check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
359 switch (op) { 301 switch (op) {
360 case OP_LOADBOOL: {
361 check(c == 0 || pc+2 < pt->sizecode); /* check its jump */
362 break;
363 }
364 case OP_LOADNIL: { 302 case OP_LOADNIL: {
365 if (a <= reg && reg <= b) 303 if (a <= reg && reg <= b)
366 last = pc; /* set registers from `a' to `b' */ 304 last = pc; /* set registers from `a' to `b' */
367 break; 305 break;
368 } 306 }
369 case OP_GETUPVAL:
370 case OP_SETUPVAL: {
371 check(b < pt->nups);
372 break;
373 }
374 case OP_GETGLOBAL:
375 case OP_SETGLOBAL: {
376 check(ttisstring(&pt->k[b]));
377 break;
378 }
379 case OP_SELF: { 307 case OP_SELF: {
380 checkreg(pt, a+1);
381 if (reg == a+1) last = pc; 308 if (reg == a+1) last = pc;
382 break; 309 break;
383 } 310 }
384 case OP_CONCAT: {
385 check(b < c); /* at least two operands */
386 break;
387 }
388 case OP_TFORCALL: { 311 case OP_TFORCALL: {
389 check(c >= 1); /* at least one result (control variable) */
390 checkreg(pt, a+2+c); /* space for results */
391 check(GET_OPCODE(pt->code[pc+1]) == OP_TFORLOOP);
392 if (reg >= a+2) last = pc; /* affect all regs above its base */ 312 if (reg >= a+2) last = pc; /* affect all regs above its base */
393 break; 313 break;
394 } 314 }
395 case OP_TFORLOOP: 315 case OP_TFORLOOP:
396 case OP_FORLOOP: 316 case OP_FORLOOP:
397 case OP_FORPREP: 317 case OP_FORPREP:
398 checkreg(pt, a+3);
399 /* go through */
400 case OP_JMP: { 318 case OP_JMP: {
401 int dest = pc+1+b; 319 int dest = pc+1+b;
402 /* not full check and jump is forward and do not skip `lastpc'? */ 320 /* not full check and jump is forward and do not skip `lastpc'? */
@@ -406,46 +324,16 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
406 } 324 }
407 case OP_CALL: 325 case OP_CALL:
408 case OP_TAILCALL: { 326 case OP_TAILCALL: {
409 if (b != 0) {
410 checkreg(pt, a+b-1);
411 }
412 c--; /* c = num. returns */
413 if (c == LUA_MULTRET) {
414 check(checkopenop(pt, pc));
415 }
416 else if (c != 0)
417 checkreg(pt, a+c-1);
418 if (reg >= a) last = pc; /* affect all registers above base */ 327 if (reg >= a) last = pc; /* affect all registers above base */
419 break; 328 break;
420 } 329 }
421 case OP_RETURN: {
422 b--; /* b = num. returns */
423 if (b > 0) checkreg(pt, a+b-1);
424 break;
425 }
426 case OP_SETLIST: {
427 if (b > 0) checkreg(pt, a + b);
428 if (c == 0) check(GET_OPCODE(pt->code[pc + 1]) == OP_EXTRAARG);
429 break;
430 }
431 case OP_CLOSURE: { 330 case OP_CLOSURE: {
432 int nup, j; 331 int nup = pt->p[b]->nups;
433 check(b < pt->sizep); 332 pc += nup; /* do not 'execute' pseudo-instructions */
434 nup = pt->p[b]->nups;
435 check(pc + nup < pt->sizecode);
436 for (j = 1; j <= nup; j++) {
437 OpCode op1 = GET_OPCODE(pt->code[pc + j]);
438 check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
439 }
440 if (reg != NO_REG) /* tracing? */
441 pc += nup; /* do not 'execute' these pseudo-instructions */
442 break; 333 break;
443 } 334 }
444 case OP_VARARG: { 335 case OP_VARARG: {
445 check(pt->is_vararg); 336 b--; /* ??? */
446 b--;
447 if (b == LUA_MULTRET) check(checkopenop(pt, pc));
448 checkreg(pt, a+b-1);
449 break; 337 break;
450 } 338 }
451 default: break; 339 default: break;
@@ -460,11 +348,6 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
460/* }====================================================== */ 348/* }====================================================== */
461 349
462 350
463int luaG_checkcode (const Proto *pt) {
464 return (symbexec(pt, pt->sizecode, NO_REG) != 0);
465}
466
467
468static const char *kname (Proto *p, int c) { 351static const char *kname (Proto *p, int c) {
469 if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) 352 if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
470 return svalue(&p->k[INDEXK(c)]); 353 return svalue(&p->k[INDEXK(c)]);