vmi_utils/bpm/controller/
breakpoint.rs1use vmi_core::{
2 Architecture, Gfn, MemoryAccess, Pa, Registers as _, Va, View, VmiCore, VmiDriver, VmiError,
3 VmiEvent,
4 arch::{EventInterrupt as _, EventReason},
5};
6
7use super::TapController;
8use crate::interceptor::Interceptor;
9
10#[doc = include_str!("breakpoint.md")]
11pub struct BreakpointController<Driver>
12where
13 Driver: VmiDriver,
14 <Driver::Architecture as Architecture>::EventReason:
15 EventReason<Architecture = Driver::Architecture>,
16{
17 interceptor: Interceptor<Driver>,
18}
19
20impl<Driver> BreakpointController<Driver>
21where
22 Driver: VmiDriver,
23 <Driver::Architecture as Architecture>::EventReason:
24 EventReason<Architecture = Driver::Architecture>,
25{
26 pub fn is_breakpoint(
28 vmi: &VmiCore<Driver>,
29 event: &VmiEvent<Driver::Architecture>,
30 ) -> Result<bool, VmiError> {
31 let interrupt = match event.reason().as_software_breakpoint() {
32 Some(interrupt) => interrupt,
33 None => return Ok(false),
34 };
35
36 let va = Va(event.registers().instruction_pointer());
37 let pa = Driver::Architecture::pa_from_gfn(interrupt.gfn())
38 + Driver::Architecture::va_offset(va);
39
40 let mut content = vec![0; Driver::Architecture::BREAKPOINT.len()];
41 vmi.read(pa, &mut content)?;
42
43 Ok(content == Driver::Architecture::BREAKPOINT)
44 }
45}
46
47impl<Driver> TapController for BreakpointController<Driver>
48where
49 Driver: VmiDriver,
50 <Driver::Architecture as Architecture>::EventReason:
51 EventReason<Architecture = Driver::Architecture>,
52{
53 type Driver = Driver;
54
55 fn new() -> Self {
56 Self {
57 interceptor: Interceptor::new(),
58 }
59 }
60
61 fn check_event(&self, event: &VmiEvent<Driver::Architecture>) -> Option<(View, Gfn)> {
62 let interrupt = event.reason().as_software_breakpoint()?;
63 let view = event.view()?;
64
65 Some((view, interrupt.gfn()))
66 }
67
68 fn insert_breakpoint(
69 &mut self,
70 vmi: &VmiCore<Driver>,
71 pa: Pa,
72 view: View,
73 ) -> Result<(), VmiError> {
74 self.interceptor.insert_breakpoint(vmi, pa, view)?;
75 Ok(())
76 }
77
78 fn remove_breakpoint(
79 &mut self,
80 vmi: &VmiCore<Driver>,
81 pa: Pa,
82 view: View,
83 ) -> Result<(), VmiError> {
84 let breakpoint_was_removed = self.interceptor.remove_breakpoint(vmi, pa, view)?;
85 debug_assert_eq!(breakpoint_was_removed, Some(true));
86 Ok(())
87 }
88
89 fn monitor(&mut self, vmi: &VmiCore<Driver>, gfn: Gfn, view: View) -> Result<(), VmiError> {
90 vmi.set_memory_access(gfn, view, MemoryAccess::X)
91 }
92
93 fn unmonitor(&mut self, vmi: &VmiCore<Driver>, gfn: Gfn, view: View) -> Result<(), VmiError> {
94 vmi.set_memory_access(gfn, view, MemoryAccess::RWX)
95 }
96}