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