LCOV - code coverage report
Current view: top level - external/lua/src - ldebug.c (source / functions) Hit Total Coverage
Test: rapport Lines: 172 462 37.2 %
Date: 2021-12-10 16:22:55 Functions: 23 43 53.5 %
Branches: 72 263 27.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            : ** $Id: ldebug.c $
       3                 :            : ** Debug Interface
       4                 :            : ** See Copyright Notice in lua.h
       5                 :            : */
       6                 :            : 
       7                 :            : #define ldebug_c
       8                 :            : #define LUA_CORE
       9                 :            : 
      10                 :            : #include "lprefix.h"
      11                 :            : 
      12                 :            : 
      13                 :            : #include <stdarg.h>
      14                 :            : #include <stddef.h>
      15                 :            : #include <string.h>
      16                 :            : 
      17                 :            : #include "lua.h"
      18                 :            : 
      19                 :            : #include "lapi.h"
      20                 :            : #include "lcode.h"
      21                 :            : #include "ldebug.h"
      22                 :            : #include "ldo.h"
      23                 :            : #include "lfunc.h"
      24                 :            : #include "lobject.h"
      25                 :            : #include "lopcodes.h"
      26                 :            : #include "lstate.h"
      27                 :            : #include "lstring.h"
      28                 :            : #include "ltable.h"
      29                 :            : #include "ltm.h"
      30                 :            : #include "lvm.h"
      31                 :            : 
      32                 :            : 
      33                 :            : 
      34                 :            : #define noLuaClosure(f)         ((f) == NULL || (f)->c.tt == LUA_VCCL)
      35                 :            : 
      36                 :            : /* inverse of 'pcRel' */
      37                 :            : #define invpcRel(pc, p)         ((p)->code + (pc) + 1)
      38                 :            : 
      39                 :            : static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
      40                 :            :                                     const char **name);
      41                 :            : 
      42                 :            : 
      43                 :        532 : static int currentpc (CallInfo *ci) {
      44                 :            :   lua_assert(isLua(ci));
      45                 :        532 :   return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
      46                 :            : }
      47                 :            : 
      48                 :            : 
      49                 :            : /*
      50                 :            : ** Get a "base line" to find the line corresponding to an instruction.
      51                 :            : ** For that, search the array of absolute line info for the largest saved
      52                 :            : ** instruction smaller or equal to the wanted instruction. A special
      53                 :            : ** case is when there is no absolute info or the instruction is before
      54                 :            : ** the first absolute one.
      55                 :            : */
      56                 :        285 : static int getbaseline (const Proto *f, int pc, int *basepc) {
      57   [ -  +  #  # ]:        285 :   if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
      58                 :        285 :     *basepc = -1;  /* start from the beginning */
      59                 :        285 :     return f->linedefined;
      60                 :            :   }
      61                 :            :   else {
      62                 :            :     unsigned int i;
      63         [ #  # ]:          0 :     if (pc >= f->abslineinfo[f->sizeabslineinfo - 1].pc)
      64                 :          0 :       i = f->sizeabslineinfo - 1;  /* instruction is after last saved one */
      65                 :            :     else {  /* binary search */
      66                 :          0 :       unsigned int j = f->sizeabslineinfo - 1;  /* pc < anchorlines[j] */
      67                 :          0 :       i = 0;  /* abslineinfo[i] <= pc */
      68         [ #  # ]:          0 :       while (i < j - 1) {
      69                 :          0 :         unsigned int m = (j + i) / 2;
      70         [ #  # ]:          0 :         if (pc >= f->abslineinfo[m].pc)
      71                 :          0 :           i = m;
      72                 :            :         else
      73                 :          0 :           j = m;
      74                 :            :       }
      75                 :            :     }
      76                 :          0 :     *basepc = f->abslineinfo[i].pc;
      77                 :          0 :     return f->abslineinfo[i].line;
      78                 :            :   }
      79                 :        285 : }
      80                 :            : 
      81                 :            : 
      82                 :            : /*
      83                 :            : ** Get the line corresponding to instruction 'pc' in function 'f';
      84                 :            : ** first gets a base line and from there does the increments until
      85                 :            : ** the desired instruction.
      86                 :            : */
      87                 :        285 : int luaG_getfuncline (const Proto *f, int pc) {
      88         [ -  + ]:        285 :   if (f->lineinfo == NULL)  /* no debug information? */
      89                 :          0 :     return -1;
      90                 :            :   else {
      91                 :            :     int basepc;
      92                 :        285 :     int baseline = getbaseline(f, pc, &basepc);
      93         [ +  + ]:       1865 :     while (basepc++ < pc) {  /* walk until given instruction */
      94                 :            :       lua_assert(f->lineinfo[basepc] != ABSLINEINFO);
      95                 :       1580 :       baseline += f->lineinfo[basepc];  /* correct line */
      96                 :            :     }
      97                 :        285 :     return baseline;
      98                 :            :   }
      99                 :        285 : }
     100                 :            : 
     101                 :            : 
     102                 :        285 : static int getcurrentline (CallInfo *ci) {
     103                 :        285 :   return luaG_getfuncline(ci_func(ci)->p, currentpc(ci));
     104                 :            : }
     105                 :            : 
     106                 :            : 
     107                 :            : /*
     108                 :            : ** Set 'trap' for all active Lua frames.
     109                 :            : ** This function can be called during a signal, under "reasonable"
     110                 :            : ** assumptions. A new 'ci' is completely linked in the list before it
     111                 :            : ** becomes part of the "active" list, and we assume that pointers are
     112                 :            : ** atomic; see comment in next function.
     113                 :            : ** (A compiler doing interprocedural optimizations could, theoretically,
     114                 :            : ** reorder memory writes in such a way that the list could be
     115                 :            : ** temporarily broken while inserting a new element. We simply assume it
     116                 :            : ** has no good reasons to do that.)
     117                 :            : */
     118                 :          0 : static void settraps (CallInfo *ci) {
     119         [ #  # ]:          0 :   for (; ci != NULL; ci = ci->previous)
     120         [ #  # ]:          0 :     if (isLua(ci))
     121                 :          0 :       ci->u.l.trap = 1;
     122                 :          0 : }
     123                 :            : 
     124                 :            : 
     125                 :            : /*
     126                 :            : ** This function can be called during a signal, under "reasonable"
     127                 :            : ** assumptions.
     128                 :            : ** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount')
     129                 :            : ** are for debug only, and it is no problem if they get arbitrary
     130                 :            : ** values (causes at most one wrong hook call). 'hookmask' is an atomic
     131                 :            : ** value. We assume that pointers are atomic too (e.g., gcc ensures that
     132                 :            : ** for all platforms where it runs). Moreover, 'hook' is always checked
     133                 :            : ** before being called (see 'luaD_hook').
     134                 :            : */
     135                 :          0 : LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
     136   [ #  #  #  # ]:          0 :   if (func == NULL || mask == 0) {  /* turn off hooks? */
     137                 :          0 :     mask = 0;
     138                 :          0 :     func = NULL;
     139                 :          0 :   }
     140                 :          0 :   L->hook = func;
     141                 :          0 :   L->basehookcount = count;
     142                 :          0 :   resethookcount(L);
     143                 :          0 :   L->hookmask = cast_byte(mask);
     144         [ #  # ]:          0 :   if (mask)
     145                 :          0 :     settraps(L->ci);  /* to trace inside 'luaV_execute' */
     146                 :          0 : }
     147                 :            : 
     148                 :            : 
     149                 :          0 : LUA_API lua_Hook lua_gethook (lua_State *L) {
     150                 :          0 :   return L->hook;
     151                 :            : }
     152                 :            : 
     153                 :            : 
     154                 :          0 : LUA_API int lua_gethookmask (lua_State *L) {
     155                 :          0 :   return L->hookmask;
     156                 :            : }
     157                 :            : 
     158                 :            : 
     159                 :          0 : LUA_API int lua_gethookcount (lua_State *L) {
     160                 :          0 :   return L->basehookcount;
     161                 :            : }
     162                 :            : 
     163                 :            : 
     164                 :        526 : LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
     165                 :            :   int status;
     166                 :            :   CallInfo *ci;
     167         [ +  - ]:        526 :   if (level < 0) return 0;  /* invalid (negative) level */
     168                 :            :   lua_lock(L);
     169   [ +  +  +  + ]:        808 :   for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
     170                 :        282 :     level--;
     171   [ +  -  +  - ]:        526 :   if (level == 0 && ci != &L->base_ci) {  /* level found? */
     172                 :        526 :     status = 1;
     173                 :        526 :     ar->i_ci = ci;
     174                 :        526 :   }
     175                 :          0 :   else status = 0;  /* no such level */
     176                 :            :   lua_unlock(L);
     177                 :        526 :   return status;
     178                 :        526 : }
     179                 :            : 
     180                 :            : 
     181                 :        247 : static const char *upvalname (const Proto *p, int uv) {
     182                 :        247 :   TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
     183         [ -  + ]:        247 :   if (s == NULL) return "?";
     184                 :        247 :   else return getstr(s);
     185                 :        247 : }
     186                 :            : 
     187                 :            : 
     188                 :          0 : static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
     189         [ #  # ]:          0 :   if (clLvalue(s2v(ci->func))->p->is_vararg) {
     190                 :          0 :     int nextra = ci->u.l.nextraargs;
     191         [ #  # ]:          0 :     if (n >= -nextra) {  /* 'n' is negative */
     192                 :          0 :       *pos = ci->func - nextra - (n + 1);
     193                 :          0 :       return "(vararg)";  /* generic name for any vararg */
     194                 :            :     }
     195                 :          0 :   }
     196                 :          0 :   return NULL;  /* no such vararg */
     197                 :          0 : }
     198                 :            : 
     199                 :            : 
     200                 :          0 : const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
     201                 :          0 :   StkId base = ci->func + 1;
     202                 :          0 :   const char *name = NULL;
     203         [ #  # ]:          0 :   if (isLua(ci)) {
     204         [ #  # ]:          0 :     if (n < 0)  /* access to vararg values? */
     205                 :          0 :       return findvararg(ci, n, pos);
     206                 :            :     else
     207                 :          0 :       name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
     208                 :          0 :   }
     209         [ #  # ]:          0 :   if (name == NULL) {  /* no 'standard' name? */
     210         [ #  # ]:          0 :     StkId limit = (ci == L->ci) ? L->top : ci->next->func;
     211   [ #  #  #  # ]:          0 :     if (limit - base >= n && n > 0) {  /* is 'n' inside 'ci' stack? */
     212                 :            :       /* generic name for any valid slot */
     213                 :          0 :       name = isLua(ci) ? "(temporary)" : "(C temporary)";
     214                 :          0 :     }
     215                 :            :     else
     216                 :          0 :       return NULL;  /* no name */
     217                 :          0 :   }
     218         [ #  # ]:          0 :   if (pos)
     219                 :          0 :     *pos = base + (n - 1);
     220                 :          0 :   return name;
     221                 :          0 : }
     222                 :            : 
     223                 :            : 
     224                 :          0 : LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
     225                 :            :   const char *name;
     226                 :            :   lua_lock(L);
     227         [ #  # ]:          0 :   if (ar == NULL) {  /* information about non-active function? */
     228         [ #  # ]:          0 :     if (!isLfunction(s2v(L->top - 1)))  /* not a Lua function? */
     229                 :          0 :       name = NULL;
     230                 :            :     else  /* consider live variables at function start (parameters) */
     231                 :          0 :       name = luaF_getlocalname(clLvalue(s2v(L->top - 1))->p, n, 0);
     232                 :          0 :   }
     233                 :            :   else {  /* active function; get information through 'ar' */
     234                 :          0 :     StkId pos = NULL;  /* to avoid warnings */
     235                 :          0 :     name = luaG_findlocal(L, ar->i_ci, n, &pos);
     236         [ #  # ]:          0 :     if (name) {
     237                 :          0 :       setobjs2s(L, L->top, pos);
     238                 :          0 :       api_incr_top(L);
     239                 :          0 :     }
     240                 :            :   }
     241                 :            :   lua_unlock(L);
     242                 :          0 :   return name;
     243                 :            : }
     244                 :            : 
     245                 :            : 
     246                 :          0 : LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
     247                 :          0 :   StkId pos = NULL;  /* to avoid warnings */
     248                 :            :   const char *name;
     249                 :            :   lua_lock(L);
     250                 :          0 :   name = luaG_findlocal(L, ar->i_ci, n, &pos);
     251         [ #  # ]:          0 :   if (name) {
     252                 :          0 :     setobjs2s(L, pos, L->top - 1);
     253                 :          0 :     L->top--;  /* pop value */
     254                 :          0 :   }
     255                 :            :   lua_unlock(L);
     256                 :          0 :   return name;
     257                 :            : }
     258                 :            : 
     259                 :            : 
     260                 :        282 : static void funcinfo (lua_Debug *ar, Closure *cl) {
     261   [ +  -  -  + ]:        282 :   if (noLuaClosure(cl)) {
     262                 :          0 :     ar->source = "=[C]";
     263                 :          0 :     ar->srclen = LL("=[C]");
     264                 :          0 :     ar->linedefined = -1;
     265                 :          0 :     ar->lastlinedefined = -1;
     266                 :          0 :     ar->what = "C";
     267                 :          0 :   }
     268                 :            :   else {
     269                 :        282 :     const Proto *p = cl->l.p;
     270         [ +  - ]:        282 :     if (p->source) {
     271                 :        282 :       ar->source = getstr(p->source);
     272         [ +  + ]:        282 :       ar->srclen = tsslen(p->source);
     273                 :        282 :     }
     274                 :            :     else {
     275                 :          0 :       ar->source = "=?";
     276                 :          0 :       ar->srclen = LL("=?");
     277                 :            :     }
     278                 :        282 :     ar->linedefined = p->linedefined;
     279                 :        282 :     ar->lastlinedefined = p->lastlinedefined;
     280                 :        282 :     ar->what = (ar->linedefined == 0) ? "main" : "Lua";
     281                 :            :   }
     282                 :        282 :   luaO_chunkid(ar->short_src, ar->source, ar->srclen);
     283                 :        282 : }
     284                 :            : 
     285                 :            : 
     286                 :          0 : static int nextline (const Proto *p, int currentline, int pc) {
     287         [ #  # ]:          0 :   if (p->lineinfo[pc] != ABSLINEINFO)
     288                 :          0 :     return currentline + p->lineinfo[pc];
     289                 :            :   else
     290                 :          0 :     return luaG_getfuncline(p, pc);
     291                 :          0 : }
     292                 :            : 
     293                 :            : 
     294                 :          0 : static void collectvalidlines (lua_State *L, Closure *f) {
     295   [ #  #  #  # ]:          0 :   if (noLuaClosure(f)) {
     296                 :          0 :     setnilvalue(s2v(L->top));
     297                 :          0 :     api_incr_top(L);
     298                 :          0 :   }
     299                 :            :   else {
     300                 :            :     int i;
     301                 :            :     TValue v;
     302                 :          0 :     const Proto *p = f->l.p;
     303                 :          0 :     int currentline = p->linedefined;
     304                 :          0 :     Table *t = luaH_new(L);  /* new table to store active lines */
     305                 :          0 :     sethvalue2s(L, L->top, t);  /* push it on stack */
     306                 :          0 :     api_incr_top(L);
     307                 :          0 :     setbtvalue(&v);  /* boolean 'true' to be the value of all indices */
     308         [ #  # ]:          0 :     for (i = 0; i < p->sizelineinfo; i++) {  /* for all lines with code */
     309                 :          0 :       currentline = nextline(p, currentline, i);
     310                 :          0 :       luaH_setint(L, t, currentline, &v);  /* table[line] = true */
     311                 :          0 :     }
     312                 :            :   }
     313                 :          0 : }
     314                 :            : 
     315                 :            : 
     316                 :        244 : static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
     317         [ +  - ]:        244 :   if (ci == NULL)  /* no 'ci'? */
     318                 :          0 :     return NULL;  /* no info */
     319         [ -  + ]:        244 :   else if (ci->callstatus & CIST_FIN) {  /* is this a finalizer? */
     320                 :          0 :     *name = "__gc";
     321                 :          0 :     return "metamethod";  /* report it as such */
     322                 :            :   }
     323                 :            :   /* calling function is a known Lua function? */
     324   [ +  -  -  + ]:        244 :   else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
     325                 :        244 :     return funcnamefromcode(L, ci->previous, name);
     326                 :          0 :   else return NULL;  /* no way to find a name */
     327                 :        244 : }
     328                 :            : 
     329                 :            : 
     330                 :        526 : static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
     331                 :            :                        Closure *f, CallInfo *ci) {
     332                 :        526 :   int status = 1;
     333         [ +  + ]:       1334 :   for (; *what; what++) {
     334   [ -  -  +  +  :        808 :     switch (*what) {
             -  -  +  - ]
     335                 :            :       case 'S': {
     336                 :        282 :         funcinfo(ar, f);
     337                 :        282 :         break;
     338                 :            :       }
     339                 :            :       case 'l': {
     340   [ +  -  -  + ]:        282 :         ar->currentline = (ci && isLua(ci)) ? getcurrentline(ci) : -1;
     341                 :        282 :         break;
     342                 :            :       }
     343                 :            :       case 'u': {
     344         [ #  # ]:          0 :         ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
     345   [ #  #  #  # ]:          0 :         if (noLuaClosure(f)) {
     346                 :          0 :           ar->isvararg = 1;
     347                 :          0 :           ar->nparams = 0;
     348                 :          0 :         }
     349                 :            :         else {
     350                 :          0 :           ar->isvararg = f->l.p->is_vararg;
     351                 :          0 :           ar->nparams = f->l.p->numparams;
     352                 :            :         }
     353                 :          0 :         break;
     354                 :            :       }
     355                 :            :       case 't': {
     356         [ #  # ]:          0 :         ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
     357                 :          0 :         break;
     358                 :            :       }
     359                 :            :       case 'n': {
     360                 :        244 :         ar->namewhat = getfuncname(L, ci, &ar->name);
     361         [ +  - ]:        244 :         if (ar->namewhat == NULL) {
     362                 :          0 :           ar->namewhat = "";  /* not found */
     363                 :          0 :           ar->name = NULL;
     364                 :          0 :         }
     365                 :        244 :         break;
     366                 :            :       }
     367                 :            :       case 'r': {
     368   [ #  #  #  # ]:          0 :         if (ci == NULL || !(ci->callstatus & CIST_TRAN))
     369                 :          0 :           ar->ftransfer = ar->ntransfer = 0;
     370                 :            :         else {
     371                 :          0 :           ar->ftransfer = ci->u2.transferinfo.ftransfer;
     372                 :          0 :           ar->ntransfer = ci->u2.transferinfo.ntransfer;
     373                 :            :         }
     374                 :          0 :         break;
     375                 :            :       }
     376                 :            :       case 'L':
     377                 :            :       case 'f':  /* handled by lua_getinfo */
     378                 :          0 :         break;
     379                 :          0 :       default: status = 0;  /* invalid option */
     380                 :          0 :     }
     381                 :        808 :   }
     382                 :        526 :   return status;
     383                 :            : }
     384                 :            : 
     385                 :            : 
     386                 :        526 : LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
     387                 :            :   int status;
     388                 :            :   Closure *cl;
     389                 :            :   CallInfo *ci;
     390                 :            :   TValue *func;
     391                 :            :   lua_lock(L);
     392         [ -  + ]:        526 :   if (*what == '>') {
     393                 :          0 :     ci = NULL;
     394                 :          0 :     func = s2v(L->top - 1);
     395                 :          0 :     api_check(L, ttisfunction(func), "function expected");
     396                 :          0 :     what++;  /* skip the '>' */
     397                 :          0 :     L->top--;  /* pop function */
     398                 :          0 :   }
     399                 :            :   else {
     400                 :        526 :     ci = ar->i_ci;
     401                 :        526 :     func = s2v(ci->func);
     402                 :            :     lua_assert(ttisfunction(func));
     403                 :            :   }
     404         [ +  + ]:        526 :   cl = ttisclosure(func) ? clvalue(func) : NULL;
     405                 :        526 :   status = auxgetinfo(L, what, ar, cl, ci);
     406         [ +  - ]:        526 :   if (strchr(what, 'f')) {
     407                 :          0 :     setobj2s(L, L->top, func);
     408                 :          0 :     api_incr_top(L);
     409                 :          0 :   }
     410         [ +  - ]:        526 :   if (strchr(what, 'L'))
     411                 :          0 :     collectvalidlines(L, cl);
     412                 :            :   lua_unlock(L);
     413                 :        526 :   return status;
     414                 :            : }
     415                 :            : 
     416                 :            : 
     417                 :            : /*
     418                 :            : ** {======================================================
     419                 :            : ** Symbolic Execution
     420                 :            : ** =======================================================
     421                 :            : */
     422                 :            : 
     423                 :            : static const char *getobjname (const Proto *p, int lastpc, int reg,
     424                 :            :                                const char **name);
     425                 :            : 
     426                 :            : 
     427                 :            : /*
     428                 :            : ** Find a "name" for the constant 'c'.
     429                 :            : */
     430                 :        491 : static void kname (const Proto *p, int c, const char **name) {
     431                 :        491 :   TValue *kvalue = &p->k[c];
     432         [ +  - ]:        491 :   *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
     433                 :        491 : }
     434                 :            : 
     435                 :            : 
     436                 :            : /*
     437                 :            : ** Find a "name" for the register 'c'.
     438                 :            : */
     439                 :          0 : static void rname (const Proto *p, int pc, int c, const char **name) {
     440                 :          0 :   const char *what = getobjname(p, pc, c, name); /* search for 'c' */
     441   [ #  #  #  # ]:          0 :   if (!(what && *what == 'c'))  /* did not find a constant name? */
     442                 :          0 :     *name = "?";
     443                 :          0 : }
     444                 :            : 
     445                 :            : 
     446                 :            : /*
     447                 :            : ** Find a "name" for a 'C' value in an RK instruction.
     448                 :            : */
     449                 :          0 : static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
     450                 :          0 :   int c = GETARG_C(i);  /* key index */
     451         [ #  # ]:          0 :   if (GETARG_k(i))  /* is 'c' a constant? */
     452                 :          0 :     kname(p, c, name);
     453                 :            :   else  /* 'c' is a register */
     454                 :          0 :     rname(p, pc, c, name);
     455                 :          0 : }
     456                 :            : 
     457                 :            : 
     458                 :       1209 : static int filterpc (int pc, int jmptarget) {
     459         [ -  + ]:       1209 :   if (pc < jmptarget)  /* is code conditional (inside a jump)? */
     460                 :          0 :     return -1;  /* cannot know who sets that register */
     461                 :       1209 :   else return pc;  /* current position sets that register */
     462                 :       1209 : }
     463                 :            : 
     464                 :            : 
     465                 :            : /*
     466                 :            : ** Try to find last instruction before 'lastpc' that modified register 'reg'.
     467                 :            : */
     468                 :        491 : static int findsetreg (const Proto *p, int lastpc, int reg) {
     469                 :            :   int pc;
     470                 :        491 :   int setreg = -1;  /* keep last instruction that changed 'reg' */
     471                 :        491 :   int jmptarget = 0;  /* any code before this address is conditional */
     472         [ +  - ]:        491 :   if (testMMMode(GET_OPCODE(p->code[lastpc])))
     473                 :          0 :     lastpc--;  /* previous instruction was not actually executed */
     474         [ +  + ]:       2102 :   for (pc = 0; pc < lastpc; pc++) {
     475                 :       1611 :     Instruction i = p->code[pc];
     476                 :       1611 :     OpCode op = GET_OPCODE(i);
     477                 :       1611 :     int a = GETARG_A(i);
     478                 :            :     int change;  /* true if current instruction changed 'reg' */
     479   [ +  +  -  -  :       1611 :     switch (op) {
                      + ]
     480                 :            :       case OP_LOADNIL: {  /* set registers from 'a' to 'a+b' */
     481                 :          0 :         int b = GETARG_B(i);
     482         [ #  # ]:          0 :         change = (a <= reg && reg <= a + b);
     483                 :          0 :         break;
     484                 :            :       }
     485                 :            :       case OP_TFORCALL: {  /* affect all regs above its base */
     486                 :          0 :         change = (reg >= a + 2);
     487                 :          0 :         break;
     488                 :            :       }
     489                 :            :       case OP_CALL:
     490                 :            :       case OP_TAILCALL: {  /* affect all registers above base */
     491                 :          6 :         change = (reg >= a);
     492                 :          6 :         break;
     493                 :            :       }
     494                 :            :       case OP_JMP: {  /* doesn't change registers, but changes 'jmptarget' */
     495                 :          1 :         int b = GETARG_sJ(i);
     496                 :          1 :         int dest = pc + 1 + b;
     497                 :            :         /* jump does not skip 'lastpc' and is larger than current one? */
     498   [ -  +  #  # ]:          1 :         if (dest <= lastpc && dest > jmptarget)
     499                 :          0 :           jmptarget = dest;  /* update 'jmptarget' */
     500                 :          1 :         change = 0;
     501                 :          1 :         break;
     502                 :            :       }
     503                 :            :       default:  /* any instruction that sets A */
     504         [ +  + ]:       1604 :         change = (testAMode(op) && reg == a);
     505                 :       1604 :         break;
     506                 :            :     }
     507         [ +  + ]:       1611 :     if (change)
     508                 :       1209 :       setreg = filterpc(pc, jmptarget);
     509                 :       1611 :   }
     510                 :        491 :   return setreg;
     511                 :            : }
     512                 :            : 
     513                 :            : 
     514                 :            : /*
     515                 :            : ** Check whether table being indexed by instruction 'i' is the
     516                 :            : ** environment '_ENV'
     517                 :            : */
     518                 :        491 : static const char *gxf (const Proto *p, int pc, Instruction i, int isup) {
     519                 :        491 :   int t = GETARG_B(i);  /* table index */
     520                 :            :   const char *name;  /* name of indexed variable */
     521         [ +  + ]:        491 :   if (isup)  /* is an upvalue? */
     522                 :        247 :     name = upvalname(p, t);
     523                 :            :   else
     524                 :        244 :     getobjname(p, pc, t, &name);
     525         [ -  + ]:        491 :   return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
     526                 :            : }
     527                 :            : 
     528                 :            : 
     529                 :        491 : static const char *getobjname (const Proto *p, int lastpc, int reg,
     530                 :            :                                const char **name) {
     531                 :            :   int pc;
     532                 :        491 :   *name = luaF_getlocalname(p, reg + 1, lastpc);
     533         [ -  + ]:        491 :   if (*name)  /* is a local? */
     534                 :          0 :     return "local";
     535                 :            :   /* else try symbolic execution */
     536                 :        491 :   pc = findsetreg(p, lastpc, reg);
     537         [ -  + ]:        491 :   if (pc != -1) {  /* could find instruction? */
     538                 :        491 :     Instruction i = p->code[pc];
     539                 :        491 :     OpCode op = GET_OPCODE(i);
     540   [ +  -  -  -  :        491 :     switch (op) {
             -  -  -  +  
                      - ]
     541                 :            :       case OP_MOVE: {
     542                 :          0 :         int b = GETARG_B(i);  /* move from 'b' to 'a' */
     543         [ #  # ]:          0 :         if (b < GETARG_A(i))
     544                 :          0 :           return getobjname(p, pc, b, name);  /* get name for 'b' */
     545                 :          0 :         break;
     546                 :            :       }
     547                 :            :       case OP_GETTABUP: {
     548                 :        247 :         int k = GETARG_C(i);  /* key index */
     549                 :        247 :         kname(p, k, name);
     550                 :        247 :         return gxf(p, pc, i, 1);
     551                 :            :       }
     552                 :            :       case OP_GETTABLE: {
     553                 :          0 :         int k = GETARG_C(i);  /* key index */
     554                 :          0 :         rname(p, pc, k, name);
     555                 :          0 :         return gxf(p, pc, i, 0);
     556                 :            :       }
     557                 :            :       case OP_GETI: {
     558                 :          0 :         *name = "integer index";
     559                 :          0 :         return "field";
     560                 :            :       }
     561                 :            :       case OP_GETFIELD: {
     562                 :        244 :         int k = GETARG_C(i);  /* key index */
     563                 :        244 :         kname(p, k, name);
     564                 :        244 :         return gxf(p, pc, i, 0);
     565                 :            :       }
     566                 :            :       case OP_GETUPVAL: {
     567                 :          0 :         *name = upvalname(p, GETARG_B(i));
     568                 :          0 :         return "upvalue";
     569                 :            :       }
     570                 :            :       case OP_LOADK:
     571                 :            :       case OP_LOADKX: {
     572         [ #  # ]:          0 :         int b = (op == OP_LOADK) ? GETARG_Bx(i)
     573                 :          0 :                                  : GETARG_Ax(p->code[pc + 1]);
     574         [ #  # ]:          0 :         if (ttisstring(&p->k[b])) {
     575                 :          0 :           *name = svalue(&p->k[b]);
     576                 :          0 :           return "constant";
     577                 :            :         }
     578                 :          0 :         break;
     579                 :            :       }
     580                 :            :       case OP_SELF: {
     581                 :          0 :         rkname(p, pc, i, name);
     582                 :          0 :         return "method";
     583                 :            :       }
     584                 :          0 :       default: break;  /* go through to return NULL */
     585                 :            :     }
     586                 :          0 :   }
     587                 :          0 :   return NULL;  /* could not find reasonable name */
     588                 :        491 : }
     589                 :            : 
     590                 :            : 
     591                 :            : /*
     592                 :            : ** Try to find a name for a function based on the code that called it.
     593                 :            : ** (Only works when function was called by a Lua function.)
     594                 :            : ** Returns what the name is (e.g., "for iterator", "method",
     595                 :            : ** "metamethod") and sets '*name' to point to the name.
     596                 :            : */
     597                 :        244 : static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
     598                 :            :                                      const char **name) {
     599                 :        244 :   TMS tm = (TMS)0;  /* (initial value avoids warnings) */
     600                 :        244 :   const Proto *p = ci_func(ci)->p;  /* calling function */
     601                 :        244 :   int pc = currentpc(ci);  /* calling instruction index */
     602                 :        244 :   Instruction i = p->code[pc];  /* calling instruction */
     603         [ -  + ]:        244 :   if (ci->callstatus & CIST_HOOKED) {  /* was it called inside a hook? */
     604                 :          0 :     *name = "?";
     605                 :          0 :     return "hook";
     606                 :            :   }
     607   [ -  -  -  -  :        244 :   switch (GET_OPCODE(i)) {
          -  -  -  -  -  
             -  -  +  - ]
     608                 :            :     case OP_CALL:
     609                 :            :     case OP_TAILCALL:
     610                 :        244 :       return getobjname(p, pc, GETARG_A(i), name);  /* get function name */
     611                 :            :     case OP_TFORCALL: {  /* for iterator */
     612                 :          0 :       *name = "for iterator";
     613                 :          0 :        return "for iterator";
     614                 :            :     }
     615                 :            :     /* other instructions can do calls through metamethods */
     616                 :            :     case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
     617                 :            :     case OP_GETI: case OP_GETFIELD:
     618                 :          0 :       tm = TM_INDEX;
     619                 :          0 :       break;
     620                 :            :     case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
     621                 :          0 :       tm = TM_NEWINDEX;
     622                 :          0 :       break;
     623                 :            :     case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: {
     624                 :          0 :       tm = cast(TMS, GETARG_C(i));
     625                 :          0 :       break;
     626                 :            :     }
     627                 :          0 :     case OP_UNM: tm = TM_UNM; break;
     628                 :          0 :     case OP_BNOT: tm = TM_BNOT; break;
     629                 :          0 :     case OP_LEN: tm = TM_LEN; break;
     630                 :          0 :     case OP_CONCAT: tm = TM_CONCAT; break;
     631                 :          0 :     case OP_EQ: tm = TM_EQ; break;
     632                 :            :     case OP_LT: case OP_LE: case OP_LTI: case OP_LEI:
     633                 :          0 :       *name = "order";  /* '<=' can call '__lt', etc. */
     634                 :          0 :       return "metamethod";
     635                 :            :     case OP_CLOSE: case OP_RETURN:
     636                 :          0 :       *name = "close";
     637                 :          0 :       return "metamethod";
     638                 :            :     default:
     639                 :          0 :       return NULL;  /* cannot find a reasonable name */
     640                 :            :   }
     641                 :          0 :   *name = getstr(G(L)->tmname[tm]) + 2;
     642                 :          0 :   return "metamethod";
     643                 :        244 : }
     644                 :            : 
     645                 :            : /* }====================================================== */
     646                 :            : 
     647                 :            : 
     648                 :            : 
     649                 :            : /*
     650                 :            : ** The subtraction of two potentially unrelated pointers is
     651                 :            : ** not ISO C, but it should not crash a program; the subsequent
     652                 :            : ** checks are ISO C and ensure a correct result.
     653                 :            : */
     654                 :          3 : static int isinstack (CallInfo *ci, const TValue *o) {
     655                 :          3 :   StkId base = ci->func + 1;
     656                 :          3 :   ptrdiff_t i = cast(StkId, o) - base;
     657   [ +  -  -  + ]:          3 :   return (0 <= i && i < (ci->top - base) && s2v(base + i) == o);
     658                 :            : }
     659                 :            : 
     660                 :            : 
     661                 :            : /*
     662                 :            : ** Checks whether value 'o' came from an upvalue. (That can only happen
     663                 :            : ** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
     664                 :            : ** upvalues.)
     665                 :            : */
     666                 :          3 : static const char *getupvalname (CallInfo *ci, const TValue *o,
     667                 :            :                                  const char **name) {
     668                 :          3 :   LClosure *c = ci_func(ci);
     669                 :            :   int i;
     670         [ +  + ]:          6 :   for (i = 0; i < c->nupvalues; i++) {
     671         [ -  + ]:          3 :     if (c->upvals[i]->v == o) {
     672                 :          0 :       *name = upvalname(c->p, i);
     673                 :          0 :       return "upvalue";
     674                 :            :     }
     675                 :          3 :   }
     676                 :          3 :   return NULL;
     677                 :          3 : }
     678                 :            : 
     679                 :            : 
     680                 :          3 : static const char *varinfo (lua_State *L, const TValue *o) {
     681                 :          3 :   const char *name = NULL;  /* to avoid warnings */
     682                 :          3 :   CallInfo *ci = L->ci;
     683                 :          3 :   const char *kind = NULL;
     684         [ -  + ]:          3 :   if (isLua(ci)) {
     685                 :          3 :     kind = getupvalname(ci, o, &name);  /* check whether 'o' is an upvalue */
     686   [ +  -  +  - ]:          3 :     if (!kind && isinstack(ci, o))  /* no? try a register */
     687                 :          6 :       kind = getobjname(ci_func(ci)->p, currentpc(ci),
     688                 :          3 :                         cast_int(cast(StkId, o) - (ci->func + 1)), &name);
     689                 :          3 :   }
     690         [ +  - ]:          3 :   return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : "";
     691                 :            : }
     692                 :            : 
     693                 :            : 
     694                 :          3 : l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
     695                 :          3 :   const char *t = luaT_objtypename(L, o);
     696                 :          3 :   luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
     697                 :            : }
     698                 :            : 
     699                 :            : 
     700                 :          0 : l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
     701                 :          0 :   luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
     702                 :          0 :                    what, luaT_objtypename(L, o));
     703                 :            : }
     704                 :            : 
     705                 :            : 
     706                 :          0 : l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
     707   [ #  #  #  # ]:          0 :   if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
     708                 :          0 :   luaG_typeerror(L, p1, "concatenate");
     709                 :            : }
     710                 :            : 
     711                 :            : 
     712                 :          0 : l_noret luaG_opinterror (lua_State *L, const TValue *p1,
     713                 :            :                          const TValue *p2, const char *msg) {
     714         [ #  # ]:          0 :   if (!ttisnumber(p1))  /* first operand is wrong? */
     715                 :          0 :     p2 = p1;  /* now second is wrong */
     716                 :          0 :   luaG_typeerror(L, p2, msg);
     717                 :            : }
     718                 :            : 
     719                 :            : 
     720                 :            : /*
     721                 :            : ** Error when both values are convertible to numbers, but not to integers
     722                 :            : */
     723                 :          0 : l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
     724                 :            :   lua_Integer temp;
     725   [ #  #  #  # ]:          0 :   if (!tointegerns(p1, &temp))
     726                 :          0 :     p2 = p1;
     727                 :          0 :   luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
     728                 :            : }
     729                 :            : 
     730                 :            : 
     731                 :          0 : l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
     732                 :          0 :   const char *t1 = luaT_objtypename(L, p1);
     733                 :          0 :   const char *t2 = luaT_objtypename(L, p2);
     734         [ #  # ]:          0 :   if (strcmp(t1, t2) == 0)
     735                 :          0 :     luaG_runerror(L, "attempt to compare two %s values", t1);
     736                 :            :   else
     737                 :          0 :     luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
     738                 :            : }
     739                 :            : 
     740                 :            : 
     741                 :            : /* add src:line information to 'msg' */
     742                 :          7 : const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
     743                 :            :                                         int line) {
     744                 :            :   char buff[LUA_IDSIZE];
     745         [ +  - ]:          7 :   if (src)
     746         [ +  + ]:          7 :     luaO_chunkid(buff, getstr(src), tsslen(src));
     747                 :            :   else {  /* no source available; use "?" instead */
     748                 :          0 :     buff[0] = '?'; buff[1] = '\0';
     749                 :            :   }
     750                 :          7 :   return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
     751                 :            : }
     752                 :            : 
     753                 :            : 
     754                 :        285 : l_noret luaG_errormsg (lua_State *L) {
     755         [ +  - ]:        285 :   if (L->errfunc != 0) {  /* is there an error handling function? */
     756                 :          0 :     StkId errfunc = restorestack(L, L->errfunc);
     757                 :            :     lua_assert(ttisfunction(s2v(errfunc)));
     758                 :          0 :     setobjs2s(L, L->top, L->top - 1);  /* move argument */
     759                 :          0 :     setobjs2s(L, L->top - 1, errfunc);  /* push function */
     760                 :          0 :     L->top++;  /* assume EXTRA_STACK */
     761                 :          0 :     luaD_callnoyield(L, L->top - 2, 1);  /* call it */
     762                 :          0 :   }
     763                 :        285 :   luaD_throw(L, LUA_ERRRUN);
     764                 :            : }
     765                 :            : 
     766                 :            : 
     767                 :          3 : l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
     768                 :          3 :   CallInfo *ci = L->ci;
     769                 :            :   const char *msg;
     770                 :            :   va_list argp;
     771         [ +  + ]:          3 :   luaC_checkGC(L);  /* error message uses memory */
     772                 :          3 :   va_start(argp, fmt);
     773                 :          3 :   msg = luaO_pushvfstring(L, fmt, argp);  /* format message */
     774                 :          3 :   va_end(argp);
     775         [ -  + ]:          3 :   if (isLua(ci))  /* if Lua function, add source:line information */
     776                 :          3 :     luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
     777                 :          3 :   luaG_errormsg(L);
     778                 :            : }
     779                 :            : 
     780                 :            : 
     781                 :            : /*
     782                 :            : ** Check whether new instruction 'newpc' is in a different line from
     783                 :            : ** previous instruction 'oldpc'.
     784                 :            : */
     785                 :          0 : static int changedline (const Proto *p, int oldpc, int newpc) {
     786         [ #  # ]:          0 :   if (p->lineinfo == NULL)  /* no debug information? */
     787                 :          0 :     return 0;
     788         [ #  # ]:          0 :   while (oldpc++ < newpc) {
     789         [ #  # ]:          0 :     if (p->lineinfo[oldpc] != 0)
     790                 :          0 :       return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc));
     791                 :            :   }
     792                 :          0 :   return 0;  /* no line changes between positions */
     793                 :          0 : }
     794                 :            : 
     795                 :            : 
     796                 :            : /*
     797                 :            : ** Traces the execution of a Lua function. Called before the execution
     798                 :            : ** of each opcode, when debug is on. 'L->oldpc' stores the last
     799                 :            : ** instruction traced, to detect line changes. When entering a new
     800                 :            : ** function, 'npci' will be zero and will test as a new line without
     801                 :            : ** the need for 'oldpc'; so, 'oldpc' does not need to be initialized
     802                 :            : ** before. Some exceptional conditions may return to a function without
     803                 :            : ** updating 'oldpc'. In that case, 'oldpc' may be invalid; if so, it is
     804                 :            : ** reset to zero.  (A wrong but valid 'oldpc' at most causes an extra
     805                 :            : ** call to a line hook.)
     806                 :            : */
     807                 :          0 : int luaG_traceexec (lua_State *L, const Instruction *pc) {
     808                 :          0 :   CallInfo *ci = L->ci;
     809                 :          0 :   lu_byte mask = L->hookmask;
     810                 :          0 :   const Proto *p = ci_func(ci)->p;
     811                 :            :   int counthook;
     812                 :            :   /* 'L->oldpc' may be invalid; reset it in this case */
     813         [ #  # ]:          0 :   int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
     814         [ #  # ]:          0 :   if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) {  /* no hooks? */
     815                 :          0 :     ci->u.l.trap = 0;  /* don't need to stop again */
     816                 :          0 :     return 0;  /* turn off 'trap' */
     817                 :            :   }
     818                 :          0 :   pc++;  /* reference is always next instruction */
     819                 :          0 :   ci->u.l.savedpc = pc;  /* save 'pc' */
     820         [ #  # ]:          0 :   counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
     821         [ #  # ]:          0 :   if (counthook)
     822                 :          0 :     resethookcount(L);  /* reset count */
     823         [ #  # ]:          0 :   else if (!(mask & LUA_MASKLINE))
     824                 :          0 :     return 1;  /* no line hook and count != 0; nothing to be done now */
     825         [ #  # ]:          0 :   if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
     826                 :          0 :     ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
     827                 :          0 :     return 1;  /* do not call hook again (VM yielded, so it did not move) */
     828                 :            :   }
     829   [ #  #  #  # ]:          0 :   if (!isIT(*(ci->u.l.savedpc - 1)))
     830                 :          0 :     L->top = ci->top;  /* prepare top */
     831         [ #  # ]:          0 :   if (counthook)
     832                 :          0 :     luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0);  /* call count hook */
     833         [ #  # ]:          0 :   if (mask & LUA_MASKLINE) {
     834                 :          0 :     int npci = pcRel(pc, p);
     835   [ #  #  #  # ]:          0 :     if (npci == 0 ||  /* call linehook when enter a new function, */
     836         [ #  # ]:          0 :         pc <= invpcRel(oldpc, p) ||  /* when jump back (loop), or when */
     837                 :          0 :         changedline(p, oldpc, npci)) {  /* enter new line */
     838                 :          0 :       int newline = luaG_getfuncline(p, npci);
     839                 :          0 :       luaD_hook(L, LUA_HOOKLINE, newline, 0, 0);  /* call line hook */
     840                 :          0 :     }
     841                 :          0 :     L->oldpc = npci;  /* 'pc' of last call to line hook */
     842                 :          0 :   }
     843         [ #  # ]:          0 :   if (L->status == LUA_YIELD) {  /* did hook yield? */
     844         [ #  # ]:          0 :     if (counthook)
     845                 :          0 :       L->hookcount = 1;  /* undo decrement to zero */
     846                 :          0 :     ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
     847                 :          0 :     ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
     848                 :          0 :     luaD_throw(L, LUA_YIELD);
     849                 :            :   }
     850                 :          0 :   return 1;  /* keep 'trap' on */
     851                 :          0 : }
     852                 :            : 

Generated by: LCOV version 1.15