1#!/usr/bin/python 2# Carlos Neira <cneirabustos@gmail.com> 3# This is a Hello World example that uses BPF_PERF_OUTPUT. 4# in this example bpf_get_ns_current_pid_tgid(), this helper 5# works inside pid namespaces. 6# bpf_get_current_pid_tgid() only returns the host pid outside any 7# namespace and this will not work when the script is run inside a pid namespace. 8 9from bcc import BPF 10from bcc.utils import printb 11import sys, os 12from stat import * 13 14# define BPF program 15prog = """ 16#include <linux/sched.h> 17 18// define output data structure in C 19struct data_t { 20 u32 pid; 21 u64 ts; 22 char comm[TASK_COMM_LEN]; 23}; 24BPF_PERF_OUTPUT(events); 25 26int hello(struct pt_regs *ctx) { 27 struct data_t data = {}; 28 struct bpf_pidns_info ns = {}; 29 30 if(bpf_get_ns_current_pid_tgid(DEV, INO, &ns, sizeof(struct bpf_pidns_info))) 31 return 0; 32 data.pid = ns.pid; 33 data.ts = bpf_ktime_get_ns(); 34 bpf_get_current_comm(&data.comm, sizeof(data.comm)); 35 36 events.perf_submit(ctx, &data, sizeof(data)); 37 38 return 0; 39} 40""" 41 42devinfo = os.stat("/proc/self/ns/pid") 43for r in (("DEV", str(devinfo.st_dev)), ("INO", str(devinfo.st_ino))): 44 prog = prog.replace(*r) 45 46# load BPF program 47b = BPF(text=prog) 48b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello") 49 50# header 51print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE")) 52 53# process event 54start = 0 55 56 57def print_event(cpu, data, size): 58 global start 59 event = b["events"].event(data) 60 if start == 0: 61 start = event.ts 62 time_s = (float(event.ts - start)) / 1000000000 63 printb( 64 b"%-18.9f %-16s %-6d %s" 65 % (time_s, event.comm, event.pid, b"Hello, perf_output!") 66 ) 67 68 69# loop with callback to print_event 70b["events"].open_perf_buffer(print_event) 71while 1: 72 try: 73 b.perf_buffer_poll() 74 except KeyboardInterrupt: 75 exit() 76