1use crate::enums::MemRWStatus;
2use crate::prelude::*;
3use crate::GuestType;
4use crate::{sys, Error};
5use crate::{GuestReadFail, GuestWriteFail};
6
7use std::ffi::CString;
8use std::os::raw::c_char;
9
10pub fn read_guest_type<T: GuestType>(
28 cpu: &mut CPUState,
29 addr: target_ptr_t,
30) -> Result<T, GuestReadFail> {
31 T::read_from_guest(cpu, addr)
32}
33
34pub fn write_guest_type<T: GuestType>(
49 cpu: &mut CPUState,
50 addr: target_ptr_t,
51 val: &T,
52) -> Result<(), GuestWriteFail> {
53 val.write_to_guest(cpu, addr)
54}
55
56pub fn read_guest_type_phys<T: GuestType>(addr: target_ptr_t) -> Result<T, GuestReadFail> {
70 T::read_from_guest_phys(addr)
71}
72
73pub fn write_guest_type_phys<T: GuestType>(
88 addr: target_ptr_t,
89 val: &T,
90) -> Result<(), GuestWriteFail> {
91 val.write_to_guest_phys(addr)
92}
93
94pub fn virtual_memory_read(
96 cpu: &mut CPUState,
97 addr: target_ulong,
98 len: usize,
99) -> Result<Vec<u8>, MemRWStatus> {
100 let mut buf: Vec<c_char> = Vec::with_capacity(len);
101
102 unsafe {
103 let res =
104 panda_sys::panda_virtual_memory_read_external(cpu, addr, buf.as_mut_ptr(), len as i32)
105 .into();
106
107 match res {
108 MemRWStatus::MemTxOk => {
109 buf.set_len(len);
110 Ok(vec_i8_into_u8(buf))
111 }
112 _ => Err(res),
113 }
114 }
115}
116
117pub fn virtual_memory_read_into(
119 cpu: &mut CPUState,
120 addr: target_ulong,
121 buf: &mut [u8],
122) -> Result<(), MemRWStatus> {
123 let res = unsafe {
124 panda_sys::panda_virtual_memory_read_external(
125 cpu,
126 addr,
127 buf.as_mut_ptr() as _,
128 buf.len() as i32,
129 )
130 .into()
131 };
132
133 match res {
134 MemRWStatus::MemTxOk => Ok(()),
135 _ => Err(res),
136 }
137}
138
139pub fn physical_memory_read(addr: target_ulong, len: usize) -> Result<Vec<u8>, MemRWStatus> {
141 let mut buf: Vec<u8> = Vec::with_capacity(len);
142
143 unsafe {
144 let res = panda_sys::panda_physical_memory_read_external(
145 addr as u64,
146 buf.as_mut_ptr(),
147 len as i32,
148 )
149 .into();
150
151 match res {
152 MemRWStatus::MemTxOk => {
153 buf.set_len(len);
154 Ok(buf)
155 }
156 _ => Err(res),
157 }
158 }
159}
160
161pub fn physical_memory_read_into(addr: target_ulong, buf: &mut [u8]) -> Result<(), MemRWStatus> {
163 let res = unsafe {
164 panda_sys::panda_physical_memory_read_external(
165 addr as u64,
166 buf.as_mut_ptr() as _,
167 buf.len() as i32,
168 )
169 .into()
170 };
171
172 match res {
173 MemRWStatus::MemTxOk => Ok(()),
174 _ => Err(res),
175 }
176}
177
178pub fn virtual_memory_write(cpu: &mut CPUState, addr: target_ulong, data: &[u8]) -> MemRWStatus {
180 let mut c_data = data.to_vec(); unsafe {
182 panda_sys::panda_virtual_memory_write_external(
183 cpu,
184 addr,
185 c_data.as_mut_ptr() as *mut c_char,
186 c_data.len() as i32,
187 )
188 .into()
189 }
190}
191
192pub fn physical_memory_write(addr: target_ulong, data: &[u8]) -> MemRWStatus {
194 let mut c_data = data.to_vec(); unsafe {
196 panda_sys::panda_physical_memory_write_external(
197 addr as _,
198 c_data.as_mut_ptr(),
199 c_data.len() as i32,
200 )
201 .into()
202 }
203}
204
205pub fn virt_to_phys(cpu: &mut CPUState, addr: target_ulong) -> Option<target_ulong> {
208 match unsafe { panda_sys::panda_virt_to_phys_external(cpu, addr) } {
209 target_ulong::MAX => None,
210 phys_addr => Some(phys_addr),
211 }
212}
213
214pub const PAGE_SIZE: target_ulong = 1024;
215
216pub fn map_memory(name: &str, size: target_ulong, addr: target_ptr_t) -> Result<(), Error> {
218 let name = CString::new(name)?;
219
220 if size % PAGE_SIZE != 0 {
221 Err(Error::UnalignedPageSize)
222 } else {
223 unsafe {
224 sys::map_memory(name.as_ptr() as _, size as _, addr as _);
225 }
226
227 drop(name);
228
229 Ok(())
230 }
231}
232
233const IS_32_BIT: bool = std::mem::size_of::<target_ptr_t>() == 4;
234const TARGET_BITS: usize = std::mem::size_of::<target_ptr_t>() * 8;
235
236fn hex_addr(addr: target_ptr_t) -> impl std::fmt::Display {
237 if IS_32_BIT {
238 format!("{:08x}", addr)
239 } else {
240 format!("{:016x}", addr)
241 }
242}
243
244pub fn virt_memory_dump(cpu: &mut CPUState, addr: target_ptr_t, len: usize) {
245 let memory = virtual_memory_read(cpu, addr, len).unwrap();
246
247 let start_addr_aligned = addr & !0xf;
248 let end_addr_aligned = (addr + (len as target_ptr_t)) & !0xf;
249
250 let bytes_offset = addr - start_addr_aligned;
251
252 let hex_dump = (start_addr_aligned..=end_addr_aligned)
253 .step_by(0x10)
254 .enumerate()
255 .map(|(line_num, line_addr)| {
256 let hex_data = (0..0x10)
257 .map(|offset_in_line| {
258 if line_num == 0 && offset_in_line < (bytes_offset as usize) {
259 " ".into()
260 } else {
261 let byte_index =
262 ((line_num * 0x10) + offset_in_line) - (bytes_offset as usize);
263
264 if let Some(byte) = memory.get(byte_index) {
265 format!("{:02x}", byte).into()
266 } else {
267 " ".into()
268 }
269 }
270 })
271 .collect::<Vec<std::borrow::Cow<'static, str>>>()
272 .join(" ");
273
274 format!("{}║{}\n", hex_addr(line_addr), hex_data)
275 })
276 .collect::<String>();
277
278 println!(
279 "{} 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f",
280 " ".repeat(TARGET_BITS / 4)
281 );
282 println!(
283 "{}╦═══════════════════════════════════════════════",
284 "═".repeat(TARGET_BITS / 4)
285 );
286 println!("{}", hex_dump);
287}
288
289fn vec_i8_into_u8(v: Vec<c_char>) -> Vec<u8> {
294 let mut v = std::mem::ManuallyDrop::new(v);
296
297 let p = v.as_mut_ptr();
299 let len = v.len();
300 let cap = v.capacity();
301
302 unsafe { Vec::from_raw_parts(p as *mut u8, len, cap) }
304}