Last active
February 27, 2023 06:24
-
-
Save ManuelBlanc/a6396fd3eb47db087d994e2787723aed to your computer and use it in GitHub Desktop.
BP Test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 8f3872a422beafcc9fc4c4d36e7518be58fb6a8b | |
Author: ManuelBlanc <manuel.blanc@estudiante.uam.es> | |
Date: Mon Feb 27 06:59:29 2023 +0100 | |
Implement BC_TRAP and jit.util.setbreakpoint | |
diff --git a/src/lib_debug.c b/src/lib_debug.c | |
index 3af7a353..e02070f1 100644 | |
--- a/src/lib_debug.c | |
+++ b/src/lib_debug.c | |
@@ -292,7 +292,10 @@ static void hookf(lua_State *L, lua_Debug *ar) | |
(L->top++)->u64 = KEY_HOOK; | |
lua_rawget(L, LUA_REGISTRYINDEX); | |
if (lua_isfunction(L, -1)) { | |
- lua_pushstring(L, hooknames[(int)ar->event]); | |
+ if (ar->event >= 0) | |
+ lua_pushstring(L, hooknames[(int)ar->event]); | |
+ else | |
+ lua_pushinteger(L, -(int)ar->event); | |
if (ar->currentline >= 0) | |
lua_pushinteger(L, ar->currentline); | |
else lua_pushnil(L); | |
diff --git a/src/lib_jit.c b/src/lib_jit.c | |
index 2867d420..2e16c317 100644 | |
--- a/src/lib_jit.c | |
+++ b/src/lib_jit.c | |
@@ -275,6 +275,53 @@ LJLIB_CF(jit_util_funcuvname) | |
return 0; | |
} | |
+static int setbreakpoint(lua_State *L, GCtab *t, GCproto *pt, BCLine line, uint16_t ud) | |
+{ | |
+ if (line < pt->firstline || line > pt->firstline + pt->numline) | |
+ return 0; | |
+ int set = 0; | |
+ BCPos pc; | |
+ for (pc = 1; pc <= pt->sizebc; ++pc) { | |
+ BCLine pcline = lj_debug_line(pt, pc); | |
+ if (pcline == line) { | |
+ BCIns *bc = proto_bc(pt)+pc; | |
+ TValue key, val; | |
+ setrawlightudV(&key, bc); | |
+ setintV(&val, *bc); | |
+ copyTV(L, lj_tab_set(L, t, &key), &val); | |
+ *bc = BCINS_AD(BC_TRAP, 0, ud); | |
+ set = 1; | |
+ break; | |
+ } | |
+ } | |
+ if (pt->flags & PROTO_CHILD) { | |
+ MSize i, sizekgc = pt->sizekgc; | |
+ GCRef *kr = mref(pt->k, GCRef) - (ptrdiff_t)sizekgc; | |
+ for (i = 0; i < sizekgc; i++, kr++) { | |
+ GCobj *o = gcref(*kr); | |
+ if (o->gch.gct == ~LJ_TPROTO) | |
+ set |= setbreakpoint(L, t, &o->pt, line, ud); | |
+ } | |
+ } | |
+ return set; | |
+} | |
+ | |
+/* local set = jit.util.setbreakpoint(func, idx) */ | |
+LJLIB_CF(jit_util_setbreakpoint) | |
+{ | |
+ GCfunc *fn = lj_lib_checkfunc(L, 1); | |
+ if (!isluafunc(fn)) | |
+ lj_err_arg(L, 1, LJ_ERR_NOLFUNC); | |
+ BCLine line = (BCLine)lj_lib_checkint(L, 2); | |
+ uint16_t ud = (uint16_t)lj_lib_checkint(L, 3); | |
+ TValue key; | |
+ key.u64 = KEY_DEBUG_BCLUT; | |
+ cTValue *t = lj_tab_get(L, tabV(registry(L)), &key); | |
+ int set = setbreakpoint(L, tabV(t), funcproto(fn), line, ud); | |
+ setboolV(L->top++, set); | |
+ return 1; | |
+} | |
+ | |
/* -- Reflection API for traces ------------------------------------------- */ | |
#if LJ_HASJIT | |
@@ -756,6 +803,10 @@ LUALIB_API int luaopen_jit(lua_State *L) | |
LJ_LIB_REG(L, "jit.opt", jit_opt); | |
#endif | |
L->top -= 2; | |
+ | |
+ TValue key; | |
+ key.u64 = KEY_DEBUG_BCLUT; | |
+ settabV(L, lj_tab_set(L, tabV(registry(L)), &key), lj_tab_new(L, 0, 0)); | |
return 1; | |
} | |
diff --git a/src/lj_bc.h b/src/lj_bc.h | |
index 02356e5b..e6f7623d 100644 | |
--- a/src/lj_bc.h | |
+++ b/src/lj_bc.h | |
@@ -187,14 +187,16 @@ | |
_(JMP, rbase, ___, jump, ___) \ | |
\ | |
/* Function headers. I/J = interp/JIT, F/V/C = fixarg/vararg/C func. */ \ | |
- _(FUNCF, rbase, ___, ___, ___) \ | |
+ _(FUNCF, rbase, ___, ___, ___) \ | |
_(IFUNCF, rbase, ___, ___, ___) \ | |
_(JFUNCF, rbase, ___, lit, ___) \ | |
- _(FUNCV, rbase, ___, ___, ___) \ | |
+ _(FUNCV, rbase, ___, ___, ___) \ | |
_(IFUNCV, rbase, ___, ___, ___) \ | |
_(JFUNCV, rbase, ___, lit, ___) \ | |
- _(FUNCC, rbase, ___, ___, ___) \ | |
- _(FUNCCW, rbase, ___, ___, ___) | |
+ _(FUNCC, rbase, ___, ___, ___) \ | |
+ _(FUNCCW, rbase, ___, ___, ___) \ | |
+ /* Extensions. */ \ | |
+ _(TRAP, base, ___, ___, ___) | |
/* Bytecode opcode numbers. */ | |
typedef enum { | |
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c | |
index ded382aa..f3c5b0d0 100644 | |
--- a/src/lj_dispatch.c | |
+++ b/src/lj_dispatch.c | |
@@ -400,7 +400,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres) | |
} | |
/* Instruction dispatch. Used by instr/line/return hooks or when recording. */ | |
-void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) | |
+void LJ_FASTCALL lj_dispatch_ins(lua_State *L, BCIns *pc) | |
{ | |
ERRNO_SAVE | |
GCfunc *fn = curr_func(L); | |
@@ -440,8 +440,19 @@ void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) | |
L->top = L->base + slots; /* Fix top again. */ | |
} | |
} | |
- if ((g->hookmask & LUA_MASKRET) && bc_isret(bc_op(pc[-1]))) | |
+ BCOp op = bc_op(pc[-1]); | |
+ if ((g->hookmask & LUA_MASKRET) && bc_isret(op)) | |
callhook(L, LUA_HOOKRET, -1); | |
+ else if (op == BC_TRAP) { | |
+ TValue key; | |
+ key.u64 = KEY_DEBUG_BCLUT; | |
+ cTValue *t = lj_tab_get(L, tabV(registry(L)), &key); | |
+ setrawlightudV(&key, pc-1); | |
+ cTValue *val = lj_tab_get(L, tabV(t), &key); | |
+ int ud = -(int)bc_d(pc[-1]); | |
+ pc[-1] = numberVint(val); | |
+ callhook(L, ud, -1); | |
+ } | |
ERRNO_RESTORE | |
} | |
diff --git a/src/lj_dispatch.h b/src/lj_dispatch.h | |
index 52762eea..7194afc6 100644 | |
--- a/src/lj_dispatch.h | |
+++ b/src/lj_dispatch.h | |
@@ -135,7 +135,7 @@ LJ_FUNC void lj_dispatch_init_hotcount(global_State *g); | |
LJ_FUNC void lj_dispatch_update(global_State *g); | |
/* Instruction dispatch callback for hooks or when recording. */ | |
-LJ_FUNCA void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc); | |
+LJ_FUNCA void LJ_FASTCALL lj_dispatch_ins(lua_State *L, BCIns *pc); | |
LJ_FUNCA ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns*pc); | |
#if LJ_HASJIT | |
LJ_FUNCA void LJ_FASTCALL lj_dispatch_stitch(jit_State *J, const BCIns *pc); | |
diff --git a/src/lj_jit.h b/src/lj_jit.h | |
index 7f081730..57fdde0d 100644 | |
--- a/src/lj_jit.h | |
+++ b/src/lj_jit.h | |
@@ -527,4 +527,6 @@ typedef struct jit_State { | |
#endif | |
#endif | |
+#define KEY_DEBUG_BCLUT (U64x(80000000,00000000)|'T') | |
+ | |
#endif | |
diff --git a/src/vm_x64.dasc b/src/vm_x64.dasc | |
index 03d96557..0bafab02 100644 | |
--- a/src/vm_x64.dasc | |
+++ b/src/vm_x64.dasc | |
@@ -4685,6 +4685,26 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |
| jmp ->vm_returnc | |
break; | |
+ case BC_TRAP: | |
+ | ins_AD | |
+ | movzx RDd, byte [DISPATCH+DISPATCH_GL(hookmask)] | |
+ | test RDL, HOOK_ACTIVE // Hook already active? | |
+ | jnz >1 | |
+ | mov L:RB, SAVE_L | |
+ | mov SAVE_PC, PC | |
+ | mov L:RB->base, BASE | |
+ | mov CARG2, PC | |
+ | mov CARG1, L:RB | |
+ | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. | |
+ | call extern lj_dispatch_ins // (lua_State *L, const BCIns *pc) | |
+ |1: | |
+ | mov BASE, L:RB->base | |
+ | movzx OP, PC_OP | |
+ | movzx RAd, PC_RA | |
+ | movzx RDd, PC_RD | |
+ | jmp aword [DISPATCH+OP*8+GG_DISP2STATIC] // Re-dispatch to static ins. | |
+ break; | |
+ | |
/* ---------------------------------------------------------------------- */ | |
default: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local CODESTR = [=[#!/usr/bin/env luajit | |
local a = 1 | |
local b = (1+3) .. string.sub("abc", 2, 3) .. "def" | |
local c = 3 | |
print(a,b,c) | |
--local function child() print(4,5,6) end local d = false | |
]=] | |
-- void lua_breakpoint(lua_State* L, int funcindex, int line, int enabled) | |
-- https://www.freelists.org/post/luajit/OP-HALT-debugger-patch-for-LuaJIT | |
-- https://marketplace.visualstudio.com/items?itemName=devCAT.lua-debug | |
-- https://github.com/fsfod/LuaJIT/commits/features/breakpoints | |
-- http://lua-users.org/lists/lua-l/2007-03/msg00006.html | |
-- http://lua-users.org/lists/lua-l/2018-05/msg00115.html | |
-- http://lua-users.org/lists/lua-l/2007-03/msg00006.html | |
-- https://groups.google.com/g/openresty/c/6EVoYdPr0I8 | |
local func = loadstring(CODESTR, "code.lua") | |
local function EXPERR(expected, fn, ...) | |
local ok, err = pcall(fn, ...) | |
if ok or err ~= expected then | |
local msg = "EXPERR failed!" | |
msg = msg.."\nExpected: "..expected | |
msg = msg.."\nReceived:"..ok and "!SUCCESS!" or err | |
error(msg) | |
end | |
end | |
local setbreakpoint = require("jit.util").setbreakpoint | |
local function printf(fmt,...) print(string.format("[INFO] "..fmt,...)) end | |
EXPERR("bad argument #1 to '?' (function expected, got no value)", setbreakpoint) | |
EXPERR("bad argument #1 to '?' (Lua function expected)", setbreakpoint, print) | |
EXPERR("bad argument #2 to '?' (number expected, got no value)", setbreakpoint, func) | |
EXPERR("bad argument #3 to '?' (number expected, got no value)", setbreakpoint, func, -999) | |
--EXPERR("bad argument #2 to '?' (index out of range)", setbreakpoint, func, 1e50) | |
local line = tonumber(..., 10) | |
if not line then io.stderr:write(arg[0]..": no argument\n") return end | |
local bc = require("jit.bc") | |
bc.dump(func, nil, true) | |
printf("Setting breakpoint at line %d", line) | |
local ok = setbreakpoint(func, line, 123) | |
printf("Success? %s ", ok and "YES" or "NO") | |
if not ok then | |
return | |
printf("Done.") | |
end | |
printf("NEW DUMP:") | |
bc.dump(func, nil, true) | |
print "Setting the hook..." | |
debug.sethook(function() | |
printf("In the hook!") | |
end, "", 999999999) | |
print("Before call") | |
func() | |
printf("After call") | |
printf("AFTER DUMP:") | |
bc.dump(func, nil, true) | |
printf("Done.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment