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