Home | History | Annotate | Download | only in old
      1 #!/usr/bin/python
      2 # @lint-avoid-python-3-compatibility-imports
      3 #
      4 # killsnoop Trace signals issued by the kill() syscall.
      5 #           For Linux, uses BCC, eBPF. Embedded C.
      6 #
      7 # USAGE: killsnoop [-h] [-t] [-x] [-p PID]
      8 #
      9 # Copyright (c) 2015 Brendan Gregg.
     10 # Licensed under the Apache License, Version 2.0 (the "License")
     11 #
     12 # 20-Sep-2015   Brendan Gregg   Created this.
     13 
     14 from __future__ import print_function
     15 from bcc import BPF
     16 import argparse
     17 
     18 # arguments
     19 examples = """examples:
     20     ./killsnoop           # trace all kill() signals
     21     ./killsnoop -t        # include timestamps
     22     ./killsnoop -x        # only show failed kills
     23     ./killsnoop -p 181    # only trace PID 181
     24 """
     25 parser = argparse.ArgumentParser(
     26     description="Trace signals issued by the kill() syscall",
     27     formatter_class=argparse.RawDescriptionHelpFormatter,
     28     epilog=examples)
     29 parser.add_argument("-t", "--timestamp", action="store_true",
     30     help="include timestamp on output")
     31 parser.add_argument("-x", "--failed", action="store_true",
     32     help="only show failed opens")
     33 parser.add_argument("-p", "--pid",
     34     help="trace this PID only")
     35 args = parser.parse_args()
     36 debug = 0
     37 
     38 # define BPF program
     39 bpf_text = """
     40 #include <uapi/linux/ptrace.h>
     41 
     42 BPF_HASH(args_pid, u32, int);
     43 BPF_HASH(args_sig, u32, int);
     44 
     45 int kprobe__sys_kill(struct pt_regs *ctx, int tpid, int sig)
     46 {
     47     u32 pid = bpf_get_current_pid_tgid();
     48 
     49     FILTER
     50     args_pid.update(&pid, &tpid);
     51     args_sig.update(&pid, &sig);
     52 
     53     return 0;
     54 };
     55 
     56 int kretprobe__sys_kill(struct pt_regs *ctx)
     57 {
     58     int *tpidp, *sigp, ret = ctx->ax;
     59     u32 pid = bpf_get_current_pid_tgid();
     60 
     61     tpidp = args_pid.lookup(&pid);
     62     sigp = args_sig.lookup(&pid);
     63     if (tpidp == 0 || sigp == 0) {
     64         return 0;   // missed entry
     65     }
     66 
     67     bpf_trace_printk("%d %d %d\\n", *tpidp, *sigp, ret);
     68     args_pid.delete(&pid);
     69     args_sig.delete(&pid);
     70 
     71     return 0;
     72 }
     73 """
     74 if args.pid:
     75     bpf_text = bpf_text.replace('FILTER',
     76         'if (pid != %s) { return 0; }' % args.pid)
     77 else:
     78     bpf_text = bpf_text.replace('FILTER', '')
     79 if debug:
     80     print(bpf_text)
     81 
     82 # initialize BPF
     83 b = BPF(text=bpf_text)
     84 
     85 # header
     86 if args.timestamp:
     87     print("%-14s" % ("TIME(s)"), end="")
     88 print("%-6s %-16s %-4s %-6s %s" % ("PID", "COMM", "SIG", "TPID", "RESULT"))
     89 
     90 start_ts = 0
     91 
     92 # format output
     93 while 1:
     94     (task, pid, cpu, flags, ts, msg) = b.trace_fields()
     95     (tpid_s, sig_s, ret_s) = msg.split(" ")
     96 
     97     ret = int(ret_s)
     98     if (args.failed and (ret >= 0)):
     99         continue
    100 
    101     # print columns
    102     if args.timestamp:
    103         if start_ts == 0:
    104             start_ts = ts
    105         print("%-14.9f" % (ts - start_ts), end="")
    106     print("%-6d %-16s %-4s %-6s %s" % (pid, task, sig_s, tpid_s, ret_s))
    107