1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env bcc-lua 2*387f9dfdSAndroid Build Coastguard Worker--[[ 3*387f9dfdSAndroid Build Coastguard WorkerCopyright 2016 GitHub, Inc 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 18*387f9dfdSAndroid Build Coastguard Workerlocal program = [[ 19*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 20*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Workerstruct data_t { 23*387f9dfdSAndroid Build Coastguard Worker u64 stack_id; 24*387f9dfdSAndroid Build Coastguard Worker u32 pid; 25*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 26*387f9dfdSAndroid Build Coastguard Worker}; 27*387f9dfdSAndroid Build Coastguard Worker 28*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE(stack_traces, 128); 29*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 30*387f9dfdSAndroid Build Coastguard Worker 31*387f9dfdSAndroid Build Coastguard Workervoid trace_stack(struct pt_regs *ctx) { 32*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 33*387f9dfdSAndroid Build Coastguard Worker FILTER 34*387f9dfdSAndroid Build Coastguard Worker struct data_t data = {}; 35*387f9dfdSAndroid Build Coastguard Worker data.stack_id = stack_traces.get_stackid(ctx, 0), 36*387f9dfdSAndroid Build Coastguard Worker data.pid = pid; 37*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&data.comm, sizeof(data.comm)); 38*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 39*387f9dfdSAndroid Build Coastguard Worker} 40*387f9dfdSAndroid Build Coastguard Worker]] 41*387f9dfdSAndroid Build Coastguard Worker 42*387f9dfdSAndroid Build Coastguard Workerlocal ffi = require("ffi") 43*387f9dfdSAndroid Build Coastguard Worker 44*387f9dfdSAndroid Build Coastguard Workerreturn function(BPF, utils) 45*387f9dfdSAndroid Build Coastguard Worker local parser = utils.argparse("stacksnoop", 46*387f9dfdSAndroid Build Coastguard Worker "Trace and print kernel stack traces for a kernel function") 47*387f9dfdSAndroid Build Coastguard Worker parser:flag("-s --offset") 48*387f9dfdSAndroid Build Coastguard Worker parser:flag("-v --verbose") 49*387f9dfdSAndroid Build Coastguard Worker parser:option("-p --pid"):convert(tonumber) 50*387f9dfdSAndroid Build Coastguard Worker parser:argument("function", "kernel function name"):target("fn") 51*387f9dfdSAndroid Build Coastguard Worker 52*387f9dfdSAndroid Build Coastguard Worker local args = parser:parse() 53*387f9dfdSAndroid Build Coastguard Worker local ksym = BPF.SymbolCache() 54*387f9dfdSAndroid Build Coastguard Worker local filter = "" 55*387f9dfdSAndroid Build Coastguard Worker 56*387f9dfdSAndroid Build Coastguard Worker if args.pid then 57*387f9dfdSAndroid Build Coastguard Worker filter = "if (pid != %d) { return; }" % args.pid 58*387f9dfdSAndroid Build Coastguard Worker end 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard Worker local text = program:gsub("FILTER", filter) 61*387f9dfdSAndroid Build Coastguard Worker local bpf = BPF:new{text=text} 62*387f9dfdSAndroid Build Coastguard Worker bpf:attach_kprobe{event=args.fn, fn_name="trace_stack"} 63*387f9dfdSAndroid Build Coastguard Worker 64*387f9dfdSAndroid Build Coastguard Worker if BPF.num_open_kprobes() == 0 then 65*387f9dfdSAndroid Build Coastguard Worker print("Function \"%s\" not found. Exiting." % {args.fn}) 66*387f9dfdSAndroid Build Coastguard Worker return 67*387f9dfdSAndroid Build Coastguard Worker end 68*387f9dfdSAndroid Build Coastguard Worker 69*387f9dfdSAndroid Build Coastguard Worker if args.verbose then 70*387f9dfdSAndroid Build Coastguard Worker print("%-18s %-12s %-6s %-3s %s" % 71*387f9dfdSAndroid Build Coastguard Worker {"TIME(s)", "COMM", "PID", "CPU", "FUNCTION"}) 72*387f9dfdSAndroid Build Coastguard Worker else 73*387f9dfdSAndroid Build Coastguard Worker print("%-18s %s" % {"TIME(s)", "FUNCTION"}) 74*387f9dfdSAndroid Build Coastguard Worker end 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker local stack_traces = bpf:get_table("stack_traces") 77*387f9dfdSAndroid Build Coastguard Worker local start_ts = utils.posix.time_ns() 78*387f9dfdSAndroid Build Coastguard Worker 79*387f9dfdSAndroid Build Coastguard Worker local function print_event(cpu, event) 80*387f9dfdSAndroid Build Coastguard Worker local ts = (utils.posix.time_ns() - start_ts) / 1e9 81*387f9dfdSAndroid Build Coastguard Worker 82*387f9dfdSAndroid Build Coastguard Worker if args.verbose then 83*387f9dfdSAndroid Build Coastguard Worker print("%-18.9f %-12.12s %-6d %-3d %s" % 84*387f9dfdSAndroid Build Coastguard Worker {ts, ffi.string(event.comm), event.pid, cpu, args.fn}) 85*387f9dfdSAndroid Build Coastguard Worker else 86*387f9dfdSAndroid Build Coastguard Worker print("%-18.9f %s" % {ts, args.fn}) 87*387f9dfdSAndroid Build Coastguard Worker end 88*387f9dfdSAndroid Build Coastguard Worker 89*387f9dfdSAndroid Build Coastguard Worker for addr in stack_traces:walk(tonumber(event.stack_id)) do 90*387f9dfdSAndroid Build Coastguard Worker local sym, offset = ksym:resolve(addr) 91*387f9dfdSAndroid Build Coastguard Worker if args.offset then 92*387f9dfdSAndroid Build Coastguard Worker print("\t%-16p %s+0x%x" % {addr, sym, tonumber(offset)}) 93*387f9dfdSAndroid Build Coastguard Worker else 94*387f9dfdSAndroid Build Coastguard Worker print("\t%-16p %s" % {addr, sym}) 95*387f9dfdSAndroid Build Coastguard Worker end 96*387f9dfdSAndroid Build Coastguard Worker end 97*387f9dfdSAndroid Build Coastguard Worker 98*387f9dfdSAndroid Build Coastguard Worker print() 99*387f9dfdSAndroid Build Coastguard Worker end 100*387f9dfdSAndroid Build Coastguard Worker 101*387f9dfdSAndroid Build Coastguard Worker local TASK_COMM_LEN = 16 -- linux/sched.h 102*387f9dfdSAndroid Build Coastguard Worker 103*387f9dfdSAndroid Build Coastguard Worker bpf:get_table("events"):open_perf_buffer(print_event, 104*387f9dfdSAndroid Build Coastguard Worker "struct { uint64_t stack_id; uint32_t pid; char comm[$]; }", 105*387f9dfdSAndroid Build Coastguard Worker {TASK_COMM_LEN}) 106*387f9dfdSAndroid Build Coastguard Worker bpf:perf_buffer_poll_loop() 107*387f9dfdSAndroid Build Coastguard Workerend 108