xref: /aosp_15_r20/external/bcc/tools/killsnoop.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# killsnoop Trace signals issued by the kill() syscall.
5*387f9dfdSAndroid Build Coastguard Worker#           For Linux, uses BCC, eBPF. Embedded C.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: killsnoop [-h] [-x] [-p PID] [-T PID] [-s SIGNAL]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg.
10*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# 20-Sep-2015   Brendan Gregg   Created this.
13*387f9dfdSAndroid Build Coastguard Worker# 19-Feb-2016   Allan McAleavy migrated to BPF_PERF_OUTPUT
14*387f9dfdSAndroid Build Coastguard Worker
15*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
16*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
17*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import ArgString, printb
18*387f9dfdSAndroid Build Coastguard Workerimport argparse
19*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Worker# arguments
22*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
23*387f9dfdSAndroid Build Coastguard Worker    ./killsnoop           # trace all kill() signals
24*387f9dfdSAndroid Build Coastguard Worker    ./killsnoop -x        # only show failed kills
25*387f9dfdSAndroid Build Coastguard Worker    ./killsnoop -p 181    # only trace PID 181
26*387f9dfdSAndroid Build Coastguard Worker    ./killsnoop -T 189    # only trace target PID 189
27*387f9dfdSAndroid Build Coastguard Worker    ./killsnoop -s 9      # only trace signal 9
28*387f9dfdSAndroid Build Coastguard Worker"""
29*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
30*387f9dfdSAndroid Build Coastguard Worker    description="Trace signals issued by the kill() syscall",
31*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
32*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
33*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-x", "--failed", action="store_true",
34*387f9dfdSAndroid Build Coastguard Worker    help="only show failed kill syscalls")
35*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid",
36*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only which is the sender of signal")
37*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--tpid",
38*387f9dfdSAndroid Build Coastguard Worker    help="trace this target PID only which is the receiver of signal")
39*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-s", "--signal",
40*387f9dfdSAndroid Build Coastguard Worker    help="trace this signal only")
41*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
42*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
43*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
44*387f9dfdSAndroid Build Coastguard Workerdebug = 0
45*387f9dfdSAndroid Build Coastguard Worker
46*387f9dfdSAndroid Build Coastguard Worker# define BPF program
47*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
48*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
49*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
50*387f9dfdSAndroid Build Coastguard Worker
51*387f9dfdSAndroid Build Coastguard Workerstruct val_t {
52*387f9dfdSAndroid Build Coastguard Worker   u32 pid;
53*387f9dfdSAndroid Build Coastguard Worker   int sig;
54*387f9dfdSAndroid Build Coastguard Worker   int tpid;
55*387f9dfdSAndroid Build Coastguard Worker   char comm[TASK_COMM_LEN];
56*387f9dfdSAndroid Build Coastguard Worker};
57*387f9dfdSAndroid Build Coastguard Worker
58*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
59*387f9dfdSAndroid Build Coastguard Worker   u32 pid;
60*387f9dfdSAndroid Build Coastguard Worker   int tpid;
61*387f9dfdSAndroid Build Coastguard Worker   int sig;
62*387f9dfdSAndroid Build Coastguard Worker   int ret;
63*387f9dfdSAndroid Build Coastguard Worker   char comm[TASK_COMM_LEN];
64*387f9dfdSAndroid Build Coastguard Worker};
65*387f9dfdSAndroid Build Coastguard Worker
66*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(infotmp, u32, struct val_t);
67*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
68*387f9dfdSAndroid Build Coastguard Worker
69*387f9dfdSAndroid Build Coastguard Workerint syscall__kill(struct pt_regs *ctx, int tpid, int sig)
70*387f9dfdSAndroid Build Coastguard Worker{
71*387f9dfdSAndroid Build Coastguard Worker    u64 pid_tgid = bpf_get_current_pid_tgid();
72*387f9dfdSAndroid Build Coastguard Worker    u32 pid = pid_tgid >> 32;
73*387f9dfdSAndroid Build Coastguard Worker    u32 tid = (u32)pid_tgid;
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker    TPID_FILTER
76*387f9dfdSAndroid Build Coastguard Worker    PID_FILTER
77*387f9dfdSAndroid Build Coastguard Worker    SIGNAL_FILTER
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {.pid = pid};
80*387f9dfdSAndroid Build Coastguard Worker    if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
81*387f9dfdSAndroid Build Coastguard Worker        val.tpid = tpid;
82*387f9dfdSAndroid Build Coastguard Worker        val.sig = sig;
83*387f9dfdSAndroid Build Coastguard Worker        infotmp.update(&tid, &val);
84*387f9dfdSAndroid Build Coastguard Worker    }
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Worker    return 0;
87*387f9dfdSAndroid Build Coastguard Worker};
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Workerint do_ret_sys_kill(struct pt_regs *ctx)
90*387f9dfdSAndroid Build Coastguard Worker{
91*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
92*387f9dfdSAndroid Build Coastguard Worker    struct val_t *valp;
93*387f9dfdSAndroid Build Coastguard Worker    u64 pid_tgid = bpf_get_current_pid_tgid();
94*387f9dfdSAndroid Build Coastguard Worker    u32 pid = pid_tgid >> 32;
95*387f9dfdSAndroid Build Coastguard Worker    u32 tid = (u32)pid_tgid;
96*387f9dfdSAndroid Build Coastguard Worker
97*387f9dfdSAndroid Build Coastguard Worker    valp = infotmp.lookup(&tid);
98*387f9dfdSAndroid Build Coastguard Worker    if (valp == 0) {
99*387f9dfdSAndroid Build Coastguard Worker        // missed entry
100*387f9dfdSAndroid Build Coastguard Worker        return 0;
101*387f9dfdSAndroid Build Coastguard Worker    }
102*387f9dfdSAndroid Build Coastguard Worker
103*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm);
104*387f9dfdSAndroid Build Coastguard Worker    data.pid = pid;
105*387f9dfdSAndroid Build Coastguard Worker    data.tpid = valp->tpid;
106*387f9dfdSAndroid Build Coastguard Worker    data.ret = PT_REGS_RC(ctx);
107*387f9dfdSAndroid Build Coastguard Worker    data.sig = valp->sig;
108*387f9dfdSAndroid Build Coastguard Worker
109*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
110*387f9dfdSAndroid Build Coastguard Worker    infotmp.delete(&tid);
111*387f9dfdSAndroid Build Coastguard Worker
112*387f9dfdSAndroid Build Coastguard Worker    return 0;
113*387f9dfdSAndroid Build Coastguard Worker}
114*387f9dfdSAndroid Build Coastguard Worker"""
115*387f9dfdSAndroid Build Coastguard Worker
116*387f9dfdSAndroid Build Coastguard Workerif args.tpid:
117*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('TPID_FILTER',
118*387f9dfdSAndroid Build Coastguard Worker        'if (tpid != %s) { return 0; }' % args.tpid)
119*387f9dfdSAndroid Build Coastguard Workerelse:
120*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('TPID_FILTER', '')
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Workerif args.pid:
123*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PID_FILTER',
124*387f9dfdSAndroid Build Coastguard Worker        'if (pid != %s) { return 0; }' % args.pid)
125*387f9dfdSAndroid Build Coastguard Workerelse:
126*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PID_FILTER', '')
127*387f9dfdSAndroid Build Coastguard Worker
128*387f9dfdSAndroid Build Coastguard Workerif args.signal:
129*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('SIGNAL_FILTER',
130*387f9dfdSAndroid Build Coastguard Worker        'if (sig != %s) { return 0; }' % args.signal)
131*387f9dfdSAndroid Build Coastguard Workerelse:
132*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('SIGNAL_FILTER', '')
133*387f9dfdSAndroid Build Coastguard Worker
134*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf:
135*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
136*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
137*387f9dfdSAndroid Build Coastguard Worker        exit()
138*387f9dfdSAndroid Build Coastguard Worker
139*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
140*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
141*387f9dfdSAndroid Build Coastguard Workerkill_fnname = b.get_syscall_fnname("kill")
142*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event=kill_fnname, fn_name="syscall__kill")
143*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event=kill_fnname, fn_name="do_ret_sys_kill")
144*387f9dfdSAndroid Build Coastguard Worker
145*387f9dfdSAndroid Build Coastguard Worker# detect the length of PID column
146*387f9dfdSAndroid Build Coastguard Workerpid_bytes = 6
147*387f9dfdSAndroid Build Coastguard Workertry:
148*387f9dfdSAndroid Build Coastguard Worker    with open("/proc/sys/kernel/pid_max", 'r') as f:
149*387f9dfdSAndroid Build Coastguard Worker        pid_bytes = len(f.read().strip()) + 1
150*387f9dfdSAndroid Build Coastguard Worker        f.close()
151*387f9dfdSAndroid Build Coastguard Workerexcept:
152*387f9dfdSAndroid Build Coastguard Worker    pass # not fatal error, just use the default value
153*387f9dfdSAndroid Build Coastguard Worker
154*387f9dfdSAndroid Build Coastguard Worker# header
155*387f9dfdSAndroid Build Coastguard Workerprint("%-9s %-*s %-16s %-4s %-*s %s" % (
156*387f9dfdSAndroid Build Coastguard Worker    "TIME", pid_bytes, "PID", "COMM", "SIG", pid_bytes, "TPID", "RESULT"))
157*387f9dfdSAndroid Build Coastguard Worker
158*387f9dfdSAndroid Build Coastguard Worker# process event
159*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
160*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
161*387f9dfdSAndroid Build Coastguard Worker
162*387f9dfdSAndroid Build Coastguard Worker    if (args.failed and (event.ret >= 0)):
163*387f9dfdSAndroid Build Coastguard Worker        return
164*387f9dfdSAndroid Build Coastguard Worker
165*387f9dfdSAndroid Build Coastguard Worker    printb(b"%-9s %-*d %-16s %-4d %-*d %d" % (strftime("%H:%M:%S").encode('ascii'),
166*387f9dfdSAndroid Build Coastguard Worker        pid_bytes, event.pid, event.comm, event.sig, pid_bytes, event.tpid, event.ret))
167*387f9dfdSAndroid Build Coastguard Worker
168*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event
169*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event)
170*387f9dfdSAndroid Build Coastguard Workerwhile 1:
171*387f9dfdSAndroid Build Coastguard Worker    try:
172*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
173*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
174*387f9dfdSAndroid Build Coastguard Worker        exit()
175