Skip to content

Instantly share code, notes, and snippets.

@thejh
Created November 2, 2016 14:31
Show Gist options
  • Save thejh/071e5c24ec02fabfef258eea2df622e0 to your computer and use it in GitHub Desktop.
Save thejh/071e5c24ec02fabfef258eea2df622e0 to your computer and use it in GitHub Desktop.
PERF_SAMPLE_REGS_INTR demo
$ ./perf_sample_regs_intr_demo
data_head is at ff0
rax=0xffffffffffffffff rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0x4005b0
rax=0xfffffffffffffff7 rbp=0xffffa5fc43efff48 rsp=0xffffa5fc43efff28 rip=0xffffffff97c55f1d
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce18
rax=0xffff8fc3ba3b79c0 rbp=0xffffa5fc43efff00 rsp=0xffffa5fc43effef0 rip=0xffffffff97c745c9
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce18
rax=0x0 rbp=0xffffa5fc43efff00 rsp=0xffffa5fc43effef8 rip=0xffffffff97c75049
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce15
rax=0xffffffffffffffff rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040c0 rip=0x4007d5
rax=0xfffffffffffffff7 rbp=0xffffa5fc43efff48 rsp=0xffffa5fc43efff10 rip=0xffffffff97c55f43
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce18
rax=0xffff8fc3ba3b79c0 rbp=0xffffa5fc43efff00 rsp=0xffffa5fc43effef0 rip=0xffffffff97c745c9
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce18
rax=0x0 rbp=0xffffa5fc43efff00 rsp=0xffffa5fc43effef8 rip=0xffffffff97c75049
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce15
rax=0xffffffffffffffff rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040c0 rip=0x4007d5
rax=0xfffffffffffffff7 rbp=0xffffa5fc43efff48 rsp=0xffffa5fc43efff10 rip=0xffffffff97c55f43
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce18
rax=0x0 rbp=0xffffa5fc43efff00 rsp=0xffffa5fc43effef8 rip=0xffffffff97c75049
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce15
rax=0xffffffffffffffff rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040c0 rip=0x4007d5
rax=0xfffffffffffffff7 rbp=0xffffa5fc43efff48 rsp=0xffffa5fc43efff10 rip=0xffffffff97c55f43
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce18
rax=0x0 rbp=0xffffa5fc43efff00 rsp=0xffffa5fc43effef8 rip=0xffffffff97c75049
rax=0xfffffffffffffff7 rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0xffffffff9862ce15
rax=0xffffffffffffffff rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040c0 rip=0x4007d5
rax=0xfffffffffffffff7 rbp=0xffffa5fc43efff48 rsp=0xffffa5fc43efff10 rip=0xffffffff97c55f43
rax=0xffffffffffffffff rbp=0x7ffc9ec04170 rsp=0x7ffc9ec040b8 rip=0x4005b0
[...]
// compile with:
// gcc -Wall -std=gnu99 -o perf_sample_regs_intr_demo perf_sample_regs_intr_demo.c
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <inttypes.h>
#include <assert.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <linux/perf_event.h>
#include <asm/perf_regs.h>
struct my_event {
struct perf_event_header header;
uint64_t abi;
uint64_t regs[4];
};
long perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags) {
return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
}
int main(void) {
int status;
pid_t child = fork();
if (child == -1)
err(1, "fork");
if (child == 0) {
sleep(1); /* quick-and-dirty way to wait for the parent to attach */
for (int i=0; i<1000000; i++) {
write(100000, NULL, 1);
}
return 0;
}
struct perf_event_attr attr = {
.type = PERF_TYPE_HARDWARE,
.config = PERF_COUNT_HW_INSTRUCTIONS,
.size = sizeof(struct perf_event_attr),
.sample_period = 100000,
.sample_type = PERF_SAMPLE_REGS_INTR,
.precise_ip = 2,
.sample_regs_intr =
(1<<PERF_REG_X86_AX) |
(1<<PERF_REG_X86_BP) |
(1<<PERF_REG_X86_SP) |
(1<<PERF_REG_X86_IP)
};
int perf_fd = perf_event_open(&attr, child, -1, -1, 0);
if (perf_fd == -1)
err(1, "perf_event_open");
struct perf_event_mmap_page *meta_page = mmap(NULL, 2*4096, PROT_READ|PROT_WRITE, MAP_SHARED, perf_fd, 0);
if (meta_page == MAP_FAILED)
err(1, "mmap");
if (waitpid(child, &status, 0) != child)
err(1, "waitpid");
uint64_t data_head = meta_page->data_head;
if (data_head == 0) {
puts("no data!");
return 0;
}
printf("data_head is at %lx\n", (unsigned long)data_head);
struct perf_event_header *head = (void*)((char*)meta_page + 4096);
while ((char*)head + head->size < (char*)meta_page + 4096 + data_head) {
if (head->type == PERF_RECORD_SAMPLE) {
struct my_event *ev = (void*)head;
printf("rax=0x%lx rbp=0x%lx rsp=0x%lx rip=0x%lx\n",
ev->regs[0], ev->regs[1], ev->regs[2], ev->regs[3]);
}
head = (void*)((char*)head + head->size);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment