lib_debug.c (9464B)
1 /* 2 ** Debug library. 3 ** Copyright (C) 2005-2016 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) LJLIB_REC(.) 42 { 43 lj_lib_checktabornil(L, 2); 44 L->top = L->base+2; 45 lua_setmetatable(L, 1); 46 #if LJ_51 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_51 260 LJLIB_CF(debug_getuservalue) 261 { 262 if (L->base < L->top) 263 lua_getuservalue(L, 1); 264 return 1; 265 } 266 267 LJLIB_CF(debug_setuservalue) 268 { 269 TValue *o = L->base; 270 if (!(o < L->top && (tvisudata(o)||tvistab(o)))) 271 lj_err_argt(L, 1, LUA_TUSERDATA); 272 if (!(o+1 < L->top && tvistab(o+1))) 273 lj_err_argt(L, 2, LUA_TTABLE); 274 L->top = o+2; 275 lua_setuservalue(L, 1); 276 return 1; 277 } 278 #endif 279 280 /* ------------------------------------------------------------------------ */ 281 282 static const char KEY_HOOK = 'h'; 283 284 static void hookf(lua_State *L, lua_Debug *ar) 285 { 286 static const char *const hooknames[] = 287 {"call", "return", "line", "count", "tail return"}; 288 lua_pushlightuserdata(L, (void *)&KEY_HOOK); 289 lua_rawget(L, LUA_REGISTRYINDEX); 290 if (lua_isfunction(L, -1)) { 291 lua_pushstring(L, hooknames[(int)ar->event]); 292 if (ar->currentline >= 0) 293 lua_pushinteger(L, ar->currentline); 294 else lua_pushnil(L); 295 lua_call(L, 2, 0); 296 } 297 } 298 299 static int makemask(const char *smask, int count) 300 { 301 int mask = 0; 302 if (strchr(smask, 'c')) mask |= LUA_MASKCALL; 303 if (strchr(smask, 'r')) mask |= LUA_MASKRET; 304 if (strchr(smask, 'l')) mask |= LUA_MASKLINE; 305 if (count > 0) mask |= LUA_MASKCOUNT; 306 return mask; 307 } 308 309 static char *unmakemask(int mask, char *smask) 310 { 311 int i = 0; 312 if (mask & LUA_MASKCALL) smask[i++] = 'c'; 313 if (mask & LUA_MASKRET) smask[i++] = 'r'; 314 if (mask & LUA_MASKLINE) smask[i++] = 'l'; 315 smask[i] = '\0'; 316 return smask; 317 } 318 319 LJLIB_CF(debug_sethook) 320 { 321 int arg, mask, count; 322 lua_Hook func; 323 (void)getthread(L, &arg); 324 if (lua_isnoneornil(L, arg+1)) { 325 lua_settop(L, arg+1); 326 func = NULL; mask = 0; count = 0; /* turn off hooks */ 327 } else { 328 const char *smask = luaL_checkstring(L, arg+2); 329 luaL_checktype(L, arg+1, LUA_TFUNCTION); 330 count = luaL_optint(L, arg+3, 0); 331 func = hookf; mask = makemask(smask, count); 332 } 333 lua_pushlightuserdata(L, (void *)&KEY_HOOK); 334 lua_pushvalue(L, arg+1); 335 lua_rawset(L, LUA_REGISTRYINDEX); 336 lua_sethook(L, func, mask, count); 337 return 0; 338 } 339 340 LJLIB_CF(debug_gethook) 341 { 342 char buff[5]; 343 int mask = lua_gethookmask(L); 344 lua_Hook hook = lua_gethook(L); 345 if (hook != NULL && hook != hookf) { /* external hook? */ 346 lua_pushliteral(L, "external hook"); 347 } else { 348 lua_pushlightuserdata(L, (void *)&KEY_HOOK); 349 lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ 350 } 351 lua_pushstring(L, unmakemask(mask, buff)); 352 lua_pushinteger(L, lua_gethookcount(L)); 353 return 3; 354 } 355 356 /* ------------------------------------------------------------------------ */ 357 358 LJLIB_CF(debug_debug) 359 { 360 for (;;) { 361 char buffer[250]; 362 fputs("lua_debug> ", stderr); 363 if (fgets(buffer, sizeof(buffer), stdin) == 0 || 364 strcmp(buffer, "cont\n") == 0) 365 return 0; 366 if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || 367 lua_pcall(L, 0, 0, 0)) { 368 fputs(lua_tostring(L, -1), stderr); 369 fputs("\n", stderr); 370 } 371 lua_settop(L, 0); /* remove eventual returns */ 372 } 373 } 374 375 /* ------------------------------------------------------------------------ */ 376 377 #define LEVELS1 12 /* size of the first part of the stack */ 378 #define LEVELS2 10 /* size of the second part of the stack */ 379 380 LJLIB_CF(debug_traceback) 381 { 382 int arg; 383 lua_State *L1 = getthread(L, &arg); 384 const char *msg = lua_tostring(L, arg+1); 385 if (msg == NULL && L->top > L->base+arg) 386 L->top = L->base+arg+1; 387 else 388 luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1))); 389 return 1; 390 } 391 392 /* ------------------------------------------------------------------------ */ 393 394 #include "lj_libdef.h" 395 396 LUALIB_API int luaopen_debug(lua_State *L) 397 { 398 LJ_LIB_REG(L, LUA_DBLIBNAME, debug); 399 return 1; 400 } 401