1use std::fs::File;
2use std::mem::size_of;
3use std::io::Seek;
4use std::io::SeekFrom;
5use std::convert::TryInto;
6
7use byteorder::{LittleEndian, ReadBytesExt};
8use libc::{_SC_PAGESIZE, sysconf};
9
10#[derive(Debug)]
11pub enum Error {
12 PageMap,
13 Read,
14 Unk,
15}
16
17pub fn virt_to_phys<T>(virt: *const T) -> Result<*const T, Error> {
18 let ptr_val = virt as usize;
19 let page_size = unsafe {
20 sysconf(_SC_PAGESIZE) as usize
21 };
22 let mut file = File::open("/proc/self/pagemap").unwrap();
23 let seek = (ptr_val / page_size * size_of::<*const T>()).try_into().unwrap();
24 file.seek(SeekFrom::Start(seek)).unwrap();
25 let entry = file.read_u64::<LittleEndian>().unwrap();
26
27 Ok(((entry & 0x7fffffffffffffu64) * page_size as u64 + (ptr_val % page_size) as u64) as *const T)
28}
29
30#[cfg(test)]
31mod tests {
32 use crate::virt_to_phys;
33 #[test]
34 fn it_works() {
35 let my_num: i32 = 10;
36 let my_num_ptr: *const i32 = &my_num;
37 println!("ptr virt: {:?} ptr phys: {:?}", my_num_ptr, virt_to_phys(my_num_ptr).unwrap());
38 }
39}