localfunctionsetbreakpoint(where, line) -- 省略 iftype(where) == "function"then return setfuncbp(where, line) else-- "string" local i = string.find(where, ":") if i then-- package name local packname = string.sub(where, 1, i-1) local line = string.sub(where, i+1) if packname == ""then io.write("no package name specified!\n") returnnil end if line ~= ""then line = tonumber(line) ifnot line then io.write("no valid line number specified!\n") returnnil end else line = -1 end localpath, err = package.searchpath(packname, package.path) ifnotpaththen io.write(err) returnnil end return setsrcbp(path, line) else end
localfunctionsetbreakpoint(where, line) -- 省略 else local i = string.find(where, "@") if i then-- function name local funcname = string.sub(where, 1, i-1) local line = string.sub(where, i+1) if funcname == ""then io.write("no function name specified!\n") returnnil end if line ~= ""then line = tonumber(line) ifnot line then io.write("no valid line number specified!\n") returnnil end else line = nil end return setnamebp(funcname, line) end end end end
localfunctionhook(event, line) local s = status if event == "call"or event == "tail call"then local stackinfo = debug.getinfo(2, "nf") local func = stackinfo.func local name = stackinfo.name local funcinfo = getfuncinfo(func) local hasbreak = false -- 处理通过包名添加的还未转换的断点 solvesrcbp(funcinfo, func)
if funcinfo.what ~= "C"then setsrcfunc(funcinfo, func) end
if s.funcbpt[func] then local id = s.funcbpt[func] if s.bptable[id] andnot s.bptable[id].src then s.bptable[id].src = funcinfo.short_src end hasbreak = true end -- 省略 end
localfunctionsolvesrcbp(info, func) local s = status local srcbp = s.srcbpt[info.short_src] if srcbp then for k, v inpairs(srcbp) do if k ~= "num"then line = verifyfuncline(info, k) if line then modsrcbp(info.short_src, func, k, line) end end end end end
localfunctionverifyfuncline(info, line) ifnot line then return info.sortedlines[1] end if line < 0then if info.what ~= "main"then returnnil end line = -line end if line < info.linedefined or line > info.lastlinedefined then returnnil end for _, v inipairs(info.sortedlines) do if v >= line then return v end end assert(false) -- impossible to reach here end
localfunctiongetfuncinfo(func) local s = status local info = s.funcinfos[func] ifnot info then info = debug.getinfo(func, "SL") if (info.activelines) then info.sortedlines = {} for k, _ inpairs(info.activelines) do table.insert(info.sortedlines, k) end table.sort(info.sortedlines) -- mainchunk需要特殊处理以使`verifyfuncline`能够正常工作 if info.what == "main"then info.linedefined = 1 info.lastlinedefined = info.sortedlines[#info.sortedlines] end end s.funcinfos[func] = info end return info end
localfunctionsetsrcfunc(info, func) local s = status local srcfunc = s.srcfuncmap[info.short_src] ifnot srcfunc then srcfunc = {} s.srcfuncmap[info.short_src] = srcfunc end ifnot srcfunc[func] then srcfunc[func] = info end end
localfunctionlookforfunc(src, line) assert(line) local srcfunc = status.srcfuncmap[src] if srcfunc then for func, info inpairs(srcfunc) do if info.what == "main"then if line < 0then return func end elseif line >= info.linedefined and line <= info.lastlinedefined then return func end end end returnnil end
local ldb = require"luadebug" local lib = require"testlib" local setbp = ldb.setbreakpoint local rmbp = ldb.removebreakpoint
local id1 = setbp("foo@") -- foo 2 local id2 = setbp("foo@3") -- foo 3
local id3 = setbp("testlib:5") -- bar 6 local id4 = setbp("testlib:7") -- bar 7 local id5 = setbp("testlib:100") -- invalid line local id6 = setbp(":5") assert(not id6) local id7 = setbp("testlib:aa") assert(not id7)
local ldb = require"luadebug" local setbp = ldb.setbreakpoint local rmbp = ldb.removebreakpoint
local id1 = setbp("testlib:") -- main 3 local id2 = setbp("testlib:-5") -- main 7 local id3 = setbp("testlib:-9") -- main 9 local id4 = setbp("testlib:-13") -- main 13
local lib = require"testlib"-- break 4 times
local id5 = setbp("testlib:2") -- foo 2 local id6 = setbp("testlib:3") -- foo 3
lib.foo() -- break 2 times
rmbp(id5)
lib.foo() -- break 1 time
rmbp(id6)
lib.foo() -- not break
运行测试脚本,首先碰到了mainchunk中的4个断点
1 2 3 4 5 6 7 8 9
lua mainchunk.lua main ()nil /usr/local/share/lua/5.3/testlib.lua:3 lua_debug> cont main ()nil /usr/local/share/lua/5.3/testlib.lua:7 lua_debug> cont main ()nil /usr/local/share/lua/5.3/testlib.lua:9 lua_debug> cont main ()nil /usr/local/share/lua/5.3/testlib.lua:13 lua_debug>