diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-10-19 10:32:10 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-10-19 10:32:10 -0200 |
commit | e2dc807c6e93dc8819d065ae8e3808c720928bbd (patch) | |
tree | f92d70870b66523e297c98f47ebcaacfa1adffb1 | |
parent | 138d00176ca3330b0ad18eb4006605746b68df94 (diff) | |
download | lua-e2dc807c6e93dc8819d065ae8e3808c720928bbd.tar.gz lua-e2dc807c6e93dc8819d065ae8e3808c720928bbd.tar.bz2 lua-e2dc807c6e93dc8819d065ae8e3808c720928bbd.zip |
check whether function is finalizer when finding a name for it +
comments + some instructions can call functions in unespected ways
(e.g., finalizers)
-rw-r--r-- | ldebug.c | 45 |
1 files changed, 32 insertions, 13 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 2.119 2016/02/26 19:20:15 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.120 2016/03/31 19:01: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 | */ |
@@ -38,7 +38,8 @@ | |||
38 | #define ci_func(ci) (clLvalue((ci)->func)) | 38 | #define ci_func(ci) (clLvalue((ci)->func)) |
39 | 39 | ||
40 | 40 | ||
41 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); | 41 | static const char *funcnamefromcode (lua_State *L, CallInfo *ci, |
42 | const char **name); | ||
42 | 43 | ||
43 | 44 | ||
44 | static int currentpc (CallInfo *ci) { | 45 | static int currentpc (CallInfo *ci) { |
@@ -244,6 +245,20 @@ static void collectvalidlines (lua_State *L, Closure *f) { | |||
244 | } | 245 | } |
245 | 246 | ||
246 | 247 | ||
248 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | ||
249 | if (ci == NULL) /* no 'ci'? */ | ||
250 | return NULL; /* no info */ | ||
251 | else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ | ||
252 | *name = "__gc"; | ||
253 | return "metamethod"; /* report it as such */ | ||
254 | } | ||
255 | /* calling function is a known Lua function? */ | ||
256 | else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) | ||
257 | return funcnamefromcode(L, ci->previous, name); | ||
258 | else return NULL; /* no way to find a name */ | ||
259 | } | ||
260 | |||
261 | |||
247 | static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | 262 | static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, |
248 | Closure *f, CallInfo *ci) { | 263 | Closure *f, CallInfo *ci) { |
249 | int status = 1; | 264 | int status = 1; |
@@ -274,11 +289,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
274 | break; | 289 | break; |
275 | } | 290 | } |
276 | case 'n': { | 291 | case 'n': { |
277 | /* calling function is a known Lua function? */ | 292 | ar->namewhat = getfuncname(L, ci, &ar->name); |
278 | if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) | ||
279 | ar->namewhat = getfuncname(L, ci->previous, &ar->name); | ||
280 | else | ||
281 | ar->namewhat = NULL; | ||
282 | if (ar->namewhat == NULL) { | 293 | if (ar->namewhat == NULL) { |
283 | ar->namewhat = ""; /* not found */ | 294 | ar->namewhat = ""; /* not found */ |
284 | ar->name = NULL; | 295 | ar->name = NULL; |
@@ -471,8 +482,15 @@ static const char *getobjname (Proto *p, int lastpc, int reg, | |||
471 | } | 482 | } |
472 | 483 | ||
473 | 484 | ||
474 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | 485 | /* |
475 | TMS tm = (TMS)0; /* to avoid warnings */ | 486 | ** Try to find a name for a function based on the code that called it. |
487 | ** (Only works when function was called by a Lua function.) | ||
488 | ** Returns what the name is (e.g., "for iterator", "method", | ||
489 | ** "metamethod") and sets '*name' to point to the name. | ||
490 | */ | ||
491 | static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | ||
492 | const char **name) { | ||
493 | TMS tm = (TMS)0; /* (initial value avoids warnings) */ | ||
476 | Proto *p = ci_func(ci)->p; /* calling function */ | 494 | Proto *p = ci_func(ci)->p; /* calling function */ |
477 | int pc = currentpc(ci); /* calling instruction index */ | 495 | int pc = currentpc(ci); /* calling instruction index */ |
478 | Instruction i = p->code[pc]; /* calling instruction */ | 496 | Instruction i = p->code[pc]; /* calling instruction */ |
@@ -482,13 +500,13 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | |||
482 | } | 500 | } |
483 | switch (GET_OPCODE(i)) { | 501 | switch (GET_OPCODE(i)) { |
484 | case OP_CALL: | 502 | case OP_CALL: |
485 | case OP_TAILCALL: /* get function name */ | 503 | case OP_TAILCALL: |
486 | return getobjname(p, pc, GETARG_A(i), name); | 504 | return getobjname(p, pc, GETARG_A(i), name); /* get function name */ |
487 | case OP_TFORCALL: { /* for iterator */ | 505 | case OP_TFORCALL: { /* for iterator */ |
488 | *name = "for iterator"; | 506 | *name = "for iterator"; |
489 | return "for iterator"; | 507 | return "for iterator"; |
490 | } | 508 | } |
491 | /* all other instructions can call only through metamethods */ | 509 | /* other instructions can do calls through metamethods */ |
492 | case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: | 510 | case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: |
493 | tm = TM_INDEX; | 511 | tm = TM_INDEX; |
494 | break; | 512 | break; |
@@ -509,7 +527,8 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | |||
509 | case OP_EQ: tm = TM_EQ; break; | 527 | case OP_EQ: tm = TM_EQ; break; |
510 | case OP_LT: tm = TM_LT; break; | 528 | case OP_LT: tm = TM_LT; break; |
511 | case OP_LE: tm = TM_LE; break; | 529 | case OP_LE: tm = TM_LE; break; |
512 | default: lua_assert(0); /* other instructions cannot call a function */ | 530 | default: |
531 | return NULL; /* cannot find a reasonable name */ | ||
513 | } | 532 | } |
514 | *name = getstr(G(L)->tmname[tm]); | 533 | *name = getstr(G(L)->tmname[tm]); |
515 | return "metamethod"; | 534 | return "metamethod"; |