On Tue, Jul 04, 2017 at 01:25:23PM +0300, Victor Krapivensky wrote: [...] > diff --git a/luajit_lib.h b/luajit_lib.h > new file mode 100644 > index 00000000..16e49610 > --- /dev/null > +++ b/luajit_lib.h > @@ -0,0 +1,260 @@ > +"do\n\ > + local ffi = require(strace._ffilibname)\n\ > + local bit = require(strace._bitlibname)\n\ > + strace._en, strace._ex = {}, {}\n\ > + for p = 0, strace.npersonalities - 1 do\n\ > + strace._en[p] = {}\n\ > + strace._ex[p] = {}\n\ > + end\n\ > + local function chain(f, g)\n\ > + if not f then return g end\n\ > + return function(...)\n\ > + f(...)\n\ > + g(...)\n\ > + end\n\ > + end\n\ > + function strace.entering(tcp)\n\ > + return bit.band(tcp.flags, strace._tcbflg.insyscall) == 0\n\ > + end\n\ > + function strace.exiting(tcp)\n\ > + return bit.band(tcp.flags, strace._tcbflg.insyscall) ~= 0\n\ > + end\n\ > +\n\ > + -- `arg' defaults to true.\n\ > + local function alter_trace_opt(flagbit, tcp, arg)\n\ > + if strace.exiting(tcp) then\n\ > + error('altering tracing options must be done on syscall > entering')\n\ > + end\n\ > + -- we want to support custom boolean-like objects, so check for > nil explicitly\n\ > + if type(arg) == 'nil' or arg then\n\ > + tcp.qual_flg = bit.bor(tcp.qual_flg, flagbit)\n\ > + else\n\ > + tcp.qual_flg = bit.band(tcp.qual_flg, > bit.bnot(flagbit))\n\ > + end\n\ > + end\n\ > + function strace.trace (tcp, arg) > alter_trace_opt(strace._qualflg.trace, tcp, arg) end\n\ > + function strace.abbrev (tcp, arg) > alter_trace_opt(strace._qualflg.abbrev, tcp, arg) end\n\ > + function strace.verbose(tcp, arg) > alter_trace_opt(strace._qualflg.verbose, tcp, arg) end\n\ > + function strace.raw (tcp, arg) alter_trace_opt(strace._qualflg.raw, > tcp, arg) end\n\ > +\n\ > + function strace.ptr_to_kulong(ptr)\n\ > + return ffi.cast('kernel_ulong_t', ffi.cast('unsigned long', > ptr))\n\ > + end\n\ > + function strace.at_exit(f)\n\ > + strace._at_exit = chain(strace._at_exit, f)\n\ > + end\n\ > + function strace.get_err_name(err, pers)\n\ > + pers = pers or 0\n\ > + if err < 0 or err > strace.nerrnoent_vec[pers] then\n\ > + return nil\n\ > + end\n\ > + local s = strace.errnoent_vec[pers][err]\n\ > + if s ~= nil then\n\ > + return ffi.string(s)\n\ > + end\n\ > + return nil\n\ > + end\n\ > + function strace.get_sc_name(scno, pers)\n\ > + pers = pers or 0\n\ > + if scno < 0 or scno >= strace.nsysent_vec[pers] then\n\ > + return nil\n\ > + end\n\ > + local s = strace.sysent_vec[pers][scno].sys_name\n\ > + if s ~= nil then\n\ > + return ffi.string(s)\n\ > + end\n\ > + return nil\n\ > + end\n\ > + function strace.get_ioctl_name(code, pers)\n\ > + pers = pers or 0\n\ > + -- we could have provided a definition for stdlib's bsearch() > and used it, but LuaJIT's FFI manual\n\ > + -- says generated callbacks are a limited resource and also > slow. So implement binary search ourselves.\n\ > + local lb, rb = ffi.cast('unsigned int', 0), > strace.nioctlent_vec[pers]\n\ > + if rb == 0 then\n\ > + return nil\n\ > + end\n\ > + local arr = strace.ioctlent_vec[pers]\n\ > + while rb - lb > 1 do\n\ > + local mid = lb + (rb - lb) / 2\n\ > + if arr[mid].code <= code then\n\ > + lb = mid\n\ > + else\n\ > + rb = mid\n\ > + end\n\ > + end\n\ > + if arr[lb].code == code then\n\ > + return ffi.string(arr[lb].symbol)\n\ > + end\n\ > + return nil\n\ > + end\n\ > + function strace.get_scno(scname, pers)\n\ > + pers = pers or 0\n\ > + for i = 0, tonumber(strace.nsysent_vec[pers]) - 1 do\n\ > + local s = strace.sysent_vec[pers][i].sys_name\n\ > + if s ~= nil and ffi.string(s) == scname then\n\ > + return i\n\ > + end\n\ > + end\n\ > + return nil\n\ > + end\n\ > + function strace.get_signo(signame, pers)\n\ > + pers = pers or 0\n\ > + for i = 0, tonumber(strace.nsignalent_vec[pers]) - 1 do\n\ > + local s = strace.signalent_vec[pers][i]\n\ > + if s ~= nil and ffi.string(s) == signame then\n\ > + return i\n\ > + end\n\ > + end\n\ > + return nil\n\ > + end\n\ > + function strace.get_errno(errname, pers)\n\ > + pers = pers or 0\n\ > + for i = 0, tonumber(strace.nerrnoent_vec[pers]) - 1 do\n\ > + local s = strace.errnoent_vec[pers][i]\n\ > + if s ~= nil and ffi.string(s) == errname then\n\ > + return i\n\ > + end\n\ > + end\n\ > + return nil\n\ > + end\n\ > + function strace.inject_signal(tcp, sig)\n\ > + if type(sig) == 'string' then\n\ > + sig = strace.get_signo(sig, tcp.currpers)\n\ > + if not sig then\n\ > + error('signal not found')\n\ > + end\n\ > + end\n\ > + if not strace.inject_signo(tcp, sig) then\n\ > + error('cannot inject signal')\n\ > + end\n\ > + end\n\ > + function strace.inject_error(tcp, err)\n\ > + if type(err) == 'string' then\n\ > + err = strace.get_errno(err, tcp.currpers)\n\ > + if not err then\n\ > + error('error not found')\n\ > + end\n\ > + end\n\ > + if err <= 0 then\n\ > + error('err must be positive')\n\ > + end\n\ > + if not strace.inject_retval(tcp, -err) then\n\ > + error('cannot inject error')\n\ > + end\n\ > + end\n\ > + function strace.read_obj(tcp, addr, ct, ...)\n\ > + local obj = ffi.new(ct, ...)\n\ > + return strace.umoven(tcp, addr, ffi.sizeof(obj, ...), obj) == 0 > and obj or nil\n\ > + end\n\ > + function strace.read_str(tcp, addr, maxsz, bufsz)\n\ > + maxsz = maxsz or 4 * 1024 * 1024\n\ > + bufsz = bufsz or 1024\n\ > + local t = {}\n\ > + local buf = ffi.new('char[?]', bufsz)\n\ > + while true do\n\ > + local r = strace.umovestr(tcp, addr, bufsz, buf)\n\ > + if r < 0 then\n\ > + return nil\n\ > + elseif r == 0 then\n\ > + maxsz = maxsz - bufsz\n\ > + if maxsz < 0 then return nil end\n\ > + t[#t + 1] = ffi.string(buf, bufsz)\n\ > + addr = addr + bufsz\n\ > + else\n\ > + local s = ffi.string(buf)\n\ > + if #s > maxsz then return nil end\n\ > + return table.concat(t) .. s\n\ > + end\n\ > + end\n\ > + end\n\ > + function strace.read_path(tcp, addr)\n\ > + return strace.read_str(tcp, addr, strace.path_max, > strace.path_max)\n\ > + end\n\ > + local function register_hook(scno, pers, en, ex, cb)\n\ > + assert(not not strace.monitor(scno, pers, en, ex))\n\ > + pers = tonumber(pers)\n\ > + scno = tonumber(scno)\n\ > + if en then\n\ > + strace._en[pers][scno] = chain(strace._en[pers][scno], > cb)\n\ > + end\n\ > + if ex then\n\ > + strace._ex[pers][scno] = chain(strace._ex[pers][scno], > cb)\n\ > + end\n\ > + end\n\ > + local function parse_when(when)\n\ > + if when == 'entering' then\n\ > + return true, false\n\ > + elseif when == 'exiting' then\n\ > + return false, true\n\ > + elseif when == 'both' then\n\ > + return true, true\n\ > + else\n\ > + error('unknown \"when\" value')\n\ > + end\n\ > + end\n\ > + function strace.monitor_all()\n\ > + for p = 0, strace.npersonalities - 1 do\n\ > + for i = 0, tonumber(strace.nsysent_vec[p]) - 1 do\n\ > + strace.monitor(i, p, true, true)\n\ > + end\n\ > + end\n\ > + end\n\ > + function strace.hook(scname, when, cb)\n\ > + local en, ex = parse_when(when)\n\ > + local found = false\n\ > + for p = 0, strace.npersonalities - 1 do\n\ > + local scno = strace.get_scno(scname, p)\n\ > + if scno then\n\ > + register_hook(scno, p, en, ex, cb)\n\ > + found = true\n\ > + end\n\ > + end\n\ > + if not found then\n\ > + error('syscall not found')\n\ > + end\n\ > + end\n\ > + function strace.hook_class(clsname, when, cb)\n\ > + local en, ex = parse_when(when)\n\ > + local flag = nil\n\ > + local ptr = strace.syscall_classes\n\ > + while ptr.name ~= nil do\n\ > + if ffi.string(ptr.name) == clsname then\n\ > + flag = ptr.value\n\ > + break\n\ > + end\n\ > + ptr = ptr + 1\n\ > + end\n\ > + if not flag then\n\ > + error('syscall class not found')\n\ > + end\n\ > + for p = 0, strace.npersonalities - 1 do\n\ > + for i = 0, tonumber(strace.nsysent_vec[p]) - 1 do\n\ > + if bit.band(strace.sysent_vec[p][i].sys_flags, > flag) ~= 0 then\n\ > + register_hook(i, p, en, ex, cb)\n\ > + end\n\ > + end\n\ > + end\n\ > + end\n\ > + function strace.hook_scno(scno, when, cb, pers)\n\ > + pers = pers or 0\n\ > + local en, ex = parse_when(when)\n\ > + reigster_hook(scno, pers, en, ex, cb)\n\ > + end\n\ > + function strace._run()\n\ > + while true do\n\ > + local tcp = strace.next_sc()\n\ > + if tcp == nil then break end\n\ > + local cb = (strace.entering(tcp) and strace._en or > strace._ex)[tonumber(tcp.currpers)][tonumber(tcp.scno)]\n\ > + if cb then cb(tcp) end\n\ > + end\n\ > + if strace._at_exit then strace._at_exit() end\n\ > + end\n\ > + function print(...)\n\ > + local sep = ''\n\ > + for i = 1, select('#', ...) do\n\ > + io.stderr:write(sep .. tostring(select(i, ...)))\n\ > + sep = '\\t'\n\ > + end\n\ > + io.stderr:write('\\n')\n\ > + end\n\ > +end"
This longish C string is actually a lua script, and it doesn't look nice in this form. Wouldn't it be better if this script was translated into a C string automatically by some Makefile rule? -- ldv
signature.asc
Description: PGP signature
------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel