v2p/
lib.rs

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}