static int bpf_attach_tracing_event(int progfd, const char *event_path, struct perf_reader *reader, int pid, int cpu, int group_fd) { int efd = -1, pfd; ssize_t bytes; char buf[256]; struct perf_event_attr attr = {}; snprintf(buf, sizeof(buf), "%s/id", event_path); efd = open(buf, O_RDONLY, 0); if (efd < 0) { fprintf(stderr, "open(%s): %s\n", buf, strerror(errno)); goto error; } bytes = read(efd, buf, sizeof(buf)); if (bytes <= 0 || bytes >= sizeof(buf)) { fprintf(stderr, "read(%s): %s\n", buf, strerror(errno)); goto error; } buf[bytes] = '\0'; attr.config = strtol(buf, NULL, 0); attr.type = PERF_TYPE_TRACEPOINT; attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN; attr.sample_period = 1; attr.wakeup_events = 1; pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, group_fd, PERF_FLAG_FD_CLOEXEC); if (pfd < 0) { fprintf(stderr, "perf_event_open(%s/id): %s\n", event_path, strerror(errno)); 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_SET_BPF, progfd) < 0) { perror("ioctl(PERF_EVENT_IOC_SET_BPF)"); goto error; } if (ioctl(pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) { perror("ioctl(PERF_EVENT_IOC_ENABLE)"); goto error; } return 0; error: if (efd >= 0) close(efd); return -1; }
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 }
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; }