1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env bcc-lua 2*387f9dfdSAndroid Build Coastguard Worker--[[ 3*387f9dfdSAndroid Build Coastguard WorkerCopyright 2016 Marek Vavrusa <[email protected]> 4*387f9dfdSAndroid Build Coastguard Worker 5*387f9dfdSAndroid Build Coastguard WorkerLicensed under the Apache License, Version 2.0 (the "License"); 6*387f9dfdSAndroid Build Coastguard Workeryou may not use this file except in compliance with the License. 7*387f9dfdSAndroid Build Coastguard WorkerYou may obtain a copy of the License at 8*387f9dfdSAndroid Build Coastguard Worker 9*387f9dfdSAndroid Build Coastguard Workerhttp://www.apache.org/licenses/LICENSE-2.0 10*387f9dfdSAndroid Build Coastguard Worker 11*387f9dfdSAndroid Build Coastguard WorkerUnless required by applicable law or agreed to in writing, software 12*387f9dfdSAndroid Build Coastguard Workerdistributed under the License is distributed on an "AS IS" BASIS, 13*387f9dfdSAndroid Build Coastguard WorkerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*387f9dfdSAndroid Build Coastguard WorkerSee the License for the specific language governing permissions and 15*387f9dfdSAndroid Build Coastguard Workerlimitations under the License. 16*387f9dfdSAndroid Build Coastguard Worker]] 17*387f9dfdSAndroid Build Coastguard Worker-- Trace operations on keys matching given pattern in KyotoTycoon daemon. 18*387f9dfdSAndroid Build Coastguard Worker-- This can show you if certain keys were modified or read during the lifetime 19*387f9dfdSAndroid Build Coastguard Worker-- even if KT doesn't support this. It also shows how to attach to C++ mangled symbols. 20*387f9dfdSAndroid Build Coastguard Workerlocal ffi = require('ffi') 21*387f9dfdSAndroid Build Coastguard Workerlocal bpf = require('bpf') 22*387f9dfdSAndroid Build Coastguard Workerlocal S = require('syscall') 23*387f9dfdSAndroid Build Coastguard Workerlocal function help(err) 24*387f9dfdSAndroid Build Coastguard Worker print(string.format('%s [get|set] [key]', arg[0])) 25*387f9dfdSAndroid Build Coastguard Worker if err then print('error: '..err) end 26*387f9dfdSAndroid Build Coastguard Worker os.exit(1) 27*387f9dfdSAndroid Build Coastguard Workerend 28*387f9dfdSAndroid Build Coastguard Worker-- Accept the same format as ktremotemgr for clarity: <get|set> <key> 29*387f9dfdSAndroid Build Coastguard Workerlocal writeable, watch_key, klen = 'any', arg[2] or '*', 80 30*387f9dfdSAndroid Build Coastguard Workerif arg[1] == 'get' then writeable = 0 31*387f9dfdSAndroid Build Coastguard Workerelseif arg[1] == 'set' then writeable = 1 32*387f9dfdSAndroid Build Coastguard Workerelseif arg[1] == '-h' or arg[1] == '--help' then help() 33*387f9dfdSAndroid Build Coastguard Workerelseif arg[1] and arg[1] ~= 'any' then 34*387f9dfdSAndroid Build Coastguard Worker help(string.format('bad cmd: "%s"', arg[1])) 35*387f9dfdSAndroid Build Coastguard Workerend 36*387f9dfdSAndroid Build Coastguard Workerif watch_key ~= '*' then klen = #watch_key end 37*387f9dfdSAndroid Build Coastguard Worker 38*387f9dfdSAndroid Build Coastguard Worker-- Find a good entrypoint that has both key and differentiates read/write in KT 39*387f9dfdSAndroid Build Coastguard Worker-- That is going to serve as an attachment point for BPF program 40*387f9dfdSAndroid Build Coastguard Worker-- ABI: bool accept(void *this, const char* kbuf, size_t ksiz, Visitor* visitor, bool writable) 41*387f9dfdSAndroid Build Coastguard Workerlocal key_type = string.format('char [%d]', klen) 42*387f9dfdSAndroid Build Coastguard Workerlocal probe = bpf.uprobe('/usr/local/bin/ktserver:kyotocabinet::StashDB::accept', 43*387f9dfdSAndroid Build Coastguard Workerfunction (ptregs) 44*387f9dfdSAndroid Build Coastguard Worker -- Watch either get/set or both 45*387f9dfdSAndroid Build Coastguard Worker if writeable ~= 'any' then 46*387f9dfdSAndroid Build Coastguard Worker if ptregs.parm5 ~= writeable then return end 47*387f9dfdSAndroid Build Coastguard Worker end 48*387f9dfdSAndroid Build Coastguard Worker local line = ffi.new(key_type) 49*387f9dfdSAndroid Build Coastguard Worker ffi.copy(line, ffi.cast('char *', ptregs.parm2)) 50*387f9dfdSAndroid Build Coastguard Worker -- Check if we're looking for specific key 51*387f9dfdSAndroid Build Coastguard Worker if watch_key ~= '*' then 52*387f9dfdSAndroid Build Coastguard Worker if ptregs.parm3 ~= klen then return false end 53*387f9dfdSAndroid Build Coastguard Worker if line ~= watch_key then return false end 54*387f9dfdSAndroid Build Coastguard Worker end 55*387f9dfdSAndroid Build Coastguard Worker print('%s write:%d\n', line, ptregs.parm5) 56*387f9dfdSAndroid Build Coastguard Workerend, false, -1, 0) 57*387f9dfdSAndroid Build Coastguard Worker-- User-space part of the program 58*387f9dfdSAndroid Build Coastguard Workerlocal ok, err = pcall(function() 59*387f9dfdSAndroid Build Coastguard Worker local log = bpf.tracelog() 60*387f9dfdSAndroid Build Coastguard Worker print(' TASK-PID CPU# TIMESTAMP FUNCTION') 61*387f9dfdSAndroid Build Coastguard Worker print(' | | | | |') 62*387f9dfdSAndroid Build Coastguard Worker while true do 63*387f9dfdSAndroid Build Coastguard Worker print(log:read()) 64*387f9dfdSAndroid Build Coastguard Worker end 65*387f9dfdSAndroid Build Coastguard Workerend) 66