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