1 //! Everything related to the [`Target`] trait + associated extension traits. 2 //! 3 //! The [`Target`] trait describes how to control and modify a system's 4 //! execution state during a GDB debugging session, and serves as the 5 //! primary bridge between `gdbstub`'s generic protocol implementation and a 6 //! target's project/platform-specific code. 7 //! 8 //! **`Target` is the most important trait in `gdbstub`, and must be implemented 9 //! by all consumers of the library!** 10 //! 11 //! # Implementing `Target` 12 //! 13 //! `gdbstub` uses a technique called "Inlineable Dyn Extension Traits" (IDETs) 14 //! to expose an ergonomic and extensible interface to the GDB protocol. It's 15 //! not a very common pattern, and can seem a little "weird" at first glance, 16 //! but it's actually very straightforward to use! 17 //! 18 //! Please refer to the [documentation in the `ext` module](ext) for more 19 //! information on IDETs, and how they're used to implement `Target` and it's 20 //! various extension traits. 21 //! 22 //! **TL;DR:** Whenever you see a method that has `Option<FooOps>` in the return 23 //! type, that method should return `Some(self)` if the extension is 24 //! implemented, or `None` if it's unimplemented / disabled. 25 //! 26 //! ## Associated Types 27 //! 28 //! - The [`Target::Arch`](trait.Target.html#associatedtype.Arch) associated 29 //! type encodes information about the target's architecture, such as it's 30 //! pointer size, register layout, etc... `gdbstub` comes with several 31 //! built-in architecture definitions, which can be found under the 32 //! [`arch`](../arch/index.html) module. 33 //! 34 //! - The [`Target::Error`](trait.Target.html#associatedtype.Error) associated 35 //! type allows implementors to plumb-through their own project-specific fatal 36 //! error type into the `Target` trait. This is a big-boost to library 37 //! ergonomics, as it enables consumers of `gdbstub` to preserve 38 //! target-specific context while using `gdbstub`, without having to do any 39 //! "error-stashing". 40 //! 41 //! For example: consider an emulated target where certain devices might return 42 //! a `MyEmuError::ContractViolation` error whenever they're accessed 43 //! "improperly" (e.g: setting registers in the wrong order). By setting `type 44 //! Error = MyEmuError`, the method signature of the `Target`'s `resume` method 45 //! becomes `fn resume(&mut self, ...) -> Result<_, MyEmuError>`, which makes it 46 //! possible to preserve the target-specific error while using `gdbstub`! 47 //! 48 //! ## Required Methods 49 //! 50 //! The [`Target::base_ops`](trait.Target.html#tymethod.base_ops) method 51 //! describes the base debugging operations that must be implemented by any 52 //! target. These are things such as starting/stopping execution, 53 //! reading/writing memory, etc.. 54 //! 55 //! All other methods are entirely optional! Check out the 56 //! [`target_ext`](../target_ext/index.html) module for a full list of currently 57 //! supported protocol extensions. 58 //! 59 //! ## Example: A Bare-Minimum Single Threaded `Target` 60 //! 61 //! ```rust,ignore 62 //! use gdbstub::target::Target; 63 //! use gdbstub::target::ext::base::singlethread::SingleThreadOps; 64 //! 65 //! impl SingleThreadOps for MyTarget { 66 //! // ... omitted for brevity 67 //! } 68 //! 69 //! impl Target for MyTarget { 70 //! fn base_ops(&mut self) -> base::BaseOps<Self::Arch, Self::Error> { 71 //! base::BaseOps::SingleThread(self) 72 //! } 73 //! } 74 //! ``` 75 76 use crate::arch::Arch; 77 78 pub mod ext; 79 80 /// The error type for various methods on `Target` and it's assorted associated 81 /// extension traits. 82 /// 83 /// # Error Handling over the GDB Remote Serial Protocol 84 /// 85 /// The GDB Remote Serial Protocol has less-than-stellar support for error 86 /// handling, typically taking the form of a single-byte 87 /// [`errno`-style error codes](https://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html). 88 /// Moreover, often times the GDB client will simply _ignore_ the specific error 89 /// code returned by the stub, and print a generic failure message instead. 90 /// 91 /// As such, while it's certainly better to use appropriate error codes when 92 /// possible (e.g: returning a `EFAULT` (14) when reading from invalid memory), 93 /// it's often fine to simply return the more general `TargetError::NonFatal` 94 /// instead, and avoid the headache of picking a "descriptive" error code. Under 95 /// the good, `TargetError::NonFatal` is sent to the GDB client as a generic 96 /// `EREMOTEIO` (121) error. 97 /// 98 /// # `From` and `Into` implementations 99 /// 100 /// - `From<()>` -> `TargetError::NonFatal` 101 /// - `From<io::Error>` -> `TargetError::Io(io::Error)` (requires `std` feature) 102 /// 103 /// When using a custom target-specific fatal error type, users are encouraged 104 /// to write the following impl to simplify error handling in `Target` methods: 105 /// 106 /// ```rust,ignore 107 /// type MyTargetFatalError = ...; // Target-specific Fatal Error 108 /// impl From<MyTargetFatalError> for TargetError<MyTargetFatalError> { 109 /// fn from(e: MyTargetFatalError) -> Self { 110 /// TargetError::Fatal(e) 111 /// } 112 /// } 113 /// ``` 114 /// 115 /// Unfortunately, a blanket impl such as `impl<T: Target> From<T::Error> for 116 /// TargetError<T::Error>` isn't possible, as it could result in impl conflicts. 117 /// For example, if a Target decided to use `()` as it's fatal error type, then 118 /// there would be conflict with the existing `From<()>` impl. 119 #[non_exhaustive] 120 pub enum TargetError<E> { 121 /// A non-specific, non-fatal error has occurred. 122 NonFatal, 123 /// I/O Error. 124 /// 125 /// At the moment, this is just shorthand for 126 /// `TargetError::NonFatal(e.raw_os_err().unwrap_or(121))`. Error code `121` 127 /// corresponds to `EREMOTEIO`. 128 /// 129 /// In the future, `gdbstub` may add support for the "QEnableErrorStrings" 130 /// LLDB protocol extension, which would allow sending additional error 131 /// context (in the form of an ASCII string) when an I/O error occurs. If 132 /// this is something you're interested in, consider opening a PR! 133 /// 134 /// Only available when the `std` feature is enabled. 135 #[cfg(feature = "std")] 136 Io(std::io::Error), 137 /// An operation-specific non-fatal error code. 138 Errno(u8), 139 /// A target-specific fatal error. 140 /// 141 /// **WARNING:** Returning this error will immediately halt the target's 142 /// execution and return a `GdbStubError::TargetError` from `GdbStub::run`! 143 /// Note that the debugging session will will _not_ be terminated, and can 144 /// be resumed by calling `GdbStub::run` after resolving the error and/or 145 /// setting up a post-mortem debugging environment. 146 Fatal(E), 147 } 148 149 /// Converts a `()` into a `TargetError::NonFatal`. 150 impl<E> From<()> for TargetError<E> { from(_: ()) -> TargetError<E>151 fn from(_: ()) -> TargetError<E> { 152 TargetError::NonFatal 153 } 154 } 155 156 /// Converts a `std::io::Error` into a `TargetError::Io`. 157 #[cfg(feature = "std")] 158 impl<E> From<std::io::Error> for TargetError<E> { from(e: std::io::Error) -> TargetError<E>159 fn from(e: std::io::Error) -> TargetError<E> { 160 TargetError::Io(e) 161 } 162 } 163 164 /// A specialized `Result` type for `Target` operations. 165 /// 166 /// _Note:_ While it's typically parameterized as `TargetResult<T, Self>`, the 167 /// error value is in-fact `TargetError<Self::Error>` (not `Self`). 168 pub type TargetResult<T, Tgt> = Result<T, TargetError<<Tgt as Target>::Error>>; 169 170 /// Describes the architecture and capabilities of a target which can be 171 /// debugged by [`GdbStub`](../struct.GdbStub.html). 172 /// 173 /// The [`Target`](trait.Target.html) trait describes how to control and modify 174 /// a system's execution state during a GDB debugging session, and serves as the 175 /// primary bridge between `gdbstub`'s generic protocol implementation and a 176 /// target's project/platform-specific code. 177 /// 178 /// **`Target` is the most important trait in `gdbstub`, and must be implemented 179 /// by anyone who uses the library!** 180 /// 181 /// Please refer to the the documentation in the [`target` module](index.html) 182 /// for more information on how to implement and work with `Target` and it's 183 /// various extension traits. 184 pub trait Target { 185 /// The target's architecture. 186 type Arch: Arch; 187 188 /// A target-specific **fatal** error. 189 type Error; 190 191 /// Base operations such as reading/writing from memory/registers, 192 /// stopping/resuming the target, etc.... 193 /// 194 /// For example, on a single-threaded target: 195 /// 196 /// ```rust,ignore 197 /// use gdbstub::target::Target; 198 /// use gdbstub::target::base::singlethread::SingleThreadOps; 199 /// 200 /// impl SingleThreadOps for MyTarget { 201 /// // ... 202 /// } 203 /// 204 /// impl Target for MyTarget { 205 /// fn base_ops(&mut self) -> base::BaseOps<Self::Arch, Self::Error> { 206 /// base::BaseOps::SingleThread(self) 207 /// } 208 /// } 209 /// ``` base_ops(&mut self) -> ext::base::BaseOps<Self::Arch, Self::Error>210 fn base_ops(&mut self) -> ext::base::BaseOps<Self::Arch, Self::Error>; 211 212 /// Set/Remote software breakpoints. sw_breakpoint(&mut self) -> Option<ext::breakpoints::SwBreakpointOps<Self>>213 fn sw_breakpoint(&mut self) -> Option<ext::breakpoints::SwBreakpointOps<Self>> { 214 None 215 } 216 217 /// Set/Remote hardware breakpoints. hw_breakpoint(&mut self) -> Option<ext::breakpoints::HwBreakpointOps<Self>>218 fn hw_breakpoint(&mut self) -> Option<ext::breakpoints::HwBreakpointOps<Self>> { 219 None 220 } 221 222 /// Set/Remote hardware watchpoints. hw_watchpoint(&mut self) -> Option<ext::breakpoints::HwWatchpointOps<Self>>223 fn hw_watchpoint(&mut self) -> Option<ext::breakpoints::HwWatchpointOps<Self>> { 224 None 225 } 226 227 /// Handle custom GDB `monitor` commands. monitor_cmd(&mut self) -> Option<ext::monitor_cmd::MonitorCmdOps<Self>>228 fn monitor_cmd(&mut self) -> Option<ext::monitor_cmd::MonitorCmdOps<Self>> { 229 None 230 } 231 232 /// Support for Extended Mode operations. extended_mode(&mut self) -> Option<ext::extended_mode::ExtendedModeOps<Self>>233 fn extended_mode(&mut self) -> Option<ext::extended_mode::ExtendedModeOps<Self>> { 234 None 235 } 236 237 /// Handle requests to get the target's current section (or segment) 238 /// offsets. section_offsets(&mut self) -> Option<ext::section_offsets::SectionOffsetsOps<Self>>239 fn section_offsets(&mut self) -> Option<ext::section_offsets::SectionOffsetsOps<Self>> { 240 None 241 } 242 243 /// Override the target description XML specified by `Target::Arch`. target_description_xml_override( &mut self, ) -> Option<ext::target_description_xml_override::TargetDescriptionXmlOverrideOps<Self>>244 fn target_description_xml_override( 245 &mut self, 246 ) -> Option<ext::target_description_xml_override::TargetDescriptionXmlOverrideOps<Self>> { 247 None 248 } 249 } 250 251 macro_rules! impl_dyn_target { 252 ($type:ty) => { 253 #[allow(clippy::type_complexity)] 254 impl<A, E> Target for $type 255 where 256 A: Arch, 257 { 258 type Arch = A; 259 type Error = E; 260 261 fn base_ops(&mut self) -> ext::base::BaseOps<Self::Arch, Self::Error> { 262 (**self).base_ops() 263 } 264 265 fn sw_breakpoint(&mut self) -> Option<ext::breakpoints::SwBreakpointOps<Self>> { 266 (**self).sw_breakpoint() 267 } 268 269 fn hw_breakpoint(&mut self) -> Option<ext::breakpoints::HwBreakpointOps<Self>> { 270 (**self).hw_breakpoint() 271 } 272 273 fn hw_watchpoint(&mut self) -> Option<ext::breakpoints::HwWatchpointOps<Self>> { 274 (**self).hw_watchpoint() 275 } 276 277 fn monitor_cmd(&mut self) -> Option<ext::monitor_cmd::MonitorCmdOps<Self>> { 278 (**self).monitor_cmd() 279 } 280 281 fn extended_mode(&mut self) -> Option<ext::extended_mode::ExtendedModeOps<Self>> { 282 (**self).extended_mode() 283 } 284 285 fn section_offsets(&mut self) -> Option<ext::section_offsets::SectionOffsetsOps<Self>> { 286 (**self).section_offsets() 287 } 288 289 fn target_description_xml_override( 290 &mut self, 291 ) -> Option<ext::target_description_xml_override::TargetDescriptionXmlOverrideOps<Self>> 292 { 293 (**self).target_description_xml_override() 294 } 295 } 296 }; 297 } 298 299 impl_dyn_target!(&mut dyn Target<Arch = A, Error = E>); 300 #[cfg(feature = "alloc")] 301 impl_dyn_target!(alloc::boxed::Box<dyn Target<Arch = A, Error = E>>); 302