def test_attach_raw_event_powerpc(self): # on PowerPC, 'addr' is always written to; for x86 see _x86 version of test bpf_text = """ #include <linux/perf_event.h> struct key_t { int cpu; int pid; char name[100]; }; static inline __attribute__((always_inline)) void get_key(struct key_t* key) { key->cpu = bpf_get_smp_processor_id(); key->pid = bpf_get_current_pid_tgid(); bpf_get_current_comm(&(key->name), sizeof(key->name)); } int on_sample_hit(struct bpf_perf_event_data *ctx) { struct key_t key = {}; get_key(&key); u64 addr = 0; struct bpf_perf_event_data_kern *kctx; struct perf_sample_data *data; kctx = (struct bpf_perf_event_data_kern *)ctx; bpf_probe_read(&data, sizeof(struct perf_sample_data*), &(kctx->data)); if (data) bpf_probe_read(&addr, sizeof(u64), &(data->addr)); bpf_trace_printk("test_attach_raw_event_powerpc: pid: %ld, comm: %s, addr: 0x%llx\\n", key.pid, key.name, addr); return 0; } """ b = BPF(text=bpf_text) try: event_attr = Perf.perf_event_attr() event_attr.type = Perf.PERF_TYPE_HARDWARE event_attr.config = PerfHWConfig.CACHE_MISSES event_attr.sample_period = 1000000 event_attr.sample_type = PerfEventSampleFormat.ADDR event_attr.exclude_kernel = 1 b.attach_perf_event_raw(attr=event_attr, fn_name="on_sample_hit", pid=-1, cpu=-1) except Exception: print( "Failed to attach to a raw event. Please check the event attr used" ) exit() print( "Running for 2 seconds or hit Ctrl-C to end. Check trace file for samples information written by bpf_trace_printk." ) sleep(2)
def test_attach_raw_event_x86(self): # on x86, need to set precise_ip in order for perf_events to write to 'addr' bpf_text = """ #include <linux/perf_event.h> struct key_t { int cpu; int pid; char name[100]; }; static inline __attribute__((always_inline)) void get_key(struct key_t* key) { key->cpu = bpf_get_smp_processor_id(); key->pid = bpf_get_current_pid_tgid(); bpf_get_current_comm(&(key->name), sizeof(key->name)); } int on_sample_hit(struct bpf_perf_event_data *ctx) { struct key_t key = {}; get_key(&key); u64 addr = ctx->addr; bpf_trace_printk("test_attach_raw_event_x86: pid: %ld, comm: %s, addr: 0x%llx\\n", key.pid, key.name, addr); return 0; } """ b = BPF(text=bpf_text) try: event_attr = Perf.perf_event_attr() event_attr.type = Perf.PERF_TYPE_HARDWARE event_attr.config = PerfHWConfig.CPU_CYCLES event_attr.sample_period = 1000000 event_attr.sample_type = PerfEventSampleFormat.ADDR event_attr.exclude_kernel = 1 event_attr.precise_ip = 2 b.attach_perf_event_raw(attr=event_attr, fn_name="on_sample_hit", pid=-1, cpu=-1) except Exception: print( "Failed to attach to a raw event. Please check the event attr used" ) exit() print( "Running for 1 seconds or hit Ctrl-C to end. Check trace file for samples information written by bpf_trace_printk." ) sleep(1)
# initialize BPF b = BPF(text=bpf_text) # signal handler def signal_ignore(signal, frame): print() # # Setup perf_events # # use perf_events to sample try: Perf.perf_event_open(0, pid=-1, ptype=Perf.PERF_TYPE_SOFTWARE, freq=args.frequency) except: print( "ERROR: initializing perf_events for sampling.\n" "To debug this, try running the following command:\n" " perf record -F 49 -e cpu-clock %s -- sleep 1\n" "If that also doesn't work, fix it first." % perf_filter, file=stderr, ) exit(0) # # Output Report # # collect samples
print("BPF initialization failed. perf_misc_flags() may be inlined in " + "your kernel build.\nThis tool will be updated in the future to " + "support Linux 4.9, which has reliable profiling support. Exiting.") exit() # signal handler def signal_ignore(signal, frame): print() # # Setup perf_events # # use perf_events to sample try: Perf.perf_event_open(0, pid=-1, ptype=Perf.PERF_TYPE_SOFTWARE, freq=args.frequency) except: print("ERROR: initializing perf_events for sampling.\n" "To debug this, try running the following command:\n" " perf record -F 49 -e cpu-clock %s -- sleep 1\n" "If that also doesn't work, fix it first." % perf_filter, file=stderr) exit(0) # # Output Report # # collect samples try: sleep(duration) except KeyboardInterrupt: