1 //! Base debugging operations for single threaded targets.
2 
3 use crate::arch::Arch;
4 use crate::common::Signal;
5 use crate::target::Target;
6 use crate::target::TargetResult;
7 
8 /// Base required debugging operations for single threaded targets.
9 pub trait SingleThreadBase: Target {
10     /// Read the target's registers.
read_registers( &mut self, regs: &mut <Self::Arch as Arch>::Registers, ) -> TargetResult<(), Self>11     fn read_registers(
12         &mut self,
13         regs: &mut <Self::Arch as Arch>::Registers,
14     ) -> TargetResult<(), Self>;
15 
16     /// Write the target's registers.
write_registers(&mut self, regs: &<Self::Arch as Arch>::Registers) -> TargetResult<(), Self>17     fn write_registers(&mut self, regs: &<Self::Arch as Arch>::Registers)
18         -> TargetResult<(), Self>;
19 
20     /// Support for single-register access.
21     /// See [`SingleRegisterAccess`] for more details.
22     ///
23     /// While this is an optional feature, it is **highly recommended** to
24     /// implement it when possible, as it can significantly improve performance
25     /// on certain architectures.
26     ///
27     /// [`SingleRegisterAccess`]:
28     /// super::single_register_access::SingleRegisterAccess
29     #[inline(always)]
support_single_register_access( &mut self, ) -> Option<super::single_register_access::SingleRegisterAccessOps<'_, (), Self>>30     fn support_single_register_access(
31         &mut self,
32     ) -> Option<super::single_register_access::SingleRegisterAccessOps<'_, (), Self>> {
33         None
34     }
35 
36     /// Read bytes from the specified address range and return the number of
37     /// bytes that were read.
38     ///
39     /// Implementations may return a number `n` that is less than `data.len()`
40     /// to indicate that memory starting at `start_addr + n` cannot be
41     /// accessed.
42     ///
43     /// Implemenations may also return an appropriate non-fatal error if the
44     /// requested address range could not be accessed (e.g: due to MMU
45     /// protection, unhanded page fault, etc...).
46     ///
47     /// Implementations must guarantee that the returned number is less than or
48     /// equal `data.len()`.
read_addrs( &mut self, start_addr: <Self::Arch as Arch>::Usize, data: &mut [u8], ) -> TargetResult<usize, Self>49     fn read_addrs(
50         &mut self,
51         start_addr: <Self::Arch as Arch>::Usize,
52         data: &mut [u8],
53     ) -> TargetResult<usize, Self>;
54 
55     /// Write bytes to the specified address range.
56     ///
57     /// If the requested address range could not be accessed (e.g: due to
58     /// MMU protection, unhanded page fault, etc...), an appropriate
59     /// non-fatal error should be returned.
write_addrs( &mut self, start_addr: <Self::Arch as Arch>::Usize, data: &[u8], ) -> TargetResult<(), Self>60     fn write_addrs(
61         &mut self,
62         start_addr: <Self::Arch as Arch>::Usize,
63         data: &[u8],
64     ) -> TargetResult<(), Self>;
65 
66     /// Support for resuming the target (e.g: via `continue` or `step`)
67     #[inline(always)]
support_resume(&mut self) -> Option<SingleThreadResumeOps<'_, Self>>68     fn support_resume(&mut self) -> Option<SingleThreadResumeOps<'_, Self>> {
69         None
70     }
71 }
72 
73 /// Target extension - support for resuming single threaded targets.
74 pub trait SingleThreadResume: Target {
75     /// Resume execution on the target.
76     ///
77     /// The GDB client may also include a `signal` which should be passed to the
78     /// target.
79     ///
80     /// # Additional Considerations
81     ///
82     /// ### Adjusting PC after a breakpoint is hit
83     ///
84     /// The [GDB remote serial protocol documentation](https://sourceware.org/gdb/current/onlinedocs/gdb/Stop-Reply-Packets.html#swbreak-stop-reason)
85     /// notes the following:
86     ///
87     /// > On some architectures, such as x86, at the architecture level, when a
88     /// > breakpoint instruction executes the program counter points at the
89     /// > breakpoint address plus an offset. On such targets, the stub is
90     /// > responsible for adjusting the PC to point back at the breakpoint
91     /// > address.
92     ///
93     /// Omitting PC adjustment may result in unexpected execution flow and/or
94     /// breakpoints not appearing to work correctly.
resume(&mut self, signal: Option<Signal>) -> Result<(), Self::Error>95     fn resume(&mut self, signal: Option<Signal>) -> Result<(), Self::Error>;
96 
97     /// Support for optimized [single stepping].
98     ///
99     /// [single stepping]: https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#index-stepi
100     #[inline(always)]
support_single_step(&mut self) -> Option<SingleThreadSingleStepOps<'_, Self>>101     fn support_single_step(&mut self) -> Option<SingleThreadSingleStepOps<'_, Self>> {
102         None
103     }
104 
105     /// Support for optimized [range stepping].
106     ///
107     /// [range stepping]: https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#range-stepping
108     #[inline(always)]
support_range_step(&mut self) -> Option<SingleThreadRangeSteppingOps<'_, Self>>109     fn support_range_step(&mut self) -> Option<SingleThreadRangeSteppingOps<'_, Self>> {
110         None
111     }
112 
113     /// Support for [reverse stepping] a target.
114     ///
115     /// [reverse stepping]: https://sourceware.org/gdb/current/onlinedocs/gdb/Reverse-Execution.html
116     #[inline(always)]
support_reverse_step( &mut self, ) -> Option<super::reverse_exec::ReverseStepOps<'_, (), Self>>117     fn support_reverse_step(
118         &mut self,
119     ) -> Option<super::reverse_exec::ReverseStepOps<'_, (), Self>> {
120         None
121     }
122 
123     /// Support for [reverse continuing] a target.
124     ///
125     /// [reverse continuing]: https://sourceware.org/gdb/current/onlinedocs/gdb/Reverse-Execution.html
126     #[inline(always)]
support_reverse_cont( &mut self, ) -> Option<super::reverse_exec::ReverseContOps<'_, (), Self>>127     fn support_reverse_cont(
128         &mut self,
129     ) -> Option<super::reverse_exec::ReverseContOps<'_, (), Self>> {
130         None
131     }
132 }
133 
134 define_ext!(SingleThreadResumeOps, SingleThreadResume);
135 
136 /// Target Extension - Optimized single stepping for single threaded targets.
137 /// See [`SingleThreadResume::support_single_step`].
138 pub trait SingleThreadSingleStep: Target + SingleThreadResume {
139     /// [Single step] the target.
140     ///
141     /// Single stepping will step the target a single "step" - typically a
142     /// single instruction.
143     /// The GDB client may also include a `signal` which should be passed to the
144     /// target.
145     ///
146     /// [Single step]: https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#index-stepi
step(&mut self, signal: Option<Signal>) -> Result<(), Self::Error>147     fn step(&mut self, signal: Option<Signal>) -> Result<(), Self::Error>;
148 }
149 
150 define_ext!(SingleThreadSingleStepOps, SingleThreadSingleStep);
151 
152 /// Target Extension - Optimized range stepping for single threaded targets.
153 /// See [`SingleThreadResume::support_range_step`].
154 pub trait SingleThreadRangeStepping: Target + SingleThreadResume {
155     /// [Range step] the target.
156     ///
157     /// Range Stepping will step the target once, and keep stepping the target
158     /// as long as execution remains between the specified start (inclusive)
159     /// and end (exclusive) addresses, or another stop condition is met
160     /// (e.g: a breakpoint it hit).
161     ///
162     /// If the range is empty (`start` == `end`), then the action becomes
163     /// equivalent to the ‘s’ action. In other words, single-step once, and
164     /// report the stop (even if the stepped instruction jumps to start).
165     ///
166     /// _Note:_ A stop reply may be sent at any point even if the PC is still
167     /// within the stepping range; for example, it is valid to implement range
168     /// stepping in a degenerate way as a single instruction step operation.
169     ///
170     /// [Range step]: https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html#range-stepping
resume_range_step( &mut self, start: <Self::Arch as Arch>::Usize, end: <Self::Arch as Arch>::Usize, ) -> Result<(), Self::Error>171     fn resume_range_step(
172         &mut self,
173         start: <Self::Arch as Arch>::Usize,
174         end: <Self::Arch as Arch>::Usize,
175     ) -> Result<(), Self::Error>;
176 }
177 
178 define_ext!(SingleThreadRangeSteppingOps, SingleThreadRangeStepping);
179