109 lines
3.1 kB
1
use anyhow::Result;
2
use log::info;
3
use std::fs;
4
use std::path::Path;
5
use std::str::FromStr;
6
7
pub struct Process {
8
pub pid: i32,
9
#[allow(dead_code)]
10
pub name: String,
11
}
12
13
#[derive(Debug, Clone)]
14
pub struct MemoryRegion {
15
pub start_addr: usize,
16
pub end_addr: usize,
17
#[allow(dead_code)]
18
pub permissions: String,
19
#[allow(dead_code)]
20
pub offset: usize,
21
#[allow(dead_code)]
22
pub pathname: String,
23
}
24
25
impl Process {
26
pub fn find_by_name(name: &str) -> Result<Self> {
27
// Search for process using pgrep-like functionality
28
let proc_dir = Path::new("/proc");
29
let mut found_pid = None;
30
31
for entry in fs::read_dir(proc_dir)? {
32
let entry = entry?;
33
let path = entry.path();
34
35
if !path.is_dir() {
36
continue;
37
}
38
39
let file_name = path.file_name().unwrap().to_string_lossy();
40
if !file_name.chars().all(|c| c.is_digit(10)) {
41
continue;
42
}
43
44
let pid = i32::from_str(&file_name)?;
45
let cmdline_path = path.join("cmdline");
46
47
if !cmdline_path.exists() {
48
continue;
49
}
50
51
let cmdline = fs::read_to_string(cmdline_path)?;
52
if cmdline.contains(name) {
53
println!("Process found with PID: {}", pid);
54
found_pid = Some(pid);
55
break;
56
}
57
}
58
59
match found_pid {
60
Some(pid) => Ok(Process {
61
pid,
62
name: name.to_string(),
63
}),
64
None => anyhow::bail!("Process '{}' not found", name),
65
}
66
}
67
68
pub fn get_memory_maps(&self) -> Result<Vec<MemoryRegion>> {
69
let maps_path = format!("/proc/{}/maps", self.pid);
70
info!("maps file located at {} opened.", maps_path);
71
72
let maps_content = fs::read_to_string(&maps_path)?;
73
let mut regions = Vec::new();
74
75
for line in maps_content.lines() {
76
let parts: Vec<&str> = line.split_whitespace().collect();
77
if parts.len() < 5 {
78
continue;
79
}
80
81
let addr_range: Vec<&str> = parts[0].split('-').collect();
82
if addr_range.len() != 2 {
83
continue;
84
}
85
86
let start_addr = usize::from_str_radix(addr_range[0], 16)?;
87
let end_addr = usize::from_str_radix(addr_range[1], 16)?;
88
let permissions = parts[1].to_string();
89
90
// Only add regions with read permission
91
if permissions.contains('r') {
92
regions.push(MemoryRegion {
93
start_addr,
94
end_addr,
95
permissions,
96
offset: usize::from_str_radix(parts[2], 16)?,
97
pathname: if parts.len() > 5 {
98
parts[5..].join(" ")
99
} else {
100
String::new()
101
},
102
});
103
}
104
}
105
106
info!("{} suitable regions found.", regions.len());
107
Ok(regions)
108
}
109
}
110