Sasha Goldshtein | 2593378 | 2017-03-09 14:37:50 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # |
| 3 | # bpflist Display processes currently using BPF programs and maps, |
| 4 | # pinned BPF programs and maps, and enabled probes. |
| 5 | # |
| 6 | # USAGE: bpflist [-v] |
| 7 | # |
| 8 | # Idea by Brendan Gregg. |
| 9 | # |
| 10 | # Copyright 2017, Sasha Goldshtein |
| 11 | # Licensed under the Apache License, Version 2.0 |
| 12 | # |
| 13 | # 09-Mar-2017 Sasha Goldshtein Created this. |
| 14 | |
| 15 | from bcc import BPF, USDT |
| 16 | import argparse |
| 17 | import re |
Sasha Goldshtein | 563af79 | 2017-02-14 11:09:13 -0500 | [diff] [blame] | 18 | import os |
Sasha Goldshtein | 2593378 | 2017-03-09 14:37:50 +0000 | [diff] [blame] | 19 | import subprocess |
| 20 | |
| 21 | examples = """examples: |
| 22 | bpflist # display all processes currently using BPF |
| 23 | bpflist -v # also count kprobes/uprobes |
| 24 | bpflist -vv # display kprobes/uprobes and count them |
| 25 | """ |
| 26 | parser = argparse.ArgumentParser( |
| 27 | description="Display processes currently using BPF programs and maps", |
| 28 | formatter_class=argparse.RawDescriptionHelpFormatter, |
| 29 | epilog=examples) |
| 30 | parser.add_argument("-v", "--verbosity", action="count", default=0, |
| 31 | help="count and display kprobes/uprobes as well") |
| 32 | args = parser.parse_args() |
| 33 | |
| 34 | def comm_for_pid(pid): |
| 35 | try: |
| 36 | return open("/proc/%d/comm" % pid).read().strip() |
| 37 | except: |
| 38 | return "[unknown]" |
| 39 | |
| 40 | counts = {} |
| 41 | |
| 42 | def parse_probes(typ): |
| 43 | if args.verbosity > 1: print("open %ss:" % typ) |
| 44 | for probe in open("/sys/kernel/debug/tracing/%s_events" % typ): |
| 45 | # Probes opened by bcc have a specific pattern that includes the pid |
| 46 | # of the requesting process. |
| 47 | match = re.search('_bcc_(\\d+)\\s', probe) |
| 48 | if match: |
| 49 | pid = int(match.group(1)) |
| 50 | counts[(pid, typ)] = counts.get((pid, typ), 0) + 1 |
| 51 | if args.verbosity > 1: print(probe.strip()) |
| 52 | if args.verbosity > 1: print("") |
| 53 | |
| 54 | if args.verbosity > 0: |
| 55 | parse_probes("kprobe") |
| 56 | parse_probes("uprobe") |
| 57 | |
Sasha Goldshtein | 563af79 | 2017-02-14 11:09:13 -0500 | [diff] [blame] | 58 | def find_bpf_fds(pid): |
| 59 | root = '/proc/%d/fd' % pid |
| 60 | for fd in os.listdir(root): |
| 61 | try: |
| 62 | link = os.readlink(os.path.join(root, fd)) |
| 63 | except OSError: |
| 64 | continue |
| 65 | match = re.match('.*bpf-(\\w+)', link) |
| 66 | if match: |
| 67 | tup = (pid, match.group(1)) |
| 68 | counts[tup] = counts.get(tup, 0) + 1 |
| 69 | |
| 70 | for pdir in os.listdir('/proc'): |
| 71 | if re.match('\\d+', pdir): |
| 72 | find_bpf_fds(int(pdir)) |
Sasha Goldshtein | 2593378 | 2017-03-09 14:37:50 +0000 | [diff] [blame] | 73 | |
| 74 | print("%-6s %-16s %-8s %s" % ("PID", "COMM", "TYPE", "COUNT")) |
| 75 | for (pid, typ), count in sorted(counts.items(), key=lambda t: t[0][0]): |
| 76 | comm = comm_for_pid(pid) |
| 77 | print("%-6d %-16s %-8s %-4d" % (pid, comm, typ, count)) |