1 use armv4t_emu::Memory; 2 3 pub enum AccessKind { 4 Read, 5 Write, 6 } 7 8 pub struct Access { 9 pub kind: AccessKind, 10 pub addr: u32, 11 pub val: u32, 12 pub len: usize, 13 } 14 15 /// Wraps a `Memory` object, logging any accesses with the provided callback. 16 #[derive(Debug)] 17 pub struct MemSniffer<'a, M, F: FnMut(Access)> { 18 mem: &'a mut M, 19 addrs: &'a [u32], 20 on_access: F, 21 } 22 23 impl<'a, M: Memory, F: FnMut(Access)> MemSniffer<'a, M, F> { new(mem: &'a mut M, addrs: &'a [u32], on_access: F) -> MemSniffer<'a, M, F>24 pub fn new(mem: &'a mut M, addrs: &'a [u32], on_access: F) -> MemSniffer<'a, M, F> { 25 MemSniffer { 26 mem, 27 addrs, 28 on_access, 29 } 30 } 31 } 32 33 macro_rules! impl_memsniff_r { 34 ($fn:ident, $ret:ty) => { 35 fn $fn(&mut self, addr: u32) -> $ret { 36 let ret = self.mem.$fn(addr); 37 if self.addrs.contains(&addr) { 38 (self.on_access)(Access { 39 kind: AccessKind::Read, 40 addr, 41 val: ret as u32, 42 len: ret.to_le_bytes().len(), 43 }); 44 } 45 ret 46 } 47 }; 48 } 49 50 macro_rules! impl_memsniff_w { 51 ($fn:ident, $val:ty) => { 52 fn $fn(&mut self, addr: u32, val: $val) { 53 self.mem.$fn(addr, val); 54 if self.addrs.contains(&addr) { 55 (self.on_access)(Access { 56 kind: AccessKind::Write, 57 addr, 58 val: val as u32, 59 len: val.to_le_bytes().len(), 60 }); 61 } 62 } 63 }; 64 } 65 66 impl<'a, M: Memory, F: FnMut(Access)> Memory for MemSniffer<'a, M, F> { 67 impl_memsniff_r!(r8, u8); 68 impl_memsniff_r!(r16, u16); 69 impl_memsniff_r!(r32, u32); 70 impl_memsniff_w!(w8, u8); 71 impl_memsniff_w!(w16, u16); 72 impl_memsniff_w!(w32, u32); 73 } 74