Skip to content

Instantly share code, notes, and snippets.

@YangKeao
Created January 6, 2021 08:15
Show Gist options
  • Save YangKeao/05e5a634bc7f2bb5a8a083ea23c21c52 to your computer and use it in GitHub Desktop.
Save YangKeao/05e5a634bc7f2bb5a8a083ea23c21c52 to your computer and use it in GitHub Desktop.
simple frame pointer perf example
use std::{mem::size_of, ptr::{null, null_mut}};
use libc::c_void;
use perf_event_open_sys as sys;
fn main() -> std::io::Result<()> {
let mut attrs = sys::bindings::perf_event_attr::default();
// Populate the fields we need.
attrs.size = std::mem::size_of::<sys::bindings::perf_event_attr>() as u32;
attrs.type_ = sys::bindings::perf_type_id_PERF_TYPE_HARDWARE;
attrs.config = sys::bindings::perf_hw_id_PERF_COUNT_HW_CPU_CYCLES as u64;
attrs.__bindgen_anon_1.sample_freq = 10000;
attrs.sample_type = sys::bindings::perf_event_sample_format_PERF_SAMPLE_CALLCHAIN;
attrs.sample_max_stack = 10;
attrs.set_disabled(1);
attrs.set_exclude_kernel(1);
attrs.set_exclude_hv(1);
attrs.set_freq(1);
let result = unsafe {
sys::perf_event_open(&mut attrs, 0, -1, -1, 0)
};
unsafe {
if result < 0 {
println!("error {}", result)
} else {
println!("successfully open {}", result);
let perf_mmap_page_addr = libc::mmap(null_mut(), ((1 << 8) + 1) * 4096, libc::PROT_READ, libc::MAP_SHARED, result, 0) as *mut sys::bindings::perf_event_mmap_page;
println!("get mmap: {:?}", perf_mmap_page_addr);
let errno = libc::__errno_location();
println!("errno: {}", *errno);
let ret = libc::ioctl(result, sys::bindings::perf_event_ioctls_RESET as u64, 0);
if ret <0 {
panic!("ioctl failed {}", ret)
}
let ret = libc::ioctl(result, sys::bindings::perf_event_ioctls_ENABLE as u64, 0);
if ret <0 {
panic!("ioctl failed {}", ret)
}
payload();
let ret = libc::ioctl(result, sys::bindings::perf_event_ioctls_DISABLE as u64, 0);
if ret <0 {
panic!("ioctl failed {}", ret)
}
let perf_mmap_page = *perf_mmap_page_addr;
println!("perf mmap data_head {}", perf_mmap_page.data_head);
println!("perf mmap data_tail {}", perf_mmap_page.data_tail);
println!("perf mmap data_offset {}", perf_mmap_page.data_offset);
println!("perf mmap data_size {}", perf_mmap_page.data_size);
let mut raw_ptr = perf_mmap_page_addr as *mut u8;
raw_ptr = raw_ptr.add(perf_mmap_page.data_offset as usize);
loop {
let record_header = raw_ptr as *mut sys::bindings::perf_event_header;
println!("header {:?}", *record_header);
let size = (*record_header).size;
if size == 0 {
break
}
let typ = (*record_header).type_;
if typ != 9 {
raw_ptr = raw_ptr.add(size as usize);
continue;
}
let sample_nr = raw_ptr.add(size_of::<sys::bindings::perf_event_header>()) as *mut u64;
println!("sample_nr: {:?}", *sample_nr);
for index in 0..*sample_nr {
let ip: *mut u64 = sample_nr.add(1 + index as usize);
println!("ip: {:x}", *ip);
backtrace::resolve(*ip as *mut c_void, |symbol| {
println!("Symbol: {:?}", symbol)
});
}
println!("STACK FINISH");
raw_ptr = raw_ptr.add(size as usize);
}
}
}
Ok(())
}
#[inline(never)]
fn fibonacci(i: i32) -> i32 {
if i == 1 || i == 2 {
return 1
}
fibonacci(i-1) + fibonacci(i-2)
}
#[inline(never)]
fn payload() {
println!("fibonacci number: {}", fibonacci(25));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment