xref: /aosp_15_r20/external/bcc/tools/bpflist.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1#!/usr/bin/env 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
15from bcc import BPF, USDT
16import argparse
17import re
18import os
19import subprocess
20
21examples = """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"""
26parser = argparse.ArgumentParser(
27    description="Display processes currently using BPF programs and maps",
28    formatter_class=argparse.RawDescriptionHelpFormatter,
29    epilog=examples)
30parser.add_argument("-v", "--verbosity", action="count", default=0,
31    help="count and display kprobes/uprobes as well")
32args = parser.parse_args()
33
34def comm_for_pid(pid):
35    try:
36        return open("/proc/%d/comm" % pid).read().strip()
37    except:
38        return "[unknown]"
39
40counts = {}
41
42def parse_probes(typ):
43    if args.verbosity > 1:
44        print("open %ss:" % typ)
45    for probe in open("/sys/kernel/debug/tracing/%s_events" % typ):
46        # Probes opened by bcc have a specific pattern that includes the pid
47        # of the requesting process.
48        match = re.search('_bcc_(\\d+)\\s', probe)
49        if match:
50            pid = int(match.group(1))
51            counts[(pid, typ)] = counts.get((pid, typ), 0) + 1
52        if args.verbosity > 1:
53            print(probe.strip())
54    if args.verbosity > 1:
55        print("")
56
57if args.verbosity > 0:
58    parse_probes("kprobe")
59    parse_probes("uprobe")
60
61def find_bpf_fds(pid):
62    root = '/proc/%d/fd' % pid
63    for fd in os.listdir(root):
64        try:
65            link = os.readlink(os.path.join(root, fd))
66        except OSError:
67            continue
68        match = re.match('anon_inode:bpf-([\\w-]+)', link)
69        if match:
70            tup = (pid, match.group(1))
71            counts[tup] = counts.get(tup, 0) + 1
72
73for pdir in os.listdir('/proc'):
74    if re.match('\\d+', pdir):
75        try:
76            find_bpf_fds(int(pdir))
77        except OSError:
78            continue
79
80items = counts.items()
81max_type_len = items and max(list(map(lambda t: len(t[0][1]), items))) or 0
82print_format = "%%-6s %%-16s %%-%ss %%s" % (max_type_len + 1)
83
84print(print_format % ("PID", "COMM", "TYPE", "COUNT"))
85for (pid, typ), count in sorted(items, key=lambda t: t[0][0]):
86    comm = comm_for_pid(pid)
87    print(print_format % (pid, comm, typ, count))
88