1use std::collections::BTreeMap;
2
3use vmm::Vmm;
4
5use crate::mem::NyxMemExtension;
6
7pub struct Breakpoint {
8 pub cr3: u64,
9 pub vaddr: u64,
10 pub orig_val: Option<u8>,
11 pub enabled: bool,
12}
13
14impl Breakpoint {
15 pub fn new(cr3: u64, vaddr: u64) -> Self {
16 return Self {
17 cr3,
18 vaddr,
19 orig_val: None,
20 enabled: false,
21 };
22 }
23}
24
25pub trait BreakpointManagerTrait {
27 fn known_breakpoint(&self, cr3: u64, rip: u64) -> bool;
29 fn disable_all_breakpoints(&mut self, vmm: &mut Vmm);
30 fn enable_all_breakpoints(&mut self, vmm: &mut Vmm);
31 fn disable_breakpoint(&mut self, vmm: &mut Vmm, _cr3: u64, _vaddr: u64) {
32 self.disable_all_breakpoints(vmm);
33 }
34 fn enable_breakpoint(&mut self, vmm: &mut Vmm, _cr3: u64, _vaddr: u64) {
35 self.enable_all_breakpoints(vmm);
36 }
37 fn add_breakpoint(&mut self, cr3: u64, vaddr: u64);
38 fn remove_breakpoint(&mut self, cr3: u64, vaddr: u64);
39 fn remove_all_breakpoints(&mut self);
40
41 fn forward_guest_bp(&self, cr3: u64, rip: u64) -> bool {
42 return !self.known_breakpoint(cr3, rip);
43 }
44}
45
46pub struct BreakpointManager {
47 pub breakpoints: BTreeMap<(u64, u64), Breakpoint>,
48 all_enabled: bool,
49}
50
51impl BreakpointManager {
52 pub fn new() -> Self {
53 return Self {
54 breakpoints: BTreeMap::new(),
55 all_enabled: false,
56 };
57 }
58}
59
60impl BreakpointManagerTrait for BreakpointManager {
61 fn known_breakpoint(&self, cr3: u64, rip: u64) -> bool {
62 let known_bp = self.breakpoints.contains_key(&(cr3, rip));
63 return known_bp;
64 }
65 fn disable_all_breakpoints(&mut self, vmm: &mut Vmm) {
66 for bp in self.breakpoints.values_mut() {
67 if !bp.enabled {
68 continue;
69 }
70 vmm.write_virtual_u8(bp.cr3, bp.vaddr, bp.orig_val.unwrap())
71 .unwrap();
72 bp.enabled = false;
73 }
74 self.all_enabled = false;
75 }
76 fn enable_all_breakpoints(&mut self, vmm: &mut Vmm) {
77 if self.all_enabled {
78 return;
79 }
80 for bp in self.breakpoints.values_mut() {
81 if bp.enabled {
82 continue;
83 }
84 if bp.orig_val.is_none() {
85 bp.orig_val = Some(vmm.read_virtual_u8(bp.cr3, bp.vaddr).unwrap());
86 }
87 vmm.write_virtual_u8(bp.cr3, bp.vaddr, 0xcc).unwrap();
88 bp.enabled = true;
89 }
90 self.all_enabled = true;
91 }
92 fn disable_breakpoint(&mut self, vmm: &mut Vmm, cr3: u64, vaddr: u64) {
93 if let Some(bp) = self.breakpoints.get_mut(&(cr3, vaddr)) {
94 if bp.enabled {
95 vmm.write_virtual_u8(bp.cr3, bp.vaddr, bp.orig_val.unwrap())
96 .unwrap();
97 bp.enabled = false;
98 self.all_enabled = false;
99 }
100 }
101 }
102 fn enable_breakpoint(&mut self, vmm: &mut Vmm, cr3: u64, vaddr: u64) {
103 if let Some(bp) = self.breakpoints.get_mut(&(cr3, vaddr)) {
104 if !bp.enabled {
105 if bp.orig_val.is_none() {
106 bp.orig_val = Some(vmm.read_virtual_u8(bp.cr3, bp.vaddr).unwrap());
107 }
108 vmm.write_virtual_u8(bp.cr3, bp.vaddr, 0xcc).unwrap();
109 bp.enabled = true;
110 }
111 }
112 }
113
114 fn add_breakpoint(&mut self, cr3: u64, vaddr: u64) {
115 let breakpoint = Breakpoint::new(cr3, vaddr);
116 self.breakpoints.insert((cr3, vaddr), breakpoint);
117 self.all_enabled = false;
118 }
119
120 fn remove_breakpoint(&mut self, cr3: u64, vaddr: u64) {
121 self.breakpoints.remove(&(cr3, vaddr));
122 self.all_enabled = false;
123 }
124 fn remove_all_breakpoints(&mut self) {
125 self.breakpoints.clear();
126 self.all_enabled = false;
127 }
128}