xref: /aosp_15_r20/external/bcc/examples/tracing/stacksnoop.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# stacksnoop    Trace a kernel function and print all kernel stack traces.
4*387f9dfdSAndroid Build Coastguard Worker#               For Linux, uses BCC, eBPF, and currently x86_64 only. Inline C.
5*387f9dfdSAndroid Build Coastguard Worker#
6*387f9dfdSAndroid Build Coastguard Worker# USAGE: stacksnoop [-h] [-p PID] [-s] [-v] function
7*387f9dfdSAndroid Build Coastguard Worker#
8*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
9*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
10*387f9dfdSAndroid Build Coastguard Worker#
11*387f9dfdSAndroid Build Coastguard Worker# 12-Jan-2016   Brendan Gregg   Created this.
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
14*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
15*387f9dfdSAndroid Build Coastguard Workerimport argparse
16*387f9dfdSAndroid Build Coastguard Workerimport time
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Worker# arguments
19*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
20*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop ext4_sync_fs           # print kernel stack traces for ext4_sync_fs
21*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop -s ext4_sync_fs        # ... also show symbol offsets
22*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop -v ext4_sync_fs        # ... show extra columns
23*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop -p 185 ext4_sync_fs    # ... only when PID 185 is on-CPU
24*387f9dfdSAndroid Build Coastguard Worker"""
25*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
26*387f9dfdSAndroid Build Coastguard Worker    description="Trace and print kernel stack traces for a kernel function",
27*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
28*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
29*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid",
30*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only")
31*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-s", "--offset", action="store_true",
32*387f9dfdSAndroid Build Coastguard Worker    help="show address offsets")
33*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-v", "--verbose", action="store_true",
34*387f9dfdSAndroid Build Coastguard Worker    help="print more fields")
35*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("function",
36*387f9dfdSAndroid Build Coastguard Worker    help="kernel function name")
37*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
38*387f9dfdSAndroid Build Coastguard Workerfunction = args.function
39*387f9dfdSAndroid Build Coastguard Workeroffset = args.offset
40*387f9dfdSAndroid Build Coastguard Workerverbose = args.verbose
41*387f9dfdSAndroid Build Coastguard Workerdebug = 0
42*387f9dfdSAndroid Build Coastguard Worker
43*387f9dfdSAndroid Build Coastguard Worker# define BPF program
44*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
45*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
46*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
47*387f9dfdSAndroid Build Coastguard Worker
48*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
49*387f9dfdSAndroid Build Coastguard Worker    u64 stack_id;
50*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
51*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN];
52*387f9dfdSAndroid Build Coastguard Worker};
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE(stack_traces, 128);
55*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
56*387f9dfdSAndroid Build Coastguard Worker
57*387f9dfdSAndroid Build Coastguard Workervoid trace_stack(struct pt_regs *ctx) {
58*387f9dfdSAndroid Build Coastguard Worker    u32 pid = bpf_get_current_pid_tgid() >> 32;
59*387f9dfdSAndroid Build Coastguard Worker    FILTER
60*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
61*387f9dfdSAndroid Build Coastguard Worker    data.stack_id = stack_traces.get_stackid(ctx, 0),
62*387f9dfdSAndroid Build Coastguard Worker    data.pid = pid;
63*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&data.comm, sizeof(data.comm));
64*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
65*387f9dfdSAndroid Build Coastguard Worker}
66*387f9dfdSAndroid Build Coastguard Worker"""
67*387f9dfdSAndroid Build Coastguard Workerif args.pid:
68*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER',
69*387f9dfdSAndroid Build Coastguard Worker        'if (pid != %s) { return; }' % args.pid)
70*387f9dfdSAndroid Build Coastguard Workerelse:
71*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER', '')
72*387f9dfdSAndroid Build Coastguard Workerif debug:
73*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
76*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
77*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event=function, fn_name="trace_stack")
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard WorkerTASK_COMM_LEN = 16  # linux/sched.h
80*387f9dfdSAndroid Build Coastguard Worker
81*387f9dfdSAndroid Build Coastguard Workermatched = b.num_open_kprobes()
82*387f9dfdSAndroid Build Coastguard Workerif matched == 0:
83*387f9dfdSAndroid Build Coastguard Worker    print("Function \"%s\" not found. Exiting." % function)
84*387f9dfdSAndroid Build Coastguard Worker    exit()
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Workerstack_traces = b.get_table("stack_traces")
87*387f9dfdSAndroid Build Coastguard Workerstart_ts = time.time()
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Worker# header
90*387f9dfdSAndroid Build Coastguard Workerif verbose:
91*387f9dfdSAndroid Build Coastguard Worker    print("%-18s %-12s %-6s %-3s %s" %
92*387f9dfdSAndroid Build Coastguard Worker            ("TIME(s)", "COMM", "PID", "CPU", "FUNCTION"))
93*387f9dfdSAndroid Build Coastguard Workerelse:
94*387f9dfdSAndroid Build Coastguard Worker    print("%-18s %s" % ("TIME(s)", "FUNCTION"))
95*387f9dfdSAndroid Build Coastguard Worker
96*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
97*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker    ts = time.time() - start_ts
100*387f9dfdSAndroid Build Coastguard Worker
101*387f9dfdSAndroid Build Coastguard Worker    if verbose:
102*387f9dfdSAndroid Build Coastguard Worker        print("%-18.9f %-12.12s %-6d %-3d %s" %
103*387f9dfdSAndroid Build Coastguard Worker              (ts, event.comm.decode('utf-8', 'replace'), event.pid, cpu, function))
104*387f9dfdSAndroid Build Coastguard Worker    else:
105*387f9dfdSAndroid Build Coastguard Worker        print("%-18.9f %s" % (ts, function))
106*387f9dfdSAndroid Build Coastguard Worker
107*387f9dfdSAndroid Build Coastguard Worker    for addr in stack_traces.walk(event.stack_id):
108*387f9dfdSAndroid Build Coastguard Worker        sym = b.ksym(addr, show_offset=offset).decode('utf-8', 'replace')
109*387f9dfdSAndroid Build Coastguard Worker        print("\t%s" % sym)
110*387f9dfdSAndroid Build Coastguard Worker
111*387f9dfdSAndroid Build Coastguard Worker    print()
112*387f9dfdSAndroid Build Coastguard Worker
113*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event)
114*387f9dfdSAndroid Build Coastguard Workerwhile 1:
115*387f9dfdSAndroid Build Coastguard Worker    try:
116*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
117*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
118*387f9dfdSAndroid Build Coastguard Worker        exit()
119