panda_sys/
extensions.rs

1use crate::{
2    panda_physical_memory_read_external, panda_virtual_memory_read_external,
3    panda_virtual_memory_write_external, target_ptr_t, target_ulong, CPUState,
4};
5use std::ffi::c_char;
6use std::mem::{size_of, transmute, MaybeUninit};
7
8const READ_CHUNK_SIZE: target_ptr_t = 0x10;
9
10impl CPUState {
11    pub fn mem_read(&mut self, addr: target_ulong, len: usize) -> Vec<u8> {
12        let mut temp = vec![0; len];
13
14        unsafe {
15            if panda_virtual_memory_read_external(
16                self,
17                addr,
18                temp.as_mut_ptr() as *mut c_char,
19                len as _,
20            ) != 0
21            {
22                panic!("Virtual memory read failed");
23            }
24        }
25
26        temp
27    }
28
29    pub fn mem_write(&mut self, addr: target_ulong, data: &[u8]) {
30        unsafe {
31            if panda_virtual_memory_write_external(
32                self,
33                addr,
34                transmute(data.as_ptr()),
35                data.len() as _,
36            ) != 0
37            {
38                panic!("Virtual memory write failed");
39            }
40        }
41    }
42
43    pub fn try_mem_read(&mut self, addr: target_ulong, len: usize) -> Option<Vec<u8>> {
44        let mut temp = vec![0; len];
45
46        let ret = unsafe {
47            panda_virtual_memory_read_external(
48                self,
49                addr,
50                temp.as_mut_ptr() as *mut c_char,
51                len as _,
52            )
53        };
54
55        if ret == 0 {
56            Some(temp)
57        } else {
58            None
59        }
60    }
61
62    pub fn try_mem_read_phys(&mut self, addr: target_ptr_t, len: usize) -> Option<Vec<u8>> {
63        let mut temp = vec![0; len];
64
65        unsafe {
66            if panda_physical_memory_read_external(addr as _, temp.as_mut_ptr(), len as _) == 0 {
67                Some(temp)
68            } else {
69                None
70            }
71        }
72    }
73
74    pub fn mem_read_val<T: Sized>(&mut self, addr: target_ulong) -> T {
75        let mut temp = MaybeUninit::uninit();
76
77        unsafe {
78            if panda_virtual_memory_read_external(
79                self,
80                addr,
81                temp.as_mut_ptr() as *mut c_char,
82                size_of::<T>() as _,
83            ) != 0
84            {
85                panic!("Virtual memory read failed");
86            }
87
88            temp.assume_init()
89        }
90    }
91
92    pub fn mem_read_string(&mut self, mut addr: target_ptr_t) -> String {
93        let mut buf = vec![];
94        let mut temp = [0; READ_CHUNK_SIZE as usize];
95        loop {
96            unsafe {
97                panda_virtual_memory_read_external(
98                    self,
99                    addr,
100                    temp.as_mut_ptr() as *mut c_char,
101                    READ_CHUNK_SIZE as _,
102                );
103            }
104
105            let null_index = temp.iter().position(|x| x == &0);
106            match null_index {
107                Some(index) => {
108                    // A null exists in the current chunk
109                    buf.extend_from_slice(&temp[0..index]);
110                    break;
111                }
112                None => {
113                    // No null byte found yet
114                    buf.extend_from_slice(&temp);
115                    addr += READ_CHUNK_SIZE;
116                }
117            }
118        }
119
120        String::from_utf8_lossy(&buf).into_owned()
121    }
122}