minidump_writer/
module_reader.rs1use {
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}