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 /ldebug.c | |
| 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)
Diffstat (limited to 'ldebug.c')
| -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"; |
