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

Attachment: 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

Reply via email to