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