root/lib_debug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. LJLIB_CF
  2. LJLIB_CF
  3. LJLIB_CF
  4. LJLIB_CF
  5. LJLIB_CF
  6. settabss
  7. settabsi
  8. settabsb
  9. getthread
  10. treatstackoption
  11. LJLIB_CF
  12. LJLIB_CF
  13. LJLIB_CF
  14. debug_getupvalue
  15. LJLIB_CF
  16. LJLIB_CF
  17. LJLIB_CF
  18. LJLIB_CF
  19. LJLIB_CF
  20. LJLIB_CF
  21. hookf
  22. makemask
  23. unmakemask
  24. LJLIB_CF
  25. LJLIB_CF
  26. LJLIB_CF
  27. LJLIB_CF
  28. luaopen_debug

   1 /*
   2 ** Debug library.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 **
   5 ** Major portions taken verbatim or adapted from the Lua interpreter.
   6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
   7 */
   8 
   9 #define lib_debug_c
  10 #define LUA_LIB
  11 
  12 #include "lua.h"
  13 #include "lauxlib.h"
  14 #include "lualib.h"
  15 
  16 #include "lj_obj.h"
  17 #include "lj_gc.h"
  18 #include "lj_err.h"
  19 #include "lj_debug.h"
  20 #include "lj_lib.h"
  21 
  22 /* ------------------------------------------------------------------------ */
  23 
  24 #define LJLIB_MODULE_debug
  25 
  26 LJLIB_CF(debug_getregistry)
  27 {
  28   copyTV(L, L->top++, registry(L));
  29   return 1;
  30 }
  31 
  32 LJLIB_CF(debug_getmetatable)    LJLIB_REC(.)
  33 {
  34   lj_lib_checkany(L, 1);
  35   if (!lua_getmetatable(L, 1)) {
  36     setnilV(L->top-1);
  37   }
  38   return 1;
  39 }
  40 
  41 LJLIB_CF(debug_setmetatable)
  42 {
  43   lj_lib_checktabornil(L, 2);
  44   L->top = L->base+2;
  45   lua_setmetatable(L, 1);
  46 #if !LJ_52
  47   setboolV(L->top-1, 1);
  48 #endif
  49   return 1;
  50 }
  51 
  52 LJLIB_CF(debug_getfenv)
  53 {
  54   lj_lib_checkany(L, 1);
  55   lua_getfenv(L, 1);
  56   return 1;
  57 }
  58 
  59 LJLIB_CF(debug_setfenv)
  60 {
  61   lj_lib_checktab(L, 2);
  62   L->top = L->base+2;
  63   if (!lua_setfenv(L, 1))
  64     lj_err_caller(L, LJ_ERR_SETFENV);
  65   return 1;
  66 }
  67 
  68 /* ------------------------------------------------------------------------ */
  69 
  70 static void settabss(lua_State *L, const char *i, const char *v)
  71 {
  72   lua_pushstring(L, v);
  73   lua_setfield(L, -2, i);
  74 }
  75 
  76 static void settabsi(lua_State *L, const char *i, int v)
  77 {
  78   lua_pushinteger(L, v);
  79   lua_setfield(L, -2, i);
  80 }
  81 
  82 static void settabsb(lua_State *L, const char *i, int v)
  83 {
  84   lua_pushboolean(L, v);
  85   lua_setfield(L, -2, i);
  86 }
  87 
  88 static lua_State *getthread(lua_State *L, int *arg)
  89 {
  90   if (L->base < L->top && tvisthread(L->base)) {
  91     *arg = 1;
  92     return threadV(L->base);
  93   } else {
  94     *arg = 0;
  95     return L;
  96   }
  97 }
  98 
  99 static void treatstackoption(lua_State *L, lua_State *L1, const char *fname)
 100 {
 101   if (L == L1) {
 102     lua_pushvalue(L, -2);
 103     lua_remove(L, -3);
 104   }
 105   else
 106     lua_xmove(L1, L, 1);
 107   lua_setfield(L, -2, fname);
 108 }
 109 
 110 LJLIB_CF(debug_getinfo)
 111 {
 112   lj_Debug ar;
 113   int arg, opt_f = 0, opt_L = 0;
 114   lua_State *L1 = getthread(L, &arg);
 115   const char *options = luaL_optstring(L, arg+2, "flnSu");
 116   if (lua_isnumber(L, arg+1)) {
 117     if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), (lua_Debug *)&ar)) {
 118       setnilV(L->top-1);
 119       return 1;
 120     }
 121   } else if (L->base+arg < L->top && tvisfunc(L->base+arg)) {
 122     options = lua_pushfstring(L, ">%s", options);
 123     setfuncV(L1, L1->top++, funcV(L->base+arg));
 124   } else {
 125     lj_err_arg(L, arg+1, LJ_ERR_NOFUNCL);
 126   }
 127   if (!lj_debug_getinfo(L1, options, &ar, 1))
 128     lj_err_arg(L, arg+2, LJ_ERR_INVOPT);
 129   lua_createtable(L, 0, 16);  /* Create result table. */
 130   for (; *options; options++) {
 131     switch (*options) {
 132     case 'S':
 133       settabss(L, "source", ar.source);
 134       settabss(L, "short_src", ar.short_src);
 135       settabsi(L, "linedefined", ar.linedefined);
 136       settabsi(L, "lastlinedefined", ar.lastlinedefined);
 137       settabss(L, "what", ar.what);
 138       break;
 139     case 'l':
 140       settabsi(L, "currentline", ar.currentline);
 141       break;
 142     case 'u':
 143       settabsi(L, "nups", ar.nups);
 144       settabsi(L, "nparams", ar.nparams);
 145       settabsb(L, "isvararg", ar.isvararg);
 146       break;
 147     case 'n':
 148       settabss(L, "name", ar.name);
 149       settabss(L, "namewhat", ar.namewhat);
 150       break;
 151     case 'f': opt_f = 1; break;
 152     case 'L': opt_L = 1; break;
 153     default: break;
 154     }
 155   }
 156   if (opt_L) treatstackoption(L, L1, "activelines");
 157   if (opt_f) treatstackoption(L, L1, "func");
 158   return 1;  /* Return result table. */
 159 }
 160 
 161 LJLIB_CF(debug_getlocal)
 162 {
 163   int arg;
 164   lua_State *L1 = getthread(L, &arg);
 165   lua_Debug ar;
 166   const char *name;
 167   int slot = lj_lib_checkint(L, arg+2);
 168   if (tvisfunc(L->base+arg)) {
 169     L->top = L->base+arg+1;
 170     lua_pushstring(L, lua_getlocal(L, NULL, slot));
 171     return 1;
 172   }
 173   if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
 174     lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
 175   name = lua_getlocal(L1, &ar, slot);
 176   if (name) {
 177     lua_xmove(L1, L, 1);
 178     lua_pushstring(L, name);
 179     lua_pushvalue(L, -2);
 180     return 2;
 181   } else {
 182     setnilV(L->top-1);
 183     return 1;
 184   }
 185 }
 186 
 187 LJLIB_CF(debug_setlocal)
 188 {
 189   int arg;
 190   lua_State *L1 = getthread(L, &arg);
 191   lua_Debug ar;
 192   TValue *tv;
 193   if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
 194     lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
 195   tv = lj_lib_checkany(L, arg+3);
 196   copyTV(L1, L1->top++, tv);
 197   lua_pushstring(L, lua_setlocal(L1, &ar, lj_lib_checkint(L, arg+2)));
 198   return 1;
 199 }
 200 
 201 static int debug_getupvalue(lua_State *L, int get)
 202 {
 203   int32_t n = lj_lib_checkint(L, 2);
 204   const char *name;
 205   lj_lib_checkfunc(L, 1);
 206   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
 207   if (name) {
 208     lua_pushstring(L, name);
 209     if (!get) return 1;
 210     copyTV(L, L->top, L->top-2);
 211     L->top++;
 212     return 2;
 213   }
 214   return 0;
 215 }
 216 
 217 LJLIB_CF(debug_getupvalue)
 218 {
 219   return debug_getupvalue(L, 1);
 220 }
 221 
 222 LJLIB_CF(debug_setupvalue)
 223 {
 224   lj_lib_checkany(L, 3);
 225   return debug_getupvalue(L, 0);
 226 }
 227 
 228 LJLIB_CF(debug_upvalueid)
 229 {
 230   GCfunc *fn = lj_lib_checkfunc(L, 1);
 231   int32_t n = lj_lib_checkint(L, 2) - 1;
 232   if ((uint32_t)n >= fn->l.nupvalues)
 233     lj_err_arg(L, 2, LJ_ERR_IDXRNG);
 234   setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
 235                                         (void *)&fn->c.upvalue[n]);
 236   return 1;
 237 }
 238 
 239 LJLIB_CF(debug_upvaluejoin)
 240 {
 241   GCfunc *fn[2];
 242   GCRef *p[2];
 243   int i;
 244   for (i = 0; i < 2; i++) {
 245     int32_t n;
 246     fn[i] = lj_lib_checkfunc(L, 2*i+1);
 247     if (!isluafunc(fn[i]))
 248       lj_err_arg(L, 2*i+1, LJ_ERR_NOLFUNC);
 249     n = lj_lib_checkint(L, 2*i+2) - 1;
 250     if ((uint32_t)n >= fn[i]->l.nupvalues)
 251       lj_err_arg(L, 2*i+2, LJ_ERR_IDXRNG);
 252     p[i] = &fn[i]->l.uvptr[n];
 253   }
 254   setgcrefr(*p[0], *p[1]);
 255   lj_gc_objbarrier(L, fn[0], gcref(*p[1]));
 256   return 0;
 257 }
 258 
 259 #if LJ_52
 260 LJLIB_CF(debug_getuservalue)
 261 {
 262   TValue *o = L->base;
 263   if (o < L->top && tvisudata(o))
 264     settabV(L, o, tabref(udataV(o)->env));
 265   else
 266     setnilV(o);
 267   L->top = o+1;
 268   return 1;
 269 }
 270 
 271 LJLIB_CF(debug_setuservalue)
 272 {
 273   TValue *o = L->base;
 274   if (!(o < L->top && tvisudata(o)))
 275     lj_err_argt(L, 1, LUA_TUSERDATA);
 276   if (!(o+1 < L->top && tvistab(o+1)))
 277     lj_err_argt(L, 2, LUA_TTABLE);
 278   L->top = o+2;
 279   lua_setfenv(L, 1);
 280   return 1;
 281 }
 282 #endif
 283 
 284 /* ------------------------------------------------------------------------ */
 285 
 286 #define KEY_HOOK        ((void *)0x3004)
 287 
 288 static void hookf(lua_State *L, lua_Debug *ar)
 289 {
 290   static const char *const hooknames[] =
 291     {"call", "return", "line", "count", "tail return"};
 292   lua_pushlightuserdata(L, KEY_HOOK);
 293   lua_rawget(L, LUA_REGISTRYINDEX);
 294   if (lua_isfunction(L, -1)) {
 295     lua_pushstring(L, hooknames[(int)ar->event]);
 296     if (ar->currentline >= 0)
 297       lua_pushinteger(L, ar->currentline);
 298     else lua_pushnil(L);
 299     lua_call(L, 2, 0);
 300   }
 301 }
 302 
 303 static int makemask(const char *smask, int count)
 304 {
 305   int mask = 0;
 306   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
 307   if (strchr(smask, 'r')) mask |= LUA_MASKRET;
 308   if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
 309   if (count > 0) mask |= LUA_MASKCOUNT;
 310   return mask;
 311 }
 312 
 313 static char *unmakemask(int mask, char *smask)
 314 {
 315   int i = 0;
 316   if (mask & LUA_MASKCALL) smask[i++] = 'c';
 317   if (mask & LUA_MASKRET) smask[i++] = 'r';
 318   if (mask & LUA_MASKLINE) smask[i++] = 'l';
 319   smask[i] = '\0';
 320   return smask;
 321 }
 322 
 323 LJLIB_CF(debug_sethook)
 324 {
 325   int arg, mask, count;
 326   lua_Hook func;
 327   (void)getthread(L, &arg);
 328   if (lua_isnoneornil(L, arg+1)) {
 329     lua_settop(L, arg+1);
 330     func = NULL; mask = 0; count = 0;  /* turn off hooks */
 331   } else {
 332     const char *smask = luaL_checkstring(L, arg+2);
 333     luaL_checktype(L, arg+1, LUA_TFUNCTION);
 334     count = luaL_optint(L, arg+3, 0);
 335     func = hookf; mask = makemask(smask, count);
 336   }
 337   lua_pushlightuserdata(L, KEY_HOOK);
 338   lua_pushvalue(L, arg+1);
 339   lua_rawset(L, LUA_REGISTRYINDEX);
 340   lua_sethook(L, func, mask, count);
 341   return 0;
 342 }
 343 
 344 LJLIB_CF(debug_gethook)
 345 {
 346   char buff[5];
 347   int mask = lua_gethookmask(L);
 348   lua_Hook hook = lua_gethook(L);
 349   if (hook != NULL && hook != hookf) {  /* external hook? */
 350     lua_pushliteral(L, "external hook");
 351   } else {
 352     lua_pushlightuserdata(L, KEY_HOOK);
 353     lua_rawget(L, LUA_REGISTRYINDEX);   /* get hook */
 354   }
 355   lua_pushstring(L, unmakemask(mask, buff));
 356   lua_pushinteger(L, lua_gethookcount(L));
 357   return 3;
 358 }
 359 
 360 /* ------------------------------------------------------------------------ */
 361 
 362 LJLIB_CF(debug_debug)
 363 {
 364   for (;;) {
 365     char buffer[250];
 366     fputs("lua_debug> ", stderr);
 367     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
 368         strcmp(buffer, "cont\n") == 0)
 369       return 0;
 370     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
 371         lua_pcall(L, 0, 0, 0)) {
 372       fputs(lua_tostring(L, -1), stderr);
 373       fputs("\n", stderr);
 374     }
 375     lua_settop(L, 0);  /* remove eventual returns */
 376   }
 377 }
 378 
 379 /* ------------------------------------------------------------------------ */
 380 
 381 #define LEVELS1 12      /* size of the first part of the stack */
 382 #define LEVELS2 10      /* size of the second part of the stack */
 383 
 384 LJLIB_CF(debug_traceback)
 385 {
 386   int arg;
 387   lua_State *L1 = getthread(L, &arg);
 388   const char *msg = lua_tostring(L, arg+1);
 389   if (msg == NULL && L->top > L->base+arg)
 390     L->top = L->base+arg+1;
 391   else
 392     luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1)));
 393   return 1;
 394 }
 395 
 396 /* ------------------------------------------------------------------------ */
 397 
 398 #include "lj_libdef.h"
 399 
 400 LUALIB_API int luaopen_debug(lua_State *L)
 401 {
 402   LJ_LIB_REG(L, LUA_DBLIBNAME, debug);
 403   return 1;
 404 }
 405 

/* [<][>][^][v][top][bottom][index][help] */