void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, void *cb_cookie, int pid, int cpu) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) int pfd; struct perf_event_attr attr = {}; struct perf_reader *reader = NULL; reader = perf_reader_new(NULL, raw_cb, cb_cookie); if (!reader) goto error; attr.config = PERF_COUNT_SW_BPF_OUTPUT; attr.type = PERF_TYPE_SOFTWARE; attr.sample_type = PERF_SAMPLE_RAW; attr.sample_period = 1; attr.wakeup_events = 1; pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC); if (pfd < 0) { perror("perf_event_open"); goto error; } perf_reader_set_fd(reader, pfd); if (perf_reader_mmap(reader, attr.type, attr.sample_type) < 0) goto error; if (ioctl(pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) { perror("ioctl(PERF_EVENT_IOC_ENABLE)"); goto error; } return reader; error: if (reader) perf_reader_free(reader); return NULL; #else fprintf(stderr, "PERF_COUNT_SW_BPF_OUTPUT feature unsupported\n"); return NULL; #endif }
static void * bpf_attach_probe(int progfd, const char *event, const char *event_desc, const char *event_type, pid_t pid, int cpu, int group_fd, perf_reader_cb cb, void *cb_cookie) { int kfd = -1; char buf[256]; struct perf_reader *reader = NULL; reader = perf_reader_new(cb, NULL, cb_cookie); if (!reader) goto error; snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", event_type); kfd = open(buf, O_WRONLY | O_APPEND, 0); if (kfd < 0) { fprintf(stderr, "open(%s): %s\n", buf, strerror(errno)); goto error; } if (write(kfd, event_desc, strlen(event_desc)) < 0) { fprintf(stderr, "write(%s, \"%s\") failed: %s\n", buf, event_desc, strerror(errno)); if (errno == EINVAL) fprintf(stderr, "check dmesg output for possible cause\n"); goto error; } snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s", event_type, event); if (bpf_attach_tracing_event(progfd, buf, reader, pid, cpu, group_fd) < 0) goto error; return reader; error: if (kfd >= 0) close(kfd); if (reader) perf_reader_free(reader); return NULL; }
void * bpf_attach_kprobe(int progfd, const char *event, const char *event_desc, pid_t pid, int cpu, int group_fd, perf_reader_cb cb, void *cb_cookie) { int rc = -1, kfd = -1; char buf[256]; struct perf_reader *reader = NULL; reader = perf_reader_new(-1, 8, cb, cb_cookie); if (!reader) goto cleanup; kfd = open("/sys/kernel/debug/tracing/kprobe_events", O_WRONLY | O_APPEND, 0); if (kfd < 0) { perror("open(kprobe_events)"); goto cleanup; } if (write(kfd, event_desc, strlen(event_desc)) < 0) { fprintf(stderr, "write of \"%s\" into kprobe_events failed: %s\n", event_desc, strerror(errno)); if (errno == EINVAL) fprintf(stderr, "check dmesg output for possible cause\n"); goto cleanup; } snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/kprobes/%s", event); rc = bpf_attach_tracing_event(progfd, buf, reader, pid, cpu, group_fd); cleanup: if (kfd >= 0) close(kfd); if (reader && rc < 0) { perf_reader_free(reader); reader = NULL; } return reader; }
void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, void *cb_cookie, int pid, int cpu) { int pfd; struct perf_event_attr attr = {}; struct perf_reader *reader = NULL; reader = perf_reader_new(NULL, raw_cb, cb_cookie); if (!reader) goto error; attr.config = 10;//PERF_COUNT_SW_BPF_OUTPUT; attr.type = PERF_TYPE_SOFTWARE; attr.sample_type = PERF_SAMPLE_RAW; attr.sample_period = 1; attr.wakeup_events = 1; pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC); if (pfd < 0) { fprintf(stderr, "perf_event_open: %s\n", strerror(errno)); fprintf(stderr, " (check your kernel for PERF_COUNT_SW_BPF_OUTPUT support, 4.4 or newer)\n"); goto error; } perf_reader_set_fd(reader, pfd); if (perf_reader_mmap(reader, attr.type, attr.sample_type) < 0) goto error; if (ioctl(pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) { perror("ioctl(PERF_EVENT_IOC_ENABLE)"); goto error; } return reader; error: if (reader) perf_reader_free(reader); return NULL; }