Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/stub/core_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ pub(crate) mod target_result_ext {
Err(TargetError::Errno(code)) => code,
#[cfg(feature = "std")]
Err(TargetError::Io(e)) => e.raw_os_error().unwrap_or(121) as u8,
#[cfg(feature = "std")]
Err(TargetError::FatalCore(e)) => return Err(InternalError::TargetCoreError(e)),
};

Err(InternalError::NonFatalError(code))
Expand Down
26 changes: 26 additions & 0 deletions src/stub/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ pub(crate) enum InternalError<T, C> {
/// Target encountered a fatal error.
TargetError(T),

/// Target encountered a fatal error. More information may be available
/// in the source of the error.
#[cfg(feature = "std")]
TargetCoreError(Box<dyn core::error::Error + Send + Sync + 'static>),

ClientSentNack,
PacketBufferOverflow,
PacketParse(PacketParseError),
Expand Down Expand Up @@ -140,6 +145,8 @@ where
PacketUnexpected => write!(f, "Client sent an unexpected packet. This should never happen! Please re-run with `log` trace-level logging enabled and file an issue at https://github.com/daniel5151/gdbstub/issues"),
TargetMismatch => write!(f, "Received a packet with too much data for the given target"),
TargetError(e) => write!(f, "Target threw a fatal error: {}", e),
#[cfg(feature = "std")]
TargetCoreError(e) => write!(f, "Target threw a fatal error: {}", e),
UnsupportedStopReason => write!(f, "{} {}", unsupported_stop_reason!(), CONTEXT),
UnexpectedStepPacket => write!(f, "{} {}", unexpected_step_packet!(), CONTEXT),

Expand All @@ -159,6 +166,16 @@ where
C: Debug + Display,
T: Debug + Display,
{
#[cfg(feature = "std")]
fn source(&self) -> Option<&(dyn CoreError + 'static)> {
let GdbStubError {
kind: InternalError::TargetCoreError(e),
} = self
else {
return None;
};
e.source()
}
}

impl<T, C> GdbStubError<T, C> {
Expand All @@ -175,6 +192,15 @@ impl<T, C> GdbStubError<T, C> {
}
}

/// If the error was due to a core error, return the core error trait.
#[cfg(feature = "std")]
pub fn into_core_error(self) -> Option<Box<dyn core::error::Error>> {
match self.kind {
InternalError::TargetCoreError(e) => Some(e),
_ => None,
}
}

/// Check if the error was due to a connection error.
pub fn is_connection_error(&self) -> bool {
matches!(self.kind, InternalError::Connection(..))
Expand Down
7 changes: 7 additions & 0 deletions src/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,13 @@ pub enum TargetError<E> {
/// debugging session, and return a
/// [`GdbStubError`](crate::stub::GdbStubError)!
Fatal(E),
/// A generic fatal error with a core Error implementation.
///
/// **WARNING:** Returning this error will immediately terminate the GDB
/// debugging session, and return a
/// [`GdbStubError`](crate::stub::GdbStubError)!
#[cfg(feature = "std")]
FatalCore(Box<dyn core::error::Error + Send + Sync + 'static>),
}

/// Converts a `()` into a `TargetError::NonFatal`.
Expand Down
Loading