在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
inject d test/inject_fuck.lua -- d 是服务的 handle
拿 simpledb.lua 举例,修改如下 1 local skynet = require "skynet" 2 require "skynet.manager" -- import skynet.register 3 local db = {} 4 5 local command = {} 6 7 local i = 13 8 local str = "abc" 9 local t = {} 10 11 function command.fuck() 12 return i, str, t 13 end 14 15 skynet.info_func(function() 16 return command.fuck() 17 end) 18 19 function command.GET(key) 20 return db[key] 21 end 22 23 function command.SET(key, value) 24 local last = db[key] 25 db[key] = value 26 return last 27 end 28 29 skynet.start(function() 30 skynet.dispatch("lua", function(session, address, cmd, ...) 31 local f = command[string.upper(cmd)] 32 if f then 33 skynet.ret(skynet.pack(f(...))) 34 else 35 error(string.format("Unknown command %s", tostring(cmd))) 36 end 37 end) 38 skynet.register "SIMPLEDB" 39 end) 添加了 fuck 函数,并设置 info_func。 设置 info_func 主要用来在 debug console 中方便用 info d 来查看 inject 的结果
下面是 inject_fuck.lua 1 if not _P then 2 print "inject error!" 3 return 4 end 5 6 local function getuv(f) 7 local i = 1 8 local ups = {} 9 while true do 10 local name, value = debug.getupvalue(f, i) 11 if not name then 12 break 13 end 14 ups[name] = { i, value } 15 i = i + 1 16 end 17 return ups 18 end 19 20 local function uvjoin(f, old_f, old_uv) 21 local i = 1 22 while true do 23 local name, value = debug.getupvalue(f, i) 24 if not name then 25 break 26 end 27 if old_uv[name] then 28 debug.upvaluejoin(f, i, old_f, old_uv[name][1]) 29 end 30 i = i + 1 31 end 32 end 33 34 35 local command = _P.lua.command 36 37 local func = command.fuck 38 local old_uv = getuv(func) 39 for k,v in pairs(old_uv) do 40 print(k,v[2]) 41 end 42 43 print(" --- ") 44 45 local t 46 local i 47 local str 48 function command.fuck() 49 return str, t, i 50 end 51 52 uvjoin(command.fuck, func, old_uv) 53 -- debug.setupvalue( command.fuck, 1, 35 ) 1. 取出原 fuck 函数的所有 upvalue 2. 然后关联到新的 fuck 函数
_P 内存的 key/value 其实就是 skynet.lua 里 14 行 proto 中的 name 和 dispatch 的 upvalue 1 local c = require "skynet.core" 2 local tostring = tostring 3 local tonumber = tonumber 4 local coroutine = coroutine 5 local assert = assert 6 local pairs = pairs 7 local pcall = pcall 8 9 local profile = require "profile" 10 11 local coroutine_resume = profile.resume 12 local coroutine_yield = profile.yield 13 14 local proto = {} 15 local skynet = { 16 -- read skynet.h 17 PTYPE_TEXT = 0, 18 PTYPE_RESPONSE = 1, 19 PTYPE_MULTICAST = 2, 20 PTYPE_CLIENT = 3, 21 PTYPE_SYSTEM = 4, 22 PTYPE_HARBOR = 5, 23 PTYPE_SOCKET = 6, 24 PTYPE_ERROR = 7, 25 PTYPE_QUEUE = 8, -- used in deprecated mqueue, use skynet.queue instead 26 PTYPE_DEBUG = 9, 27 PTYPE_LUA = 10, 28 PTYPE_SNAX = 11, 29 } 30 31 ---
再看 simpledb.lua 的例子,文件中 disptch 的 upvalue 有两个,command 和 skynet 所以 _P.lua.command 就是文件中的 command,_P.lua.skynet 就是 skynet
在 debug console 用 inject 命令时要格外小心。。
|
请发表评论