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