stop = true;
 }
 
-static enum bpf_perf_event_ret print_bpf_output(void *event, void *priv)
+static enum bpf_perf_event_ret
+print_bpf_output(struct perf_event_header *event, void *private_data)
 {
-       struct event_ring_info *ring = priv;
-       struct perf_event_sample *e = event;
+       struct perf_event_sample *e = container_of(event, struct perf_event_sample,
+                                                  header);
+       struct event_ring_info *ring = private_data;
        struct {
                struct perf_event_header header;
                __u64 id;
                __u64 lost;
-       } *lost = event;
+       } *lost = (typeof(lost))event;
 
        if (json_output) {
                jsonw_start_object(json_wtr);
 
 }
 
 enum bpf_perf_event_ret
-bpf_perf_event_read_simple(void *mem, unsigned long size,
-                          unsigned long page_size, void **buf, size_t *buf_len,
-                          bpf_perf_event_print_t fn, void *priv)
+bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
+                          void **copy_mem, size_t *copy_size,
+                          bpf_perf_event_print_t fn, void *private_data)
 {
-       struct perf_event_mmap_page *header = mem;
+       struct perf_event_mmap_page *header = mmap_mem;
        __u64 data_head = ring_buffer_read_head(header);
        __u64 data_tail = header->data_tail;
-       int ret = LIBBPF_PERF_EVENT_ERROR;
-       void *base, *begin, *end;
-
-       if (data_head == data_tail)
-               return LIBBPF_PERF_EVENT_CONT;
-
-       base = ((char *)header) + page_size;
-
-       begin = base + data_tail % size;
-       end = base + data_head % size;
-
-       while (begin != end) {
-               struct perf_event_header *ehdr;
-
-               ehdr = begin;
-               if (begin + ehdr->size > base + size) {
-                       long len = base + size - begin;
-
-                       if (*buf_len < ehdr->size) {
-                               free(*buf);
-                               *buf = malloc(ehdr->size);
-                               if (!*buf) {
+       void *base = ((__u8 *)header) + page_size;
+       int ret = LIBBPF_PERF_EVENT_CONT;
+       struct perf_event_header *ehdr;
+       size_t ehdr_size;
+
+       while (data_head != data_tail) {
+               ehdr = base + (data_tail & (mmap_size - 1));
+               ehdr_size = ehdr->size;
+
+               if (((void *)ehdr) + ehdr_size > base + mmap_size) {
+                       void *copy_start = ehdr;
+                       size_t len_first = base + mmap_size - copy_start;
+                       size_t len_secnd = ehdr_size - len_first;
+
+                       if (*copy_size < ehdr_size) {
+                               free(*copy_mem);
+                               *copy_mem = malloc(ehdr_size);
+                               if (!*copy_mem) {
+                                       *copy_size = 0;
                                        ret = LIBBPF_PERF_EVENT_ERROR;
                                        break;
                                }
-                               *buf_len = ehdr->size;
+                               *copy_size = ehdr_size;
                        }
 
-                       memcpy(*buf, begin, len);
-                       memcpy(*buf + len, base, ehdr->size - len);
-                       ehdr = (void *)*buf;
-                       begin = base + ehdr->size - len;
-               } else if (begin + ehdr->size == base + size) {
-                       begin = base;
-               } else {
-                       begin += ehdr->size;
+                       memcpy(*copy_mem, copy_start, len_first);
+                       memcpy(*copy_mem + len_first, base, len_secnd);
+                       ehdr = *copy_mem;
                }
 
-               ret = fn(ehdr, priv);
+               ret = fn(ehdr, private_data);
+               data_tail += ehdr_size;
                if (ret != LIBBPF_PERF_EVENT_CONT)
                        break;
-
-               data_tail += ehdr->size;
        }
 
        ring_buffer_write_tail(header, data_tail);
 
        LIBBPF_PERF_EVENT_CONT  = -2,
 };
 
-typedef enum bpf_perf_event_ret (*bpf_perf_event_print_t)(void *event,
-                                                         void *priv);
-LIBBPF_API int bpf_perf_event_read_simple(void *mem, unsigned long size,
-                                         unsigned long page_size,
-                                         void **buf, size_t *buf_len,
-                                         bpf_perf_event_print_t fn,
-                                         void *priv);
+struct perf_event_header;
+typedef enum bpf_perf_event_ret
+       (*bpf_perf_event_print_t)(struct perf_event_header *hdr,
+                                 void *private_data);
+LIBBPF_API enum bpf_perf_event_ret
+bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
+                          void **copy_mem, size_t *copy_size,
+                          bpf_perf_event_print_t fn, void *private_data);
 
 struct nlattr;
 typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);