xref: /aosp_15_r20/external/bcc/tools/stacksnoop.lua (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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