src/lib_debug.c - luajit-2.0-src

Global variables defined

Functions defined

Macros defined

Source code

  1. /*
  2. ** Debug library.
  3. ** Copyright (C) 2005-2015 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. #define lib_debug_c
  9. #define LUA_LIB

  10. #include "lua.h"
  11. #include "lauxlib.h"
  12. #include "lualib.h"

  13. #include "lj_obj.h"
  14. #include "lj_gc.h"
  15. #include "lj_err.h"
  16. #include "lj_debug.h"
  17. #include "lj_lib.h"

  18. /* ------------------------------------------------------------------------ */

  19. #define LJLIB_MODULE_debug

  20. LJLIB_CF(debug_getregistry)
  21. {
  22.   copyTV(L, L->top++, registry(L));
  23.   return 1;
  24. }

  25. LJLIB_CF(debug_getmetatable)        LJLIB_REC(.)
  26. {
  27.   lj_lib_checkany(L, 1);
  28.   if (!lua_getmetatable(L, 1)) {
  29.     setnilV(L->top-1);
  30.   }
  31.   return 1;
  32. }

  33. LJLIB_CF(debug_setmetatable)
  34. {
  35.   lj_lib_checktabornil(L, 2);
  36.   L->top = L->base+2;
  37.   lua_setmetatable(L, 1);
  38. #if !LJ_52
  39.   setboolV(L->top-1, 1);
  40. #endif
  41.   return 1;
  42. }

  43. LJLIB_CF(debug_getfenv)
  44. {
  45.   lj_lib_checkany(L, 1);
  46.   lua_getfenv(L, 1);
  47.   return 1;
  48. }

  49. LJLIB_CF(debug_setfenv)
  50. {
  51.   lj_lib_checktab(L, 2);
  52.   L->top = L->base+2;
  53.   if (!lua_setfenv(L, 1))
  54.     lj_err_caller(L, LJ_ERR_SETFENV);
  55.   return 1;
  56. }

  57. /* ------------------------------------------------------------------------ */

  58. static void settabss(lua_State *L, const char *i, const char *v)
  59. {
  60.   lua_pushstring(L, v);
  61.   lua_setfield(L, -2, i);
  62. }

  63. static void settabsi(lua_State *L, const char *i, int v)
  64. {
  65.   lua_pushinteger(L, v);
  66.   lua_setfield(L, -2, i);
  67. }

  68. static void settabsb(lua_State *L, const char *i, int v)
  69. {
  70.   lua_pushboolean(L, v);
  71.   lua_setfield(L, -2, i);
  72. }

  73. static lua_State *getthread(lua_State *L, int *arg)
  74. {
  75.   if (L->base < L->top && tvisthread(L->base)) {
  76.     *arg = 1;
  77.     return threadV(L->base);
  78.   } else {
  79.     *arg = 0;
  80.     return L;
  81.   }
  82. }

  83. static void treatstackoption(lua_State *L, lua_State *L1, const char *fname)
  84. {
  85.   if (L == L1) {
  86.     lua_pushvalue(L, -2);
  87.     lua_remove(L, -3);
  88.   }
  89.   else
  90.     lua_xmove(L1, L, 1);
  91.   lua_setfield(L, -2, fname);
  92. }

  93. LJLIB_CF(debug_getinfo)
  94. {
  95.   lj_Debug ar;
  96.   int arg, opt_f = 0, opt_L = 0;
  97.   lua_State *L1 = getthread(L, &arg);
  98.   const char *options = luaL_optstring(L, arg+2, "flnSu");
  99.   if (lua_isnumber(L, arg+1)) {
  100.     if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), (lua_Debug *)&ar)) {
  101.       setnilV(L->top-1);
  102.       return 1;
  103.     }
  104.   } else if (L->base+arg < L->top && tvisfunc(L->base+arg)) {
  105.     options = lua_pushfstring(L, ">%s", options);
  106.     setfuncV(L1, L1->top++, funcV(L->base+arg));
  107.   } else {
  108.     lj_err_arg(L, arg+1, LJ_ERR_NOFUNCL);
  109.   }
  110.   if (!lj_debug_getinfo(L1, options, &ar, 1))
  111.     lj_err_arg(L, arg+2, LJ_ERR_INVOPT);
  112.   lua_createtable(L, 0, 16);  /* Create result table. */
  113.   for (; *options; options++) {
  114.     switch (*options) {
  115.     case 'S':
  116.       settabss(L, "source", ar.source);
  117.       settabss(L, "short_src", ar.short_src);
  118.       settabsi(L, "linedefined", ar.linedefined);
  119.       settabsi(L, "lastlinedefined", ar.lastlinedefined);
  120.       settabss(L, "what", ar.what);
  121.       break;
  122.     case 'l':
  123.       settabsi(L, "currentline", ar.currentline);
  124.       break;
  125.     case 'u':
  126.       settabsi(L, "nups", ar.nups);
  127.       settabsi(L, "nparams", ar.nparams);
  128.       settabsb(L, "isvararg", ar.isvararg);
  129.       break;
  130.     case 'n':
  131.       settabss(L, "name", ar.name);
  132.       settabss(L, "namewhat", ar.namewhat);
  133.       break;
  134.     case 'f': opt_f = 1; break;
  135.     case 'L': opt_L = 1; break;
  136.     default: break;
  137.     }
  138.   }
  139.   if (opt_L) treatstackoption(L, L1, "activelines");
  140.   if (opt_f) treatstackoption(L, L1, "func");
  141.   return 1/* Return result table. */
  142. }

  143. LJLIB_CF(debug_getlocal)
  144. {
  145.   int arg;
  146.   lua_State *L1 = getthread(L, &arg);
  147.   lua_Debug ar;
  148.   const char *name;
  149.   int slot = lj_lib_checkint(L, arg+2);
  150.   if (tvisfunc(L->base+arg)) {
  151.     L->top = L->base+arg+1;
  152.     lua_pushstring(L, lua_getlocal(L, NULL, slot));
  153.     return 1;
  154.   }
  155.   if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
  156.     lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
  157.   name = lua_getlocal(L1, &ar, slot);
  158.   if (name) {
  159.     lua_xmove(L1, L, 1);
  160.     lua_pushstring(L, name);
  161.     lua_pushvalue(L, -2);
  162.     return 2;
  163.   } else {
  164.     setnilV(L->top-1);
  165.     return 1;
  166.   }
  167. }

  168. LJLIB_CF(debug_setlocal)
  169. {
  170.   int arg;
  171.   lua_State *L1 = getthread(L, &arg);
  172.   lua_Debug ar;
  173.   TValue *tv;
  174.   if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
  175.     lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
  176.   tv = lj_lib_checkany(L, arg+3);
  177.   copyTV(L1, L1->top++, tv);
  178.   lua_pushstring(L, lua_setlocal(L1, &ar, lj_lib_checkint(L, arg+2)));
  179.   return 1;
  180. }

  181. static int debug_getupvalue(lua_State *L, int get)
  182. {
  183.   int32_t n = lj_lib_checkint(L, 2);
  184.   const char *name;
  185.   lj_lib_checkfunc(L, 1);
  186.   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
  187.   if (name) {
  188.     lua_pushstring(L, name);
  189.     if (!get) return 1;
  190.     copyTV(L, L->top, L->top-2);
  191.     L->top++;
  192.     return 2;
  193.   }
  194.   return 0;
  195. }

  196. LJLIB_CF(debug_getupvalue)
  197. {
  198.   return debug_getupvalue(L, 1);
  199. }

  200. LJLIB_CF(debug_setupvalue)
  201. {
  202.   lj_lib_checkany(L, 3);
  203.   return debug_getupvalue(L, 0);
  204. }

  205. LJLIB_CF(debug_upvalueid)
  206. {
  207.   GCfunc *fn = lj_lib_checkfunc(L, 1);
  208.   int32_t n = lj_lib_checkint(L, 2) - 1;
  209.   if ((uint32_t)n >= fn->l.nupvalues)
  210.     lj_err_arg(L, 2, LJ_ERR_IDXRNG);
  211.   setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
  212.                                         (void *)&fn->c.upvalue[n]);
  213.   return 1;
  214. }

  215. LJLIB_CF(debug_upvaluejoin)
  216. {
  217.   GCfunc *fn[2];
  218.   GCRef *p[2];
  219.   int i;
  220.   for (i = 0; i < 2; i++) {
  221.     int32_t n;
  222.     fn[i] = lj_lib_checkfunc(L, 2*i+1);
  223.     if (!isluafunc(fn[i]))
  224.       lj_err_arg(L, 2*i+1, LJ_ERR_NOLFUNC);
  225.     n = lj_lib_checkint(L, 2*i+2) - 1;
  226.     if ((uint32_t)n >= fn[i]->l.nupvalues)
  227.       lj_err_arg(L, 2*i+2, LJ_ERR_IDXRNG);
  228.     p[i] = &fn[i]->l.uvptr[n];
  229.   }
  230.   setgcrefr(*p[0], *p[1]);
  231.   lj_gc_objbarrier(L, fn[0], gcref(*p[1]));
  232.   return 0;
  233. }

  234. #if LJ_52
  235. LJLIB_CF(debug_getuservalue)
  236. {
  237.   TValue *o = L->base;
  238.   if (o < L->top && tvisudata(o))
  239.     settabV(L, o, tabref(udataV(o)->env));
  240.   else
  241.     setnilV(o);
  242.   L->top = o+1;
  243.   return 1;
  244. }

  245. LJLIB_CF(debug_setuservalue)
  246. {
  247.   TValue *o = L->base;
  248.   if (!(o < L->top && tvisudata(o)))
  249.     lj_err_argt(L, 1, LUA_TUSERDATA);
  250.   if (!(o+1 < L->top && tvistab(o+1)))
  251.     lj_err_argt(L, 2, LUA_TTABLE);
  252.   L->top = o+2;
  253.   lua_setfenv(L, 1);
  254.   return 1;
  255. }
  256. #endif

  257. /* ------------------------------------------------------------------------ */

  258. static const char KEY_HOOK = 'h';

  259. static void hookf(lua_State *L, lua_Debug *ar)
  260. {
  261.   static const char *const hooknames[] =
  262.     {"call", "return", "line", "count", "tail return"};
  263.   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
  264.   lua_rawget(L, LUA_REGISTRYINDEX);
  265.   if (lua_isfunction(L, -1)) {
  266.     lua_pushstring(L, hooknames[(int)ar->event]);
  267.     if (ar->currentline >= 0)
  268.       lua_pushinteger(L, ar->currentline);
  269.     else lua_pushnil(L);
  270.     lua_call(L, 2, 0);
  271.   }
  272. }

  273. static int makemask(const char *smask, int count)
  274. {
  275.   int mask = 0;
  276.   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
  277.   if (strchr(smask, 'r')) mask |= LUA_MASKRET;
  278.   if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
  279.   if (count > 0) mask |= LUA_MASKCOUNT;
  280.   return mask;
  281. }

  282. static char *unmakemask(int mask, char *smask)
  283. {
  284.   int i = 0;
  285.   if (mask & LUA_MASKCALL) smask[i++] = 'c';
  286.   if (mask & LUA_MASKRET) smask[i++] = 'r';
  287.   if (mask & LUA_MASKLINE) smask[i++] = 'l';
  288.   smask[i] = '\0';
  289.   return smask;
  290. }

  291. LJLIB_CF(debug_sethook)
  292. {
  293.   int arg, mask, count;
  294.   lua_Hook func;
  295.   (void)getthread(L, &arg);
  296.   if (lua_isnoneornil(L, arg+1)) {
  297.     lua_settop(L, arg+1);
  298.     func = NULL; mask = 0; count = 0/* turn off hooks */
  299.   } else {
  300.     const char *smask = luaL_checkstring(L, arg+2);
  301.     luaL_checktype(L, arg+1, LUA_TFUNCTION);
  302.     count = luaL_optint(L, arg+3, 0);
  303.     func = hookf; mask = makemask(smask, count);
  304.   }
  305.   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
  306.   lua_pushvalue(L, arg+1);
  307.   lua_rawset(L, LUA_REGISTRYINDEX);
  308.   lua_sethook(L, func, mask, count);
  309.   return 0;
  310. }

  311. LJLIB_CF(debug_gethook)
  312. {
  313.   char buff[5];
  314.   int mask = lua_gethookmask(L);
  315.   lua_Hook hook = lua_gethook(L);
  316.   if (hook != NULL && hook != hookf) {  /* external hook? */
  317.     lua_pushliteral(L, "external hook");
  318.   } else {
  319.     lua_pushlightuserdata(L, (void *)&KEY_HOOK);
  320.     lua_rawget(L, LUA_REGISTRYINDEX);   /* get hook */
  321.   }
  322.   lua_pushstring(L, unmakemask(mask, buff));
  323.   lua_pushinteger(L, lua_gethookcount(L));
  324.   return 3;
  325. }

  326. /* ------------------------------------------------------------------------ */

  327. LJLIB_CF(debug_debug)
  328. {
  329.   for (;;) {
  330.     char buffer[250];
  331.     fputs("lua_debug> ", stderr);
  332.     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
  333.         strcmp(buffer, "cont\n") == 0)
  334.       return 0;
  335.     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
  336.         lua_pcall(L, 0, 0, 0)) {
  337.       fputs(lua_tostring(L, -1), stderr);
  338.       fputs("\n", stderr);
  339.     }
  340.     lua_settop(L, 0);  /* remove eventual returns */
  341.   }
  342. }

  343. /* ------------------------------------------------------------------------ */

  344. #define LEVELS1        12        /* size of the first part of the stack */
  345. #define LEVELS2        10        /* size of the second part of the stack */

  346. LJLIB_CF(debug_traceback)
  347. {
  348.   int arg;
  349.   lua_State *L1 = getthread(L, &arg);
  350.   const char *msg = lua_tostring(L, arg+1);
  351.   if (msg == NULL && L->top > L->base+arg)
  352.     L->top = L->base+arg+1;
  353.   else
  354.     luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1)));
  355.   return 1;
  356. }

  357. /* ------------------------------------------------------------------------ */

  358. #include "lj_libdef.h"

  359. LUALIB_API int luaopen_debug(lua_State *L)
  360. {
  361.   LJ_LIB_REG(L, LUA_DBLIBNAME, debug);
  362.   return 1;
  363. }