minidump_writer/linux/process_inspection/
process_reader.rs1use super::{
2 Backend, Error, ProcessInspector,
3 maps_reader::{MappingInfo, MapsReaderError},
4};
5use crate::module_reader::ProcessModuleMemoryReader;
6
7use process_backend::local;
8
9pub type ProcessHandle = libc::pid_t;
10
11#[derive(Debug)]
12pub struct ProcessReader<'a> {
13 process_inspector: &'a ProcessInspector,
14 forced_backend: Option<ForcedBackend>,
15}
16
17#[derive(Debug)]
18enum ForcedBackend {
19 Local(local::ProcessReader),
20}
21
22impl<'a> ProcessReader<'a> {
23 pub fn new(process_inspector: &'a ProcessInspector) -> Self {
24 Self {
25 process_inspector,
26 forced_backend: None,
27 }
28 }
29 pub fn for_virtual_mem(process_inspector: &'a ProcessInspector) -> Self {
30 let forced_backend = match &process_inspector.backend {
31 Backend::Local { backend, .. } => {
32 ForcedBackend::Local(backend.process_reader_for_virtual_mem())
33 }
34 };
35 Self {
36 process_inspector,
37 forced_backend: Some(forced_backend),
38 }
39 }
40 pub fn for_file(process_inspector: &'a ProcessInspector) -> Result<Self, Error> {
41 let forced_backend = match &process_inspector.backend {
42 Backend::Local { backend, .. } => {
43 ForcedBackend::Local(backend.process_reader_for_file().map_err(Error::Local)?)
44 }
45 };
46 Ok(Self {
47 process_inspector,
48 forced_backend: Some(forced_backend),
49 })
50 }
51 pub fn for_ptrace(process_inspector: &'a ProcessInspector) -> Self {
52 let forced_backend = match &process_inspector.backend {
53 Backend::Local { backend, .. } => {
54 ForcedBackend::Local(backend.process_reader_for_ptrace())
55 }
56 };
57 Self {
58 process_inspector,
59 forced_backend: Some(forced_backend),
60 }
61 }
62
63 pub fn read(&self, src: usize, dst: &mut [u8]) -> Result<usize, CopyFromProcessError> {
67 if let Some(forced_backend) = &self.forced_backend {
68 match forced_backend {
69 ForcedBackend::Local(process_reader_backend) => process_reader_backend
70 .read_at(src, dst)
71 .map_err(Error::Local),
72 }
73 } else {
74 match &self.process_inspector.backend {
75 Backend::Local {
76 process_reader_backend,
77 ..
78 } => process_reader_backend
79 .read_at(src, dst)
80 .map_err(Error::Local),
81 }
82 }
83 .map_err(CopyFromProcessError::Backend)
84 }
85 pub fn find_module(
87 &self,
88 module_name: &str,
89 ) -> Result<ProcessModuleMemoryReader<'_>, FindModuleError> {
90 MappingInfo::for_pid(self.process_inspector, self.process_inspector.pid, None)?
91 .into_iter()
92 .find_map(|m| {
93 let mmem = ProcessModuleMemoryReader::new(self, m.start_address);
94 let name = m.name.as_ref().and_then(|s| s.to_str())?;
95 if name == module_name {
96 return Some(mmem);
97 }
98 #[cfg(target_os = "android")]
103 if name.ends_with(".apk") {
104 if let Ok(so_name) = crate::module_reader::read_soname_from_module(&mmem) {
105 if so_name == name {
106 return Some(mmem);
107 }
108 }
109 }
110
111 None
112 })
113 .ok_or(FindModuleError::ModuleNotFound)
114 }
115}
116
117#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)]
118pub enum CopyFromProcessError {
119 #[error("an error occurred calling ProcessReader")]
120 Backend(Error),
121 #[error("an invalid argument was passed")]
122 InvalidArgument,
123}
124
125#[derive(Debug, thiserror::Error, serde::Serialize)]
126pub enum FindModuleError {
127 #[error("Module not found")]
128 ModuleNotFound,
129 #[error("Failed to read process module mappings")]
130 MappingError(#[from] MapsReaderError),
131}