You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
1.8 KiB

use armv4t_emu::Memory;
pub enum AccessKind {
Read,
Write,
}
pub struct Access {
pub kind: AccessKind,
pub addr: u32,
pub val: u32,
pub len: usize,
}
/// Wraps a `Memory` object, logging any accesses with the provided callback.
#[derive(Debug)]
pub struct MemSniffer<'a, M, F: FnMut(Access)> {
mem: &'a mut M,
addrs: &'a [u32],
on_access: F,
}
impl<'a, M: Memory, F: FnMut(Access)> MemSniffer<'a, M, F> {
pub fn new(mem: &'a mut M, addrs: &'a [u32], on_access: F) -> MemSniffer<'a, M, F> {
MemSniffer {
mem,
addrs,
on_access,
}
}
}
macro_rules! impl_memsniff_r {
($fn:ident, $ret:ty) => {
fn $fn(&mut self, addr: u32) -> $ret {
let ret = self.mem.$fn(addr);
if self.addrs.contains(&addr) {
(self.on_access)(Access {
kind: AccessKind::Read,
addr,
val: ret as u32,
len: ret.to_le_bytes().len(),
});
}
ret
}
};
}
macro_rules! impl_memsniff_w {
($fn:ident, $val:ty) => {
fn $fn(&mut self, addr: u32, val: $val) {
self.mem.$fn(addr, val);
if self.addrs.contains(&addr) {
(self.on_access)(Access {
kind: AccessKind::Write,
addr,
val: val as u32,
len: val.to_le_bytes().len(),
});
}
}
};
}
impl<'a, M: Memory, F: FnMut(Access)> Memory for MemSniffer<'a, M, F> {
impl_memsniff_r!(r8, u8);
impl_memsniff_r!(r16, u16);
impl_memsniff_r!(r32, u32);
impl_memsniff_w!(w8, u8);
impl_memsniff_w!(w16, u16);
impl_memsniff_w!(w32, u32);
}