1 use core::fmt::{self, Debug, Display}; 2 3 use crate::arch::SingleStepGdbBehavior; 4 use crate::protocol::{PacketParseError, ResponseWriterError}; 5 use crate::util::managed_vec::CapacityError; 6 7 /// An error which may occur during a GDB debugging session. 8 #[derive(Debug)] 9 #[non_exhaustive] 10 pub enum GdbStubError<T, C> { 11 /// Connection Error while initializing the session. 12 ConnectionInit(C), 13 /// Connection Error while reading request. 14 ConnectionRead(C), 15 /// Connection Error while writing response. 16 ConnectionWrite(C), 17 18 /// Client nack'd the last packet, but `gdbstub` doesn't implement 19 /// re-transmission. 20 ClientSentNack, 21 /// Packet cannot fit in the provided packet buffer. 22 PacketBufferOverflow, 23 /// Could not parse the packet into a valid command. 24 PacketParse(PacketParseError), 25 /// GDB client sent an unexpected packet. This should never happen! 26 /// Please re-run with `log` trace-level logging enabled and file an issue 27 /// at <https://github.com/daniel5151/gdbstub/issues> 28 PacketUnexpected, 29 /// GDB client sent a packet with too much data for the given target. 30 TargetMismatch, 31 /// Target encountered a fatal error. 32 TargetError(T), 33 /// Target responded with an unsupported stop reason. 34 /// 35 /// Certain stop reasons can only be used when their associated protocol 36 /// feature has been implemented. e.g: a Target cannot return a 37 /// `StopReason::HwBreak` if the hardware breakpoints IDET hasn't been 38 /// implemented. 39 UnsupportedStopReason, 40 /// Target didn't report any active threads when there should have been at 41 /// least one running. 42 NoActiveThreads, 43 44 /// The target has not opted into using implicit software breakpoints. 45 /// See [`Target::guard_rail_implicit_sw_breakpoints`] for more information. 46 /// 47 /// [`Target::guard_rail_implicit_sw_breakpoints`]: 48 /// crate::target::Target::guard_rail_implicit_sw_breakpoints 49 ImplicitSwBreakpoints, 50 /// The target has not indicated support for optional single stepping. See 51 /// [`Target::guard_rail_single_step_gdb_behavior`] for more information. 52 /// 53 /// If you encountered this error while using an `Arch` implementation 54 /// defined in `gdbstub_arch` and believe this is incorrect, please file an 55 /// issue at <https://github.com/daniel5151/gdbstub/issues>. 56 /// 57 /// [`Target::guard_rail_single_step_gdb_behavior`]: 58 /// crate::target::Target::guard_rail_single_step_gdb_behavior 59 SingleStepGdbBehavior(SingleStepGdbBehavior), 60 61 // Internal - A non-fatal error occurred (with errno-style error code) 62 // 63 // This "dummy" error is required as part of the internal 64 // `TargetResultExt::handle_error()` machinery, and will never be 65 // propagated up to the end user. 66 #[doc(hidden)] 67 NonFatalError(u8), 68 } 69 70 impl<T, C> From<ResponseWriterError<C>> for GdbStubError<T, C> { from(e: ResponseWriterError<C>) -> Self71 fn from(e: ResponseWriterError<C>) -> Self { 72 GdbStubError::ConnectionWrite(e.0) 73 } 74 } 75 76 impl<A, T, C> From<CapacityError<A>> for GdbStubError<T, C> { from(_: CapacityError<A>) -> Self77 fn from(_: CapacityError<A>) -> Self { 78 GdbStubError::PacketBufferOverflow 79 } 80 } 81 82 impl<T, C> Display for GdbStubError<T, C> 83 where 84 C: Debug, 85 T: Debug, 86 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 88 use self::GdbStubError::*; 89 match self { 90 ConnectionInit(e) => write!(f, "Connection Error while initializing the session: {:?}", e), 91 ConnectionRead(e) => write!(f, "Connection Error while reading request: {:?}", e), 92 ConnectionWrite(e) => write!(f, "Connection Error while writing response: {:?}", e), 93 ClientSentNack => write!(f, "Client nack'd the last packet, but `gdbstub` doesn't implement re-transmission."), 94 PacketBufferOverflow => write!(f, "Packet too big for provided buffer!"), 95 PacketParse(e) => write!(f, "Could not parse the packet into a valid command: {:?}", e), 96 PacketUnexpected => write!(f, "Client sent an unexpected packet. Please re-run with `log` trace-level logging enabled and file an issue at https://github.com/daniel5151/gdbstub/issues"), 97 TargetMismatch => write!(f, "GDB client sent a packet with too much data for the given target."), 98 TargetError(e) => write!(f, "Target threw a fatal error: {:?}", e), 99 UnsupportedStopReason => write!(f, "Target responded with an unsupported stop reason."), 100 NoActiveThreads => write!(f, "Target didn't report any active threads when there should have been at least one running."), 101 102 ImplicitSwBreakpoints => write!(f, "Warning: The target has not opted into using implicit software breakpoints. See `Target::guard_rail_implicit_sw_breakpoints` for more information."), 103 SingleStepGdbBehavior(behavior) => { 104 use crate::arch::SingleStepGdbBehavior; 105 write!( 106 f, 107 "Warning: Mismatch between the targets' single-step support and arch-level single-step behavior: {} ", 108 match behavior { 109 SingleStepGdbBehavior::Optional => "", // unreachable, since optional single step will not result in an error 110 SingleStepGdbBehavior::Required => "GDB requires single-step support on this arch.", 111 SingleStepGdbBehavior::Ignored => "GDB ignores single-step support on this arch, yet the target has implemented support for it.", 112 SingleStepGdbBehavior::Unknown => "This arch's single-step behavior hasn't been tested yet: please conduct a test + upstream your findings!", 113 } 114 )?; 115 write!(f, "See `Target::guard_rail_single_step_gdb_behavior` for more information.") 116 }, 117 118 NonFatalError(_) => write!(f, "Internal non-fatal error. End users should never see this! Please file an issue if you do!"), 119 } 120 } 121 } 122 123 #[cfg(feature = "std")] 124 impl<T, C> std::error::Error for GdbStubError<T, C> 125 where 126 C: Debug, 127 T: Debug, 128 { 129 } 130