Skip to main content

minidump_writer/
module_reader.rs

1//! Common module reader types.
2use {
3    crate::process_reader::{CopyFromProcessError, ProcessReader},
4    std::borrow::Cow,
5};
6
7#[cfg(any(target_os = "linux", target_os = "android"))]
8pub use crate::linux::module_reader::*;
9
10#[cfg(target_os = "windows")]
11pub use crate::windows::module_reader::*;
12
13#[cfg(target_os = "macos")]
14pub use crate::mac::module_reader::*;
15
16pub struct ProcessModuleMemoryReader<'a> {
17    pub(super) reader: &'a ProcessReader<'a>,
18    pub(super) start_address: u64,
19}
20
21impl<'a> ProcessModuleMemoryReader<'a> {
22    pub fn new(reader: &'a ProcessReader<'a>, start_address: usize) -> Self {
23        Self {
24            reader,
25            start_address: start_address as u64,
26        }
27    }
28    pub fn read(&self, offset: u64, length: u64) -> Result<Cow<'a, [u8]>, ModuleMemoryReadError> {
29        let inner = || {
30            let address = self
31                .start_address
32                .checked_add(offset)
33                .ok_or(ReadError::Overflow)?;
34            let address = usize::try_from(address).map_err(|_| ReadError::Overflow)?;
35            let length = usize::try_from(length).map_err(|_| ReadError::Overflow)?;
36            let length =
37                std::num::NonZeroUsize::new(length).ok_or(ReadError::ZeroLengthProcessRead)?;
38            self.reader
39                .read_to_vec(address, length)
40                .map(Cow::Owned)
41                .map_err(ReadError::CopyError)
42        };
43
44        inner().map_err(|error| ModuleMemoryReadError {
45            start_address: Some(self.start_address),
46            offset,
47            length,
48            error,
49        })
50    }
51}
52
53#[derive(Debug, thiserror::Error, serde::Serialize)]
54#[error("Error reading {length} bytes at {offset:#x}{}: {error}",
55    .start_address.map(|s| format!(" (module start address {s:#x})")).unwrap_or_default()
56)]
57pub struct ModuleMemoryReadError {
58    pub offset: u64,
59    pub length: u64,
60    pub start_address: Option<u64>,
61    #[source]
62    pub error: ReadError,
63}
64
65#[derive(Debug, thiserror::Error, serde::Serialize)]
66pub enum ReadError {
67    #[error("Attempted to read 0 bytes from process memory")]
68    ZeroLengthProcessRead,
69    #[error("Read overflowed the address space")]
70    Overflow,
71    #[error("Read was out of slice memory bounds")]
72    OutOfBounds,
73    #[error(transparent)]
74    CopyError(#[from] CopyFromProcessError),
75    #[cfg(any(target_os = "linux", target_os = "android"))]
76    #[error(transparent)]
77    PlatformSpecific(crate::linux::BackendError),
78}