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