Created
January 6, 2021 08:15
-
-
Save YangKeao/05e5a634bc7f2bb5a8a083ea23c21c52 to your computer and use it in GitHub Desktop.
simple frame pointer perf example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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