xref: /aosp_15_r20/external/bcc/tools/old/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# The current implementation uses an unrolled loop for x86_64, and was written
9*387f9dfdSAndroid Build Coastguard Worker# as a proof of concept. This implementation should be replaced in the future
10*387f9dfdSAndroid Build Coastguard Worker# with an appropriate bpf_ call, when available.
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# The stack depth is limited to 10 (+1 for the current instruction pointer).
13*387f9dfdSAndroid Build Coastguard Worker# This could be tunable in a future version.
14*387f9dfdSAndroid Build Coastguard Worker#
15*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
16*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
17*387f9dfdSAndroid Build Coastguard Worker#
18*387f9dfdSAndroid Build Coastguard Worker# 12-Jan-2016   Brendan Gregg   Created this.
19*387f9dfdSAndroid Build Coastguard Worker
20*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
21*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
22*387f9dfdSAndroid Build Coastguard Workerimport argparse
23*387f9dfdSAndroid Build Coastguard Worker
24*387f9dfdSAndroid Build Coastguard Worker# arguments
25*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
26*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop ext4_sync_fs    # print kernel stack traces for ext4_sync_fs
27*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop -s ext4_sync_fs    # ... also show symbol offsets
28*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop -v ext4_sync_fs    # ... show extra columns
29*387f9dfdSAndroid Build Coastguard Worker    ./stacksnoop -p 185 ext4_sync_fs    # ... only when PID 185 is on-CPU
30*387f9dfdSAndroid Build Coastguard Worker"""
31*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
32*387f9dfdSAndroid Build Coastguard Worker    description="Trace and print kernel stack traces for a kernel function",
33*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
34*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
35*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid",
36*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only")
37*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-s", "--offset", action="store_true",
38*387f9dfdSAndroid Build Coastguard Worker    help="show address offsets")
39*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-v", "--verbose", action="store_true",
40*387f9dfdSAndroid Build Coastguard Worker    help="print more fields")
41*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("function",
42*387f9dfdSAndroid Build Coastguard Worker    help="kernel function name")
43*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
44*387f9dfdSAndroid Build Coastguard Workerfunction = args.function
45*387f9dfdSAndroid Build Coastguard Workeroffset = args.offset
46*387f9dfdSAndroid Build Coastguard Workerverbose = args.verbose
47*387f9dfdSAndroid Build Coastguard Workerdebug = 0
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Worker# define BPF program
50*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
51*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
52*387f9dfdSAndroid Build Coastguard Worker
53*387f9dfdSAndroid Build Coastguard Workerstatic int print_frame(u64 *bp, int *depth) {
54*387f9dfdSAndroid Build Coastguard Worker    if (*bp) {
55*387f9dfdSAndroid Build Coastguard Worker        // The following stack walker is x86_64 specific
56*387f9dfdSAndroid Build Coastguard Worker        u64 ret = 0;
57*387f9dfdSAndroid Build Coastguard Worker        if (bpf_probe_read(&ret, sizeof(ret), (void *)(*bp+8)))
58*387f9dfdSAndroid Build Coastguard Worker            return 0;
59*387f9dfdSAndroid Build Coastguard Worker        if (ret < __START_KERNEL_map)
60*387f9dfdSAndroid Build Coastguard Worker            return 0;
61*387f9dfdSAndroid Build Coastguard Worker        bpf_trace_printk("r%d: %llx\\n", *depth, ret);
62*387f9dfdSAndroid Build Coastguard Worker        if (bpf_probe_read(bp, sizeof(*bp), (void *)*bp))
63*387f9dfdSAndroid Build Coastguard Worker            return 0;
64*387f9dfdSAndroid Build Coastguard Worker        *depth += 1;
65*387f9dfdSAndroid Build Coastguard Worker        return 1;
66*387f9dfdSAndroid Build Coastguard Worker    }
67*387f9dfdSAndroid Build Coastguard Worker    return 0;
68*387f9dfdSAndroid Build Coastguard Worker}
69*387f9dfdSAndroid Build Coastguard Worker
70*387f9dfdSAndroid Build Coastguard Workervoid trace_stack(struct pt_regs *ctx) {
71*387f9dfdSAndroid Build Coastguard Worker    FILTER
72*387f9dfdSAndroid Build Coastguard Worker    u64 bp = 0;
73*387f9dfdSAndroid Build Coastguard Worker    int depth = 0;
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker    bpf_trace_printk("\\n");
76*387f9dfdSAndroid Build Coastguard Worker    if (ctx->ip)
77*387f9dfdSAndroid Build Coastguard Worker        bpf_trace_printk("ip: %llx\\n", ctx->ip);
78*387f9dfdSAndroid Build Coastguard Worker    bp = ctx->bp;
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard Worker    // unrolled loop, 10 frames deep:
81*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
82*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
83*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
84*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
85*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
86*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
87*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
88*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
89*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
90*387f9dfdSAndroid Build Coastguard Worker    if (!print_frame(&bp, &depth)) return;
91*387f9dfdSAndroid Build Coastguard Worker};
92*387f9dfdSAndroid Build Coastguard Worker"""
93*387f9dfdSAndroid Build Coastguard Workerif args.pid:
94*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER',
95*387f9dfdSAndroid Build Coastguard Worker        ('u32 pid; pid = bpf_get_current_pid_tgid(); ' +
96*387f9dfdSAndroid Build Coastguard Worker        'if (pid != %s) { return; }') % (args.pid))
97*387f9dfdSAndroid Build Coastguard Workerelse:
98*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER', '')
99*387f9dfdSAndroid Build Coastguard Workerif debug:
100*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
101*387f9dfdSAndroid Build Coastguard Worker
102*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
103*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
104*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event=function, fn_name="trace_stack")
105*387f9dfdSAndroid Build Coastguard Workermatched = b.num_open_kprobes()
106*387f9dfdSAndroid Build Coastguard Workerif matched == 0:
107*387f9dfdSAndroid Build Coastguard Worker    print("Function \"%s\" not found. Exiting." % function)
108*387f9dfdSAndroid Build Coastguard Worker    exit()
109*387f9dfdSAndroid Build Coastguard Worker
110*387f9dfdSAndroid Build Coastguard Worker# header
111*387f9dfdSAndroid Build Coastguard Workerif verbose:
112*387f9dfdSAndroid Build Coastguard Worker    print("%-18s %-12s %-6s %-3s %s" % ("TIME(s)", "COMM", "PID", "CPU",
113*387f9dfdSAndroid Build Coastguard Worker        "STACK"))
114*387f9dfdSAndroid Build Coastguard Workerelse:
115*387f9dfdSAndroid Build Coastguard Worker    print("%-18s %s" % ("TIME(s)", "STACK"))
116*387f9dfdSAndroid Build Coastguard Worker
117*387f9dfdSAndroid Build Coastguard Worker# format output
118*387f9dfdSAndroid Build Coastguard Workerwhile 1:
119*387f9dfdSAndroid Build Coastguard Worker    (task, pid, cpu, flags, ts, msg) = b.trace_fields()
120*387f9dfdSAndroid Build Coastguard Worker    if msg != "":
121*387f9dfdSAndroid Build Coastguard Worker        (reg, addr) = msg.split(" ")
122*387f9dfdSAndroid Build Coastguard Worker        ip = b.ksym(int(addr, 16), show_offset=offset)
123*387f9dfdSAndroid Build Coastguard Worker        msg = msg + " " + ip
124*387f9dfdSAndroid Build Coastguard Worker    if verbose:
125*387f9dfdSAndroid Build Coastguard Worker        print("%-18.9f %-12.12s %-6d %-3d %s" % (ts, task, pid, cpu, msg))
126*387f9dfdSAndroid Build Coastguard Worker    else:
127*387f9dfdSAndroid Build Coastguard Worker        print("%-18.9f %s" % (ts, msg))
128