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 buf.extend_from_slice(&temp[0..index]);
110 break;
111 }
112 None => {
113 buf.extend_from_slice(&temp);
115 addr += READ_CHUNK_SIZE;
116 }
117 }
118 }
119
120 String::from_utf8_lossy(&buf).into_owned()
121 }
122}