xref: /illumos-gate/usr/src/uts/common/fs/zfs/lua/ldebug.c (revision 9cfcc091666d5546e419c22f4963474d11673f5e)
1*dfc11533SChris Williamson /*
2*dfc11533SChris Williamson ** $Id: ldebug.c,v 2.90.1.4 2015/02/19 17:05:13 roberto Exp $
3*dfc11533SChris Williamson ** Debug Interface
4*dfc11533SChris Williamson ** See Copyright Notice in lua.h
5*dfc11533SChris Williamson */
6*dfc11533SChris Williamson 
7*dfc11533SChris Williamson 
8*dfc11533SChris Williamson #include <sys/zfs_context.h>
9*dfc11533SChris Williamson 
10*dfc11533SChris Williamson #define ldebug_c
11*dfc11533SChris Williamson #define LUA_CORE
12*dfc11533SChris Williamson 
13*dfc11533SChris Williamson #include "lua.h"
14*dfc11533SChris Williamson 
15*dfc11533SChris Williamson #include "lapi.h"
16*dfc11533SChris Williamson #include "lcode.h"
17*dfc11533SChris Williamson #include "ldebug.h"
18*dfc11533SChris Williamson #include "ldo.h"
19*dfc11533SChris Williamson #include "lfunc.h"
20*dfc11533SChris Williamson #include "lobject.h"
21*dfc11533SChris Williamson #include "lopcodes.h"
22*dfc11533SChris Williamson #include "lstate.h"
23*dfc11533SChris Williamson #include "lstring.h"
24*dfc11533SChris Williamson #include "ltable.h"
25*dfc11533SChris Williamson #include "ltm.h"
26*dfc11533SChris Williamson #include "lvm.h"
27*dfc11533SChris Williamson 
28*dfc11533SChris Williamson 
29*dfc11533SChris Williamson 
30*dfc11533SChris Williamson #define noLuaClosure(f)		((f) == NULL || (f)->c.tt == LUA_TCCL)
31*dfc11533SChris Williamson 
32*dfc11533SChris Williamson 
33*dfc11533SChris Williamson static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
34*dfc11533SChris Williamson 
35*dfc11533SChris Williamson 
currentpc(CallInfo * ci)36*dfc11533SChris Williamson static int currentpc (CallInfo *ci) {
37*dfc11533SChris Williamson   lua_assert(isLua(ci));
38*dfc11533SChris Williamson   return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
39*dfc11533SChris Williamson }
40*dfc11533SChris Williamson 
41*dfc11533SChris Williamson 
currentline(CallInfo * ci)42*dfc11533SChris Williamson static int currentline (CallInfo *ci) {
43*dfc11533SChris Williamson   return getfuncline(ci_func(ci)->p, currentpc(ci));
44*dfc11533SChris Williamson }
45*dfc11533SChris Williamson 
46*dfc11533SChris Williamson 
swapextra(lua_State * L)47*dfc11533SChris Williamson static void swapextra (lua_State *L) {
48*dfc11533SChris Williamson   if (L->status == LUA_YIELD) {
49*dfc11533SChris Williamson     CallInfo *ci = L->ci;  /* get function that yielded */
50*dfc11533SChris Williamson     StkId temp = ci->func;  /* exchange its 'func' and 'extra' values */
51*dfc11533SChris Williamson     ci->func = restorestack(L, ci->extra);
52*dfc11533SChris Williamson     ci->extra = savestack(L, temp);
53*dfc11533SChris Williamson   }
54*dfc11533SChris Williamson }
55*dfc11533SChris Williamson 
56*dfc11533SChris Williamson 
57*dfc11533SChris Williamson /*
58*dfc11533SChris Williamson ** this function can be called asynchronous (e.g. during a signal)
59*dfc11533SChris Williamson */
lua_sethook(lua_State * L,lua_Hook func,int mask,int count)60*dfc11533SChris Williamson LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
61*dfc11533SChris Williamson   if (func == NULL || mask == 0) {  /* turn off hooks? */
62*dfc11533SChris Williamson     mask = 0;
63*dfc11533SChris Williamson     func = NULL;
64*dfc11533SChris Williamson   }
65*dfc11533SChris Williamson   if (isLua(L->ci))
66*dfc11533SChris Williamson     L->oldpc = L->ci->u.l.savedpc;
67*dfc11533SChris Williamson   L->hook = func;
68*dfc11533SChris Williamson   L->basehookcount = count;
69*dfc11533SChris Williamson   resethookcount(L);
70*dfc11533SChris Williamson   L->hookmask = cast_byte(mask);
71*dfc11533SChris Williamson   return 1;
72*dfc11533SChris Williamson }
73*dfc11533SChris Williamson 
74*dfc11533SChris Williamson 
lua_gethook(lua_State * L)75*dfc11533SChris Williamson LUA_API lua_Hook lua_gethook (lua_State *L) {
76*dfc11533SChris Williamson   return L->hook;
77*dfc11533SChris Williamson }
78*dfc11533SChris Williamson 
79*dfc11533SChris Williamson 
lua_gethookmask(lua_State * L)80*dfc11533SChris Williamson LUA_API int lua_gethookmask (lua_State *L) {
81*dfc11533SChris Williamson   return L->hookmask;
82*dfc11533SChris Williamson }
83*dfc11533SChris Williamson 
84*dfc11533SChris Williamson 
lua_gethookcount(lua_State * L)85*dfc11533SChris Williamson LUA_API int lua_gethookcount (lua_State *L) {
86*dfc11533SChris Williamson   return L->basehookcount;
87*dfc11533SChris Williamson }
88*dfc11533SChris Williamson 
89*dfc11533SChris Williamson 
lua_getstack(lua_State * L,int level,lua_Debug * ar)90*dfc11533SChris Williamson LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
91*dfc11533SChris Williamson   int status;
92*dfc11533SChris Williamson   CallInfo *ci;
93*dfc11533SChris Williamson   if (level < 0) return 0;  /* invalid (negative) level */
94*dfc11533SChris Williamson   lua_lock(L);
95*dfc11533SChris Williamson   for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
96*dfc11533SChris Williamson     level--;
97*dfc11533SChris Williamson   if (level == 0 && ci != &L->base_ci) {  /* level found? */
98*dfc11533SChris Williamson     status = 1;
99*dfc11533SChris Williamson     ar->i_ci = ci;
100*dfc11533SChris Williamson   }
101*dfc11533SChris Williamson   else status = 0;  /* no such level */
102*dfc11533SChris Williamson   lua_unlock(L);
103*dfc11533SChris Williamson   return status;
104*dfc11533SChris Williamson }
105*dfc11533SChris Williamson 
106*dfc11533SChris Williamson 
upvalname(Proto * p,int uv)107*dfc11533SChris Williamson static const char *upvalname (Proto *p, int uv) {
108*dfc11533SChris Williamson   TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
109*dfc11533SChris Williamson   if (s == NULL) return "?";
110*dfc11533SChris Williamson   else return getstr(s);
111*dfc11533SChris Williamson }
112*dfc11533SChris Williamson 
113*dfc11533SChris Williamson 
findvararg(CallInfo * ci,int n,StkId * pos)114*dfc11533SChris Williamson static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
115*dfc11533SChris Williamson   int nparams = clLvalue(ci->func)->p->numparams;
116*dfc11533SChris Williamson   if (n >= ci->u.l.base - ci->func - nparams)
117*dfc11533SChris Williamson     return NULL;  /* no such vararg */
118*dfc11533SChris Williamson   else {
119*dfc11533SChris Williamson     *pos = ci->func + nparams + n;
120*dfc11533SChris Williamson     return "(*vararg)";  /* generic name for any vararg */
121*dfc11533SChris Williamson   }
122*dfc11533SChris Williamson }
123*dfc11533SChris Williamson 
124*dfc11533SChris Williamson 
findlocal(lua_State * L,CallInfo * ci,int n,StkId * pos)125*dfc11533SChris Williamson static const char *findlocal (lua_State *L, CallInfo *ci, int n,
126*dfc11533SChris Williamson                               StkId *pos) {
127*dfc11533SChris Williamson   const char *name = NULL;
128*dfc11533SChris Williamson   StkId base;
129*dfc11533SChris Williamson   if (isLua(ci)) {
130*dfc11533SChris Williamson     if (n < 0)  /* access to vararg values? */
131*dfc11533SChris Williamson       return findvararg(ci, -n, pos);
132*dfc11533SChris Williamson     else {
133*dfc11533SChris Williamson       base = ci->u.l.base;
134*dfc11533SChris Williamson       name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
135*dfc11533SChris Williamson     }
136*dfc11533SChris Williamson   }
137*dfc11533SChris Williamson   else
138*dfc11533SChris Williamson     base = ci->func + 1;
139*dfc11533SChris Williamson   if (name == NULL) {  /* no 'standard' name? */
140*dfc11533SChris Williamson     StkId limit = (ci == L->ci) ? L->top : ci->next->func;
141*dfc11533SChris Williamson     if (limit - base >= n && n > 0)  /* is 'n' inside 'ci' stack? */
142*dfc11533SChris Williamson       name = "(*temporary)";  /* generic name for any valid slot */
143*dfc11533SChris Williamson     else
144*dfc11533SChris Williamson       return NULL;  /* no name */
145*dfc11533SChris Williamson   }
146*dfc11533SChris Williamson   *pos = base + (n - 1);
147*dfc11533SChris Williamson   return name;
148*dfc11533SChris Williamson }
149*dfc11533SChris Williamson 
150*dfc11533SChris Williamson 
lua_getlocal(lua_State * L,const lua_Debug * ar,int n)151*dfc11533SChris Williamson LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
152*dfc11533SChris Williamson   const char *name;
153*dfc11533SChris Williamson   lua_lock(L);
154*dfc11533SChris Williamson   swapextra(L);
155*dfc11533SChris Williamson   if (ar == NULL) {  /* information about non-active function? */
156*dfc11533SChris Williamson     if (!isLfunction(L->top - 1))  /* not a Lua function? */
157*dfc11533SChris Williamson       name = NULL;
158*dfc11533SChris Williamson     else  /* consider live variables at function start (parameters) */
159*dfc11533SChris Williamson       name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
160*dfc11533SChris Williamson   }
161*dfc11533SChris Williamson   else {  /* active function; get information through 'ar' */
162*dfc11533SChris Williamson     StkId pos = 0;  /* to avoid warnings */
163*dfc11533SChris Williamson     name = findlocal(L, ar->i_ci, n, &pos);
164*dfc11533SChris Williamson     if (name) {
165*dfc11533SChris Williamson       setobj2s(L, L->top, pos);
166*dfc11533SChris Williamson       api_incr_top(L);
167*dfc11533SChris Williamson     }
168*dfc11533SChris Williamson   }
169*dfc11533SChris Williamson   swapextra(L);
170*dfc11533SChris Williamson   lua_unlock(L);
171*dfc11533SChris Williamson   return name;
172*dfc11533SChris Williamson }
173*dfc11533SChris Williamson 
174*dfc11533SChris Williamson 
lua_setlocal(lua_State * L,const lua_Debug * ar,int n)175*dfc11533SChris Williamson LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
176*dfc11533SChris Williamson   StkId pos = 0;  /* to avoid warnings */
177*dfc11533SChris Williamson   const char *name;
178*dfc11533SChris Williamson   lua_lock(L);
179*dfc11533SChris Williamson   swapextra(L);
180*dfc11533SChris Williamson   name = findlocal(L, ar->i_ci, n, &pos);
181*dfc11533SChris Williamson   if (name)
182*dfc11533SChris Williamson     setobjs2s(L, pos, L->top - 1);
183*dfc11533SChris Williamson   L->top--;  /* pop value */
184*dfc11533SChris Williamson   swapextra(L);
185*dfc11533SChris Williamson   lua_unlock(L);
186*dfc11533SChris Williamson   return name;
187*dfc11533SChris Williamson }
188*dfc11533SChris Williamson 
189*dfc11533SChris Williamson 
funcinfo(lua_Debug * ar,Closure * cl)190*dfc11533SChris Williamson static void funcinfo (lua_Debug *ar, Closure *cl) {
191*dfc11533SChris Williamson   if (noLuaClosure(cl)) {
192*dfc11533SChris Williamson     ar->source = "=[C]";
193*dfc11533SChris Williamson     ar->linedefined = -1;
194*dfc11533SChris Williamson     ar->lastlinedefined = -1;
195*dfc11533SChris Williamson     ar->what = "C";
196*dfc11533SChris Williamson   }
197*dfc11533SChris Williamson   else {
198*dfc11533SChris Williamson     Proto *p = cl->l.p;
199*dfc11533SChris Williamson     ar->source = p->source ? getstr(p->source) : "=?";
200*dfc11533SChris Williamson     ar->linedefined = p->linedefined;
201*dfc11533SChris Williamson     ar->lastlinedefined = p->lastlinedefined;
202*dfc11533SChris Williamson     ar->what = (ar->linedefined == 0) ? "main" : "Lua";
203*dfc11533SChris Williamson   }
204*dfc11533SChris Williamson   luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
205*dfc11533SChris Williamson }
206*dfc11533SChris Williamson 
207*dfc11533SChris Williamson 
collectvalidlines(lua_State * L,Closure * f)208*dfc11533SChris Williamson static void collectvalidlines (lua_State *L, Closure *f) {
209*dfc11533SChris Williamson   if (noLuaClosure(f)) {
210*dfc11533SChris Williamson     setnilvalue(L->top);
211*dfc11533SChris Williamson     api_incr_top(L);
212*dfc11533SChris Williamson   }
213*dfc11533SChris Williamson   else {
214*dfc11533SChris Williamson     int i;
215*dfc11533SChris Williamson     TValue v;
216*dfc11533SChris Williamson     int *lineinfo = f->l.p->lineinfo;
217*dfc11533SChris Williamson     Table *t = luaH_new(L);  /* new table to store active lines */
218*dfc11533SChris Williamson     sethvalue(L, L->top, t);  /* push it on stack */
219*dfc11533SChris Williamson     api_incr_top(L);
220*dfc11533SChris Williamson     setbvalue(&v, 1);  /* boolean 'true' to be the value of all indices */
221*dfc11533SChris Williamson     for (i = 0; i < f->l.p->sizelineinfo; i++)  /* for all lines with code */
222*dfc11533SChris Williamson       luaH_setint(L, t, lineinfo[i], &v);  /* table[line] = true */
223*dfc11533SChris Williamson   }
224*dfc11533SChris Williamson }
225*dfc11533SChris Williamson 
226*dfc11533SChris Williamson 
auxgetinfo(lua_State * L,const char * what,lua_Debug * ar,Closure * f,CallInfo * ci)227*dfc11533SChris Williamson static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
228*dfc11533SChris Williamson                        Closure *f, CallInfo *ci) {
229*dfc11533SChris Williamson   int status = 1;
230*dfc11533SChris Williamson   for (; *what; what++) {
231*dfc11533SChris Williamson     switch (*what) {
232*dfc11533SChris Williamson       case 'S': {
233*dfc11533SChris Williamson         funcinfo(ar, f);
234*dfc11533SChris Williamson         break;
235*dfc11533SChris Williamson       }
236*dfc11533SChris Williamson       case 'l': {
237*dfc11533SChris Williamson         ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1;
238*dfc11533SChris Williamson         break;
239*dfc11533SChris Williamson       }
240*dfc11533SChris Williamson       case 'u': {
241*dfc11533SChris Williamson         ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
242*dfc11533SChris Williamson         if (noLuaClosure(f)) {
243*dfc11533SChris Williamson           ar->isvararg = 1;
244*dfc11533SChris Williamson           ar->nparams = 0;
245*dfc11533SChris Williamson         }
246*dfc11533SChris Williamson         else {
247*dfc11533SChris Williamson           ar->isvararg = f->l.p->is_vararg;
248*dfc11533SChris Williamson           ar->nparams = f->l.p->numparams;
249*dfc11533SChris Williamson         }
250*dfc11533SChris Williamson         break;
251*dfc11533SChris Williamson       }
252*dfc11533SChris Williamson       case 't': {
253*dfc11533SChris Williamson         ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
254*dfc11533SChris Williamson         break;
255*dfc11533SChris Williamson       }
256*dfc11533SChris Williamson       case 'n': {
257*dfc11533SChris Williamson         /* calling function is a known Lua function? */
258*dfc11533SChris Williamson         if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
259*dfc11533SChris Williamson           ar->namewhat = getfuncname(L, ci->previous, &ar->name);
260*dfc11533SChris Williamson         else
261*dfc11533SChris Williamson           ar->namewhat = NULL;
262*dfc11533SChris Williamson         if (ar->namewhat == NULL) {
263*dfc11533SChris Williamson           ar->namewhat = "";  /* not found */
264*dfc11533SChris Williamson           ar->name = NULL;
265*dfc11533SChris Williamson         }
266*dfc11533SChris Williamson         break;
267*dfc11533SChris Williamson       }
268*dfc11533SChris Williamson       case 'L':
269*dfc11533SChris Williamson       case 'f':  /* handled by lua_getinfo */
270*dfc11533SChris Williamson         break;
271*dfc11533SChris Williamson       default: status = 0;  /* invalid option */
272*dfc11533SChris Williamson     }
273*dfc11533SChris Williamson   }
274*dfc11533SChris Williamson   return status;
275*dfc11533SChris Williamson }
276*dfc11533SChris Williamson 
277*dfc11533SChris Williamson 
lua_getinfo(lua_State * L,const char * what,lua_Debug * ar)278*dfc11533SChris Williamson LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
279*dfc11533SChris Williamson   int status;
280*dfc11533SChris Williamson   Closure *cl;
281*dfc11533SChris Williamson   CallInfo *ci;
282*dfc11533SChris Williamson   StkId func;
283*dfc11533SChris Williamson   lua_lock(L);
284*dfc11533SChris Williamson   swapextra(L);
285*dfc11533SChris Williamson   if (*what == '>') {
286*dfc11533SChris Williamson     ci = NULL;
287*dfc11533SChris Williamson     func = L->top - 1;
288*dfc11533SChris Williamson     api_check(L, ttisfunction(func), "function expected");
289*dfc11533SChris Williamson     what++;  /* skip the '>' */
290*dfc11533SChris Williamson     L->top--;  /* pop function */
291*dfc11533SChris Williamson   }
292*dfc11533SChris Williamson   else {
293*dfc11533SChris Williamson     ci = ar->i_ci;
294*dfc11533SChris Williamson     func = ci->func;
295*dfc11533SChris Williamson     lua_assert(ttisfunction(ci->func));
296*dfc11533SChris Williamson   }
297*dfc11533SChris Williamson   cl = ttisclosure(func) ? clvalue(func) : NULL;
298*dfc11533SChris Williamson   status = auxgetinfo(L, what, ar, cl, ci);
299*dfc11533SChris Williamson   if (strchr(what, 'f')) {
300*dfc11533SChris Williamson     setobjs2s(L, L->top, func);
301*dfc11533SChris Williamson     api_incr_top(L);
302*dfc11533SChris Williamson   }
303*dfc11533SChris Williamson   swapextra(L);
304*dfc11533SChris Williamson   if (strchr(what, 'L'))
305*dfc11533SChris Williamson     collectvalidlines(L, cl);
306*dfc11533SChris Williamson   lua_unlock(L);
307*dfc11533SChris Williamson   return status;
308*dfc11533SChris Williamson }
309*dfc11533SChris Williamson 
310*dfc11533SChris Williamson 
311*dfc11533SChris Williamson /*
312*dfc11533SChris Williamson ** {======================================================
313*dfc11533SChris Williamson ** Symbolic Execution
314*dfc11533SChris Williamson ** =======================================================
315*dfc11533SChris Williamson */
316*dfc11533SChris Williamson 
317*dfc11533SChris Williamson static const char *getobjname (Proto *p, int lastpc, int reg,
318*dfc11533SChris Williamson                                const char **name);
319*dfc11533SChris Williamson 
320*dfc11533SChris Williamson 
321*dfc11533SChris Williamson /*
322*dfc11533SChris Williamson ** find a "name" for the RK value 'c'
323*dfc11533SChris Williamson */
kname(Proto * p,int pc,int c,const char ** name)324*dfc11533SChris Williamson static void kname (Proto *p, int pc, int c, const char **name) {
325*dfc11533SChris Williamson   if (ISK(c)) {  /* is 'c' a constant? */
326*dfc11533SChris Williamson     TValue *kvalue = &p->k[INDEXK(c)];
327*dfc11533SChris Williamson     if (ttisstring(kvalue)) {  /* literal constant? */
328*dfc11533SChris Williamson       *name = svalue(kvalue);  /* it is its own name */
329*dfc11533SChris Williamson       return;
330*dfc11533SChris Williamson     }
331*dfc11533SChris Williamson     /* else no reasonable name found */
332*dfc11533SChris Williamson   }
333*dfc11533SChris Williamson   else {  /* 'c' is a register */
334*dfc11533SChris Williamson     const char *what = getobjname(p, pc, c, name); /* search for 'c' */
335*dfc11533SChris Williamson     if (what && *what == 'c') {  /* found a constant name? */
336*dfc11533SChris Williamson       return;  /* 'name' already filled */
337*dfc11533SChris Williamson     }
338*dfc11533SChris Williamson     /* else no reasonable name found */
339*dfc11533SChris Williamson   }
340*dfc11533SChris Williamson   *name = "?";  /* no reasonable name found */
341*dfc11533SChris Williamson }
342*dfc11533SChris Williamson 
343*dfc11533SChris Williamson 
filterpc(int pc,int jmptarget)344*dfc11533SChris Williamson static int filterpc (int pc, int jmptarget) {
345*dfc11533SChris Williamson   if (pc < jmptarget)  /* is code conditional (inside a jump)? */
346*dfc11533SChris Williamson     return -1;  /* cannot know who sets that register */
347*dfc11533SChris Williamson   else return pc;  /* current position sets that register */
348*dfc11533SChris Williamson }
349*dfc11533SChris Williamson 
350*dfc11533SChris Williamson 
351*dfc11533SChris Williamson /*
352*dfc11533SChris Williamson ** try to find last instruction before 'lastpc' that modified register 'reg'
353*dfc11533SChris Williamson */
findsetreg(Proto * p,int lastpc,int reg)354*dfc11533SChris Williamson static int findsetreg (Proto *p, int lastpc, int reg) {
355*dfc11533SChris Williamson   int pc;
356*dfc11533SChris Williamson   int setreg = -1;  /* keep last instruction that changed 'reg' */
357*dfc11533SChris Williamson   int jmptarget = 0;  /* any code before this address is conditional */
358*dfc11533SChris Williamson   for (pc = 0; pc < lastpc; pc++) {
359*dfc11533SChris Williamson     Instruction i = p->code[pc];
360*dfc11533SChris Williamson     OpCode op = GET_OPCODE(i);
361*dfc11533SChris Williamson     int a = GETARG_A(i);
362*dfc11533SChris Williamson     switch (op) {
363*dfc11533SChris Williamson       case OP_LOADNIL: {
364*dfc11533SChris Williamson         int b = GETARG_B(i);
365*dfc11533SChris Williamson         if (a <= reg && reg <= a + b)  /* set registers from 'a' to 'a+b' */
366*dfc11533SChris Williamson           setreg = filterpc(pc, jmptarget);
367*dfc11533SChris Williamson         break;
368*dfc11533SChris Williamson       }
369*dfc11533SChris Williamson       case OP_TFORCALL: {
370*dfc11533SChris Williamson         if (reg >= a + 2)  /* affect all regs above its base */
371*dfc11533SChris Williamson           setreg = filterpc(pc, jmptarget);
372*dfc11533SChris Williamson         break;
373*dfc11533SChris Williamson       }
374*dfc11533SChris Williamson       case OP_CALL:
375*dfc11533SChris Williamson       case OP_TAILCALL: {
376*dfc11533SChris Williamson         if (reg >= a)  /* affect all registers above base */
377*dfc11533SChris Williamson           setreg = filterpc(pc, jmptarget);
378*dfc11533SChris Williamson         break;
379*dfc11533SChris Williamson       }
380*dfc11533SChris Williamson       case OP_JMP: {
381*dfc11533SChris Williamson         int b = GETARG_sBx(i);
382*dfc11533SChris Williamson         int dest = pc + 1 + b;
383*dfc11533SChris Williamson         /* jump is forward and do not skip `lastpc'? */
384*dfc11533SChris Williamson         if (pc < dest && dest <= lastpc) {
385*dfc11533SChris Williamson           if (dest > jmptarget)
386*dfc11533SChris Williamson             jmptarget = dest;  /* update 'jmptarget' */
387*dfc11533SChris Williamson         }
388*dfc11533SChris Williamson         break;
389*dfc11533SChris Williamson       }
390*dfc11533SChris Williamson       case OP_TEST: {
391*dfc11533SChris Williamson         if (reg == a)  /* jumped code can change 'a' */
392*dfc11533SChris Williamson           setreg = filterpc(pc, jmptarget);
393*dfc11533SChris Williamson         break;
394*dfc11533SChris Williamson       }
395*dfc11533SChris Williamson       default:
396*dfc11533SChris Williamson         if (testAMode(op) && reg == a)  /* any instruction that set A */
397*dfc11533SChris Williamson           setreg = filterpc(pc, jmptarget);
398*dfc11533SChris Williamson         break;
399*dfc11533SChris Williamson     }
400*dfc11533SChris Williamson   }
401*dfc11533SChris Williamson   return setreg;
402*dfc11533SChris Williamson }
403*dfc11533SChris Williamson 
404*dfc11533SChris Williamson 
getobjname(Proto * p,int lastpc,int reg,const char ** name)405*dfc11533SChris Williamson static const char *getobjname (Proto *p, int lastpc, int reg,
406*dfc11533SChris Williamson                                const char **name) {
407*dfc11533SChris Williamson   int pc;
408*dfc11533SChris Williamson   *name = luaF_getlocalname(p, reg + 1, lastpc);
409*dfc11533SChris Williamson   if (*name)  /* is a local? */
410*dfc11533SChris Williamson     return "local";
411*dfc11533SChris Williamson   /* else try symbolic execution */
412*dfc11533SChris Williamson   pc = findsetreg(p, lastpc, reg);
413*dfc11533SChris Williamson   if (pc != -1) {  /* could find instruction? */
414*dfc11533SChris Williamson     Instruction i = p->code[pc];
415*dfc11533SChris Williamson     OpCode op = GET_OPCODE(i);
416*dfc11533SChris Williamson     switch (op) {
417*dfc11533SChris Williamson       case OP_MOVE: {
418*dfc11533SChris Williamson         int b = GETARG_B(i);  /* move from 'b' to 'a' */
419*dfc11533SChris Williamson         if (b < GETARG_A(i))
420*dfc11533SChris Williamson           return getobjname(p, pc, b, name);  /* get name for 'b' */
421*dfc11533SChris Williamson         break;
422*dfc11533SChris Williamson       }
423*dfc11533SChris Williamson       case OP_GETTABUP:
424*dfc11533SChris Williamson       case OP_GETTABLE: {
425*dfc11533SChris Williamson         int k = GETARG_C(i);  /* key index */
426*dfc11533SChris Williamson         int t = GETARG_B(i);  /* table index */
427*dfc11533SChris Williamson         const char *vn = (op == OP_GETTABLE)  /* name of indexed variable */
428*dfc11533SChris Williamson                          ? luaF_getlocalname(p, t + 1, pc)
429*dfc11533SChris Williamson                          : upvalname(p, t);
430*dfc11533SChris Williamson         kname(p, pc, k, name);
431*dfc11533SChris Williamson         return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";
432*dfc11533SChris Williamson       }
433*dfc11533SChris Williamson       case OP_GETUPVAL: {
434*dfc11533SChris Williamson         *name = upvalname(p, GETARG_B(i));
435*dfc11533SChris Williamson         return "upvalue";
436*dfc11533SChris Williamson       }
437*dfc11533SChris Williamson       case OP_LOADK:
438*dfc11533SChris Williamson       case OP_LOADKX: {
439*dfc11533SChris Williamson         int b = (op == OP_LOADK) ? GETARG_Bx(i)
440*dfc11533SChris Williamson                                  : GETARG_Ax(p->code[pc + 1]);
441*dfc11533SChris Williamson         if (ttisstring(&p->k[b])) {
442*dfc11533SChris Williamson           *name = svalue(&p->k[b]);
443*dfc11533SChris Williamson           return "constant";
444*dfc11533SChris Williamson         }
445*dfc11533SChris Williamson         break;
446*dfc11533SChris Williamson       }
447*dfc11533SChris Williamson       case OP_SELF: {
448*dfc11533SChris Williamson         int k = GETARG_C(i);  /* key index */
449*dfc11533SChris Williamson         kname(p, pc, k, name);
450*dfc11533SChris Williamson         return "method";
451*dfc11533SChris Williamson       }
452*dfc11533SChris Williamson       default: break;  /* go through to return NULL */
453*dfc11533SChris Williamson     }
454*dfc11533SChris Williamson   }
455*dfc11533SChris Williamson   return NULL;  /* could not find reasonable name */
456*dfc11533SChris Williamson }
457*dfc11533SChris Williamson 
458*dfc11533SChris Williamson 
getfuncname(lua_State * L,CallInfo * ci,const char ** name)459*dfc11533SChris Williamson static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
460*dfc11533SChris Williamson   TMS tm;
461*dfc11533SChris Williamson   Proto *p = ci_func(ci)->p;  /* calling function */
462*dfc11533SChris Williamson   int pc = currentpc(ci);  /* calling instruction index */
463*dfc11533SChris Williamson   Instruction i = p->code[pc];  /* calling instruction */
464*dfc11533SChris Williamson   switch (GET_OPCODE(i)) {
465*dfc11533SChris Williamson     case OP_CALL:
466*dfc11533SChris Williamson     case OP_TAILCALL:  /* get function name */
467*dfc11533SChris Williamson       return getobjname(p, pc, GETARG_A(i), name);
468*dfc11533SChris Williamson     case OP_TFORCALL: {  /* for iterator */
469*dfc11533SChris Williamson       *name = "for iterator";
470*dfc11533SChris Williamson       return "for iterator";
471*dfc11533SChris Williamson     }
472*dfc11533SChris Williamson     /* all other instructions can call only through metamethods */
473*dfc11533SChris Williamson     case OP_SELF:
474*dfc11533SChris Williamson     case OP_GETTABUP:
475*dfc11533SChris Williamson     case OP_GETTABLE: tm = TM_INDEX; break;
476*dfc11533SChris Williamson     case OP_SETTABUP:
477*dfc11533SChris Williamson     case OP_SETTABLE: tm = TM_NEWINDEX; break;
478*dfc11533SChris Williamson     case OP_EQ: tm = TM_EQ; break;
479*dfc11533SChris Williamson     case OP_ADD: tm = TM_ADD; break;
480*dfc11533SChris Williamson     case OP_SUB: tm = TM_SUB; break;
481*dfc11533SChris Williamson     case OP_MUL: tm = TM_MUL; break;
482*dfc11533SChris Williamson     case OP_DIV: tm = TM_DIV; break;
483*dfc11533SChris Williamson     case OP_MOD: tm = TM_MOD; break;
484*dfc11533SChris Williamson     case OP_POW: tm = TM_POW; break;
485*dfc11533SChris Williamson     case OP_UNM: tm = TM_UNM; break;
486*dfc11533SChris Williamson     case OP_LEN: tm = TM_LEN; break;
487*dfc11533SChris Williamson     case OP_LT: tm = TM_LT; break;
488*dfc11533SChris Williamson     case OP_LE: tm = TM_LE; break;
489*dfc11533SChris Williamson     case OP_CONCAT: tm = TM_CONCAT; break;
490*dfc11533SChris Williamson     default:
491*dfc11533SChris Williamson       return NULL;  /* else no useful name can be found */
492*dfc11533SChris Williamson   }
493*dfc11533SChris Williamson   *name = getstr(G(L)->tmname[tm]);
494*dfc11533SChris Williamson   return "metamethod";
495*dfc11533SChris Williamson }
496*dfc11533SChris Williamson 
497*dfc11533SChris Williamson /* }====================================================== */
498*dfc11533SChris Williamson 
499*dfc11533SChris Williamson 
500*dfc11533SChris Williamson 
501*dfc11533SChris Williamson /*
502*dfc11533SChris Williamson ** only ANSI way to check whether a pointer points to an array
503*dfc11533SChris Williamson ** (used only for error messages, so efficiency is not a big concern)
504*dfc11533SChris Williamson */
isinstack(CallInfo * ci,const TValue * o)505*dfc11533SChris Williamson static int isinstack (CallInfo *ci, const TValue *o) {
506*dfc11533SChris Williamson   StkId p;
507*dfc11533SChris Williamson   for (p = ci->u.l.base; p < ci->top; p++)
508*dfc11533SChris Williamson     if (o == p) return 1;
509*dfc11533SChris Williamson   return 0;
510*dfc11533SChris Williamson }
511*dfc11533SChris Williamson 
512*dfc11533SChris Williamson 
getupvalname(CallInfo * ci,const TValue * o,const char ** name)513*dfc11533SChris Williamson static const char *getupvalname (CallInfo *ci, const TValue *o,
514*dfc11533SChris Williamson                                  const char **name) {
515*dfc11533SChris Williamson   LClosure *c = ci_func(ci);
516*dfc11533SChris Williamson   int i;
517*dfc11533SChris Williamson   for (i = 0; i < c->nupvalues; i++) {
518*dfc11533SChris Williamson     if (c->upvals[i]->v == o) {
519*dfc11533SChris Williamson       *name = upvalname(c->p, i);
520*dfc11533SChris Williamson       return "upvalue";
521*dfc11533SChris Williamson     }
522*dfc11533SChris Williamson   }
523*dfc11533SChris Williamson   return NULL;
524*dfc11533SChris Williamson }
525*dfc11533SChris Williamson 
526*dfc11533SChris Williamson 
luaG_typeerror(lua_State * L,const TValue * o,const char * op)527*dfc11533SChris Williamson l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
528*dfc11533SChris Williamson   CallInfo *ci = L->ci;
529*dfc11533SChris Williamson   const char *name = NULL;
530*dfc11533SChris Williamson   const char *t = objtypename(o);
531*dfc11533SChris Williamson   const char *kind = NULL;
532*dfc11533SChris Williamson   if (isLua(ci)) {
533*dfc11533SChris Williamson     kind = getupvalname(ci, o, &name);  /* check whether 'o' is an upvalue */
534*dfc11533SChris Williamson     if (!kind && isinstack(ci, o))  /* no? try a register */
535*dfc11533SChris Williamson       kind = getobjname(ci_func(ci)->p, currentpc(ci),
536*dfc11533SChris Williamson                         cast_int(o - ci->u.l.base), &name);
537*dfc11533SChris Williamson   }
538*dfc11533SChris Williamson   if (kind)
539*dfc11533SChris Williamson     luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
540*dfc11533SChris Williamson                 op, kind, name, t);
541*dfc11533SChris Williamson   else
542*dfc11533SChris Williamson     luaG_runerror(L, "attempt to %s a %s value", op, t);
543*dfc11533SChris Williamson }
544*dfc11533SChris Williamson 
545*dfc11533SChris Williamson 
luaG_concaterror(lua_State * L,StkId p1,StkId p2)546*dfc11533SChris Williamson l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
547*dfc11533SChris Williamson   if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
548*dfc11533SChris Williamson   lua_assert(!ttisstring(p1) && !ttisnumber(p1));
549*dfc11533SChris Williamson   luaG_typeerror(L, p1, "concatenate");
550*dfc11533SChris Williamson }
551*dfc11533SChris Williamson 
552*dfc11533SChris Williamson 
luaG_aritherror(lua_State * L,const TValue * p1,const TValue * p2)553*dfc11533SChris Williamson l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
554*dfc11533SChris Williamson   TValue temp;
555*dfc11533SChris Williamson   if (luaV_tonumber(p1, &temp) == NULL)
556*dfc11533SChris Williamson     p2 = p1;  /* first operand is wrong */
557*dfc11533SChris Williamson   luaG_typeerror(L, p2, "perform arithmetic on");
558*dfc11533SChris Williamson }
559*dfc11533SChris Williamson 
560*dfc11533SChris Williamson 
luaG_ordererror(lua_State * L,const TValue * p1,const TValue * p2)561*dfc11533SChris Williamson l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
562*dfc11533SChris Williamson   const char *t1 = objtypename(p1);
563*dfc11533SChris Williamson   const char *t2 = objtypename(p2);
564*dfc11533SChris Williamson   if (t1 == t2)
565*dfc11533SChris Williamson     luaG_runerror(L, "attempt to compare two %s values", t1);
566*dfc11533SChris Williamson   else
567*dfc11533SChris Williamson     luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
568*dfc11533SChris Williamson }
569*dfc11533SChris Williamson 
570*dfc11533SChris Williamson 
addinfo(lua_State * L,const char * msg)571*dfc11533SChris Williamson static void addinfo (lua_State *L, const char *msg) {
572*dfc11533SChris Williamson   CallInfo *ci = L->ci;
573*dfc11533SChris Williamson   if (isLua(ci)) {  /* is Lua code? */
574*dfc11533SChris Williamson     char buff[LUA_IDSIZE];  /* add file:line information */
575*dfc11533SChris Williamson     int line = currentline(ci);
576*dfc11533SChris Williamson     TString *src = ci_func(ci)->p->source;
577*dfc11533SChris Williamson     if (src)
578*dfc11533SChris Williamson       luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
579*dfc11533SChris Williamson     else {  /* no source available; use "?" instead */
580*dfc11533SChris Williamson       buff[0] = '?'; buff[1] = '\0';
581*dfc11533SChris Williamson     }
582*dfc11533SChris Williamson     luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
583*dfc11533SChris Williamson   }
584*dfc11533SChris Williamson }
585*dfc11533SChris Williamson 
586*dfc11533SChris Williamson 
luaG_errormsg(lua_State * L)587*dfc11533SChris Williamson l_noret luaG_errormsg (lua_State *L) {
588*dfc11533SChris Williamson   if (L->errfunc != 0) {  /* is there an error handling function? */
589*dfc11533SChris Williamson     StkId errfunc = restorestack(L, L->errfunc);
590*dfc11533SChris Williamson     if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
591*dfc11533SChris Williamson     setobjs2s(L, L->top, L->top - 1);  /* move argument */
592*dfc11533SChris Williamson     setobjs2s(L, L->top - 1, errfunc);  /* push function */
593*dfc11533SChris Williamson     L->top++;
594*dfc11533SChris Williamson     luaD_call(L, L->top - 2, 1, 0);  /* call it */
595*dfc11533SChris Williamson   }
596*dfc11533SChris Williamson   luaD_throw(L, LUA_ERRRUN);
597*dfc11533SChris Williamson }
598*dfc11533SChris Williamson 
599*dfc11533SChris Williamson 
luaG_runerror(lua_State * L,const char * fmt,...)600*dfc11533SChris Williamson l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
601*dfc11533SChris Williamson   va_list argp;
602*dfc11533SChris Williamson   va_start(argp, fmt);
603*dfc11533SChris Williamson   addinfo(L, luaO_pushvfstring(L, fmt, argp));
604*dfc11533SChris Williamson   va_end(argp);
605*dfc11533SChris Williamson   luaG_errormsg(L);
606*dfc11533SChris Williamson }
607*dfc11533SChris Williamson 
608