• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Add/Remove various kinds of breakpoints.
2 
3 use crate::arch::Arch;
4 use crate::target::{Target, TargetResult};
5 
6 /// Target Extension - Set/Remove Breakpoints.
7 pub trait Breakpoints: Target {
8     /// Set/Remote software breakpoints.
9     #[inline(always)]
sw_breakpoint(&mut self) -> Option<SwBreakpointOps<Self>>10     fn sw_breakpoint(&mut self) -> Option<SwBreakpointOps<Self>> {
11         None
12     }
13 
14     /// Set/Remote hardware breakpoints.
15     #[inline(always)]
hw_breakpoint(&mut self) -> Option<HwBreakpointOps<Self>>16     fn hw_breakpoint(&mut self) -> Option<HwBreakpointOps<Self>> {
17         None
18     }
19 
20     /// Set/Remote hardware watchpoints.
21     #[inline(always)]
hw_watchpoint(&mut self) -> Option<HwWatchpointOps<Self>>22     fn hw_watchpoint(&mut self) -> Option<HwWatchpointOps<Self>> {
23         None
24     }
25 }
26 
27 define_ext!(BreakpointsOps, Breakpoints);
28 
29 /// Nested Target Extension - Set/Remove Software Breakpoints.
30 ///
31 /// See [this stackoverflow discussion](https://stackoverflow.com/questions/8878716/what-is-the-difference-between-hardware-and-software-breakpoints)
32 /// about the differences between hardware and software breakpoints.
33 ///
34 /// _Recommendation:_ If you're implementing `Target` for an emulator that's
35 /// using an _interpreted_ CPU (as opposed to a JIT), the simplest way to
36 /// implement "software" breakpoints would be to check the `PC` value after each
37 /// CPU cycle, ignoring the specified breakpoint `kind` entirely.
38 pub trait SwBreakpoint: Target + Breakpoints {
39     /// Add a new software breakpoint.
40     /// Return `Ok(false)` if the operation could not be completed.
add_sw_breakpoint( &mut self, addr: <Self::Arch as Arch>::Usize, kind: <Self::Arch as Arch>::BreakpointKind, ) -> TargetResult<bool, Self>41     fn add_sw_breakpoint(
42         &mut self,
43         addr: <Self::Arch as Arch>::Usize,
44         kind: <Self::Arch as Arch>::BreakpointKind,
45     ) -> TargetResult<bool, Self>;
46 
47     /// Remove an existing software breakpoint.
48     /// Return `Ok(false)` if the operation could not be completed.
remove_sw_breakpoint( &mut self, addr: <Self::Arch as Arch>::Usize, kind: <Self::Arch as Arch>::BreakpointKind, ) -> TargetResult<bool, Self>49     fn remove_sw_breakpoint(
50         &mut self,
51         addr: <Self::Arch as Arch>::Usize,
52         kind: <Self::Arch as Arch>::BreakpointKind,
53     ) -> TargetResult<bool, Self>;
54 }
55 
56 define_ext!(SwBreakpointOps, SwBreakpoint);
57 
58 /// Nested Target Extension - Set/Remove Hardware Breakpoints.
59 ///
60 /// See [this stackoverflow discussion](https://stackoverflow.com/questions/8878716/what-is-the-difference-between-hardware-and-software-breakpoints)
61 /// about the differences between hardware and software breakpoints.
62 ///
63 /// _Recommendation:_ If you're implementing `Target` for an emulator that's
64 /// using an _interpreted_ CPU (as opposed to a JIT), there shouldn't be any
65 /// reason to implement this extension (as software breakpoints are likely to be
66 /// just-as-fast).
67 pub trait HwBreakpoint: Target + Breakpoints {
68     /// Add a new hardware breakpoint.
69     /// Return `Ok(false)` if the operation could not be completed.
add_hw_breakpoint( &mut self, addr: <Self::Arch as Arch>::Usize, kind: <Self::Arch as Arch>::BreakpointKind, ) -> TargetResult<bool, Self>70     fn add_hw_breakpoint(
71         &mut self,
72         addr: <Self::Arch as Arch>::Usize,
73         kind: <Self::Arch as Arch>::BreakpointKind,
74     ) -> TargetResult<bool, Self>;
75 
76     /// Remove an existing hardware breakpoint.
77     /// Return `Ok(false)` if the operation could not be completed.
remove_hw_breakpoint( &mut self, addr: <Self::Arch as Arch>::Usize, kind: <Self::Arch as Arch>::BreakpointKind, ) -> TargetResult<bool, Self>78     fn remove_hw_breakpoint(
79         &mut self,
80         addr: <Self::Arch as Arch>::Usize,
81         kind: <Self::Arch as Arch>::BreakpointKind,
82     ) -> TargetResult<bool, Self>;
83 }
84 
85 define_ext!(HwBreakpointOps, HwBreakpoint);
86 
87 /// The kind of watchpoint that should be set/removed.
88 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
89 pub enum WatchKind {
90     /// Fire when the memory location is written to.
91     Write,
92     /// Fire when the memory location is read from.
93     Read,
94     /// Fire when the memory location is written to and/or read from.
95     ReadWrite,
96 }
97 
98 /// Nested Target Extension - Set/Remove Hardware Watchpoints.
99 ///
100 /// See the [GDB documentation](https://sourceware.org/gdb/current/onlinedocs/gdb/Set-Watchpoints.html)
101 /// regarding watchpoints for how they're supposed to work.
102 ///
103 /// _Note:_ If this extension isn't implemented, GDB will default to using
104 /// _software watchpoints_, which tend to be excruciatingly slow (as hey are
105 /// implemented by single-stepping the system, and reading the watched memory
106 /// location after each step).
107 pub trait HwWatchpoint: Target + Breakpoints {
108     /// Add a new hardware watchpoint.
109     /// Return `Ok(false)` if the operation could not be completed.
add_hw_watchpoint( &mut self, addr: <Self::Arch as Arch>::Usize, kind: WatchKind, ) -> TargetResult<bool, Self>110     fn add_hw_watchpoint(
111         &mut self,
112         addr: <Self::Arch as Arch>::Usize,
113         kind: WatchKind,
114     ) -> TargetResult<bool, Self>;
115 
116     /// Remove an existing hardware watchpoint.
117     /// Return `Ok(false)` if the operation could not be completed.
remove_hw_watchpoint( &mut self, addr: <Self::Arch as Arch>::Usize, kind: WatchKind, ) -> TargetResult<bool, Self>118     fn remove_hw_watchpoint(
119         &mut self,
120         addr: <Self::Arch as Arch>::Usize,
121         kind: WatchKind,
122     ) -> TargetResult<bool, Self>;
123 }
124 
125 define_ext!(HwWatchpointOps, HwWatchpoint);
126