nyx_lite/
hw_breakpoints.rs1#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
2pub enum HwBreakpointMode {
3 Exec,
4 Write,
5 ReadWrite,
6}
7
8impl HwBreakpointMode {
9 pub fn bits(&self) -> u64 {
10 match self {
11 Self::Exec => 0b00,
12 Self::Write => 0b01,
13 Self::ReadWrite => 0b11,
14 }
15 }
16}
17
18#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
19pub struct HwBreakpoint {
20 pub addr: u64,
21 pub size: usize,
22 pub mode: HwBreakpointMode,
23}
24
25impl HwBreakpoint {
26 pub fn apply_dr7(&self, bp_index: usize, dr7: u64) -> u64 {
27 assert!(bp_index < 4);
28 const L: usize = 0;
29 const G: usize = 1;
30 const RW: usize = 16; const LEN: usize = 18; let mask = (1 << L | 1 << G) << (bp_index * 2) | ((3 << RW | 3 << LEN) << bp_index * 4);
33 let dr7 = dr7 & !(mask << bp_index);
34 let dr7 = dr7
35 | ((1 << L | 1 << G) << bp_index * 2)
36 | (self.mode.bits() << RW | self.size_bits() << LEN) << bp_index * 4;
37 const LE_AND_LG: usize = 8; let dr7 = dr7 | 0b11 << LE_AND_LG; return dr7;
40 }
41 pub fn size_bits(&self) -> u64 {
42 return match self.size {
43 1 => 0b00,
44 2 => 0b01,
45 4 => 0b11,
46 8 => 0b10,
47 _ => panic!("invalid hw breakpoint size"),
48 };
49 }
50}
51
52pub struct HwBreakpoints {
53 pub bps: [Option<HwBreakpoint>; 4],
54}
55
56impl HwBreakpoints {
57 pub fn new() -> Self {
58 return Self {
59 bps: [None, None, None, None],
60 };
61 }
62 pub fn enable(&mut self, i: usize, addr: u64, size: usize, mode: HwBreakpointMode) {
63 if mode == HwBreakpointMode::Exec {
64 assert_eq!(size, 1);
65 }
66 self.bps[i] = Some(HwBreakpoint { addr, size, mode })
67 }
68 pub fn enable_access(&mut self, i: usize, addr: u64, size: usize) {
69 self.enable(i, addr, size, HwBreakpointMode::ReadWrite);
70 }
71 pub fn enable_write(&mut self, i: usize, addr: u64, size: usize) {
72 self.enable(i, addr, size, HwBreakpointMode::Write);
73 }
74 pub fn enable_exec(&mut self, i: usize, addr: u64) {
75 self.enable(i, addr, 1, HwBreakpointMode::Exec);
76 }
77
78 pub fn disable(&mut self, i: usize) {
79 self.bps[i] = None;
80 }
81 pub fn addr(&self, i: usize) -> u64 {
82 if let Some(ref bp) = self.bps[i] {
83 return bp.addr;
84 }
85 return 0;
86 }
87 pub fn compute_dr7(&self) -> u64 {
88 let mut dr7 = 0;
89 for i in 0..4 {
90 if let Some(ref bp) = self.bps[i] {
91 dr7 = bp.apply_dr7(i, dr7);
92 }
93 }
94 return dr7;
95 }
96
97 pub fn any_active(&self) -> bool {
98 self.bps.iter().any(|b| b.is_some())
99 }
100}