1use core::{
2 error::Error as StdError,
3 ffi::c_int,
4 fmt::{Display, Formatter, Result as FmtResult},
5};
6
7#[derive(Debug)]
29#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
30pub struct ReadError(pub(crate) ReadErrorInner);
31
32impl ReadError {
33 pub fn virtual_mem_error(&self) -> Option<&(dyn StdError + 'static)> {
42 match &self.0 {
43 ReadErrorInner::AllStrategies { vmem_err, .. } => Some(vmem_err),
44 ReadErrorInner::VirtualMemStrategy(e) => Some(e),
45 _ => None,
46 }
47 }
48
49 pub fn file_error(&self) -> Option<&(dyn StdError + 'static)> {
58 match &self.0 {
59 ReadErrorInner::AllStrategies { file_err, .. } => Some(file_err),
60 ReadErrorInner::FileStrategy(e) => Some(e),
61 _ => None,
62 }
63 }
64
65 pub fn ptrace_error(&self) -> Option<&(dyn StdError + 'static)> {
73 match &self.0 {
74 ReadErrorInner::AllStrategies { ptrace_err, .. } => Some(ptrace_err),
75 ReadErrorInner::PtraceStrategy(e) => Some(e),
76 _ => None,
77 }
78 }
79}
80
81impl Display for ReadError {
82 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
83 use ReadErrorInner as E;
84 match &self.0 {
85 E::AllStrategies { .. } => write!(f, "all process reading strategies failed"),
86 E::VirtualMemStrategy(_) => write!(f, "virtual memory strategy failed"),
87 E::FileStrategy(_) => write!(f, "file strategy failed"),
88 E::PtraceStrategy(_) => write!(f, "ptrace strategy failed"),
89 }
90 }
91}
92
93impl StdError for ReadError {
94 fn source(&self) -> Option<&(dyn StdError + 'static)> {
95 use ReadErrorInner as E;
96 match &self.0 {
97 E::AllStrategies { .. } => None,
98 E::VirtualMemStrategy(e) => Some(e),
99 E::FileStrategy(e) => Some(e),
100 E::PtraceStrategy(e) => Some(e),
101 }
102 }
103}
104
105#[derive(Debug)]
106#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
107pub(crate) enum ReadErrorInner {
108 AllStrategies {
109 vmem_err: ProcessVmReadvFailed,
110 file_err: FileStrategyError,
111 ptrace_err: PtraceError,
112 },
113 VirtualMemStrategy(ProcessVmReadvFailed),
114 FileStrategy(FileStrategyError),
115 PtraceStrategy(PtraceError),
116}
117
118#[derive(Debug)]
125#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
126pub enum ReadExactError {
127 Read(ReadError),
134 UnexpectedEof,
140}
141
142impl Display for ReadExactError {
143 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
144 match self {
145 Self::Read(_) => write!(f, "an error occurred before filling entire buffer"),
146 Self::UnexpectedEof => write!(f, "unexpected end-of-file before filling entire buffer"),
147 }
148 }
149}
150
151impl StdError for ReadExactError {
152 fn source(&self) -> Option<&(dyn StdError + 'static)> {
153 match self {
154 Self::Read(e) => Some(e),
155 Self::UnexpectedEof => None,
156 }
157 }
158}
159
160#[derive(Debug)]
161#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
162pub(crate) struct ProcessVmReadvFailed(pub(crate) c_int);
163
164impl Display for ProcessVmReadvFailed {
165 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
166 write!(f, "process_vm_readv() returned an error code: {}", self.0)
167 }
168}
169
170impl StdError for ProcessVmReadvFailed {}
171
172#[derive(Debug)]
173#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
174pub(crate) enum FileStrategyError {
175 Open(OpenFailed),
176 Read(ReadExactAtError),
177}
178
179impl Display for FileStrategyError {
180 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
181 match self {
182 Self::Open(_) => write!(f, "failed to open /proc/<pid>/mem file"),
183 Self::Read(_) => write!(f, "failed to read /proc/<pid>/mem file"),
184 }
185 }
186}
187
188impl StdError for FileStrategyError {
189 fn source(&self) -> Option<&(dyn StdError + 'static)> {
190 match self {
191 Self::Open(e) => Some(e),
192 Self::Read(e) => Some(e),
193 }
194 }
195}
196
197#[derive(Debug)]
198#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
199pub(crate) struct OpenFailed(pub(crate) c_int);
200
201impl Display for OpenFailed {
202 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
203 write!(f, "open64() returned an error code: {}", self.0)
204 }
205}
206
207impl StdError for OpenFailed {}
208
209#[derive(Debug)]
210#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
211pub(crate) enum ReadExactAtError {
212 ReadAt(ReadAtFailed),
213 AddressOverflow,
214 UnexpectedEof { position: usize },
215}
216
217impl Display for ReadExactAtError {
218 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
219 match self {
220 Self::ReadAt(_) => write!(f, "I/O error reading file"),
221 Self::AddressOverflow => write!(
222 f,
223 "the given address/length pair overflowed the machine's memory range"
224 ),
225 Self::UnexpectedEof { position } => write!(
226 f,
227 "unexpected end-of-file encountered at position: {position}"
228 ),
229 }
230 }
231}
232
233impl StdError for ReadExactAtError {
234 fn source(&self) -> Option<&(dyn StdError + 'static)> {
235 match self {
236 Self::ReadAt(e) => Some(e),
237 Self::AddressOverflow => None,
238 Self::UnexpectedEof { .. } => None,
239 }
240 }
241}
242
243#[derive(Debug)]
244#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
245pub(crate) enum ReadAtFailed {
246 Syscall(c_int),
247 AddressOutOfBounds,
248}
249
250impl Display for ReadAtFailed {
251 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
252 match self {
253 Self::Syscall(errno) => write!(f, "pread64() returned an error code: {errno}"),
254 Self::AddressOutOfBounds => {
255 write!(f, "requested address was out-of-bounds for pread64()")
256 }
257 }
258 }
259}
260
261impl StdError for ReadAtFailed {}
262
263#[derive(Debug)]
264#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
265pub(crate) enum PtraceError {
266 Syscall { errno: c_int, position: usize },
267 AddressOverflow,
268}
269
270impl Display for PtraceError {
271 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
272 match self {
273 Self::Syscall { errno, position } => write!(
274 f,
275 "ptrace(PTRACE_PEEKDATA) returned an error code at position {position}: {errno}",
276 ),
277 Self::AddressOverflow => write!(
278 f,
279 "the given address/length pair overflowed the machine's memory range"
280 ),
281 }
282 }
283}
284
285impl StdError for PtraceError {}