substrate/symbol/
memmap.rs1use crate::error::{Result, SubstrateError};
2use std::collections::HashMap;
3use std::fs::File;
4use std::io::{BufRead, BufReader};
5
6pub struct MemoryMap {
7 pub name: String,
8 pub start: usize,
9 pub end: usize,
10}
11
12pub fn load_memory_maps(pid: libc::pid_t) -> Result<Vec<MemoryMap>> {
13 let path = format!("/proc/{}/maps", pid);
14 let file = File::open(&path).map_err(|e| {
15 SubstrateError::Io(e)
16 })?;
17
18 let reader = BufReader::new(file);
19 let mut maps = Vec::new();
20 let mut map_dict: HashMap<String, (usize, usize)> = HashMap::new();
21
22 for line in reader.lines() {
23 let line = line?;
24 let parts: Vec<&str> = line.split_whitespace().collect();
25
26 if parts.len() < 1 {
27 continue;
28 }
29
30 let addr_parts: Vec<&str> = parts[0].split('-').collect();
31 if addr_parts.len() != 2 {
32 continue;
33 }
34
35 let start = usize::from_str_radix(addr_parts[0], 16)
36 .map_err(|_| SubstrateError::ElfParsing("Invalid address".to_string()))?;
37 let end = usize::from_str_radix(addr_parts[1], 16)
38 .map_err(|_| SubstrateError::ElfParsing("Invalid address".to_string()))?;
39
40 let name = if parts.len() >= 6 {
41 parts[5].to_string()
42 } else {
43 "[memory]".to_string()
44 };
45
46 if let Some((existing_start, existing_end)) = map_dict.get_mut(&name) {
47 if start < *existing_start {
48 *existing_start = start;
49 }
50 if end > *existing_end {
51 *existing_end = end;
52 }
53 } else {
54 map_dict.insert(name.clone(), (start, end));
55 }
56 }
57
58 for (name, (start, end)) in map_dict {
59 maps.push(MemoryMap { name, start, end });
60 }
61
62 Ok(maps)
63}
64
65pub fn find_library_base(pid: libc::pid_t, lib_name: &str) -> Result<usize> {
66 let maps = load_memory_maps(pid)?;
67
68 for map in maps {
69 if map.name == "[memory]" {
70 continue;
71 }
72
73 if let Some(pos) = map.name.rfind('/') {
74 let basename = &map.name[pos + 1..];
75 if basename.starts_with(lib_name) && (basename.len() == lib_name.len() + 3 && basename.ends_with(".so") || basename.len() > lib_name.len() + 3) {
76 unsafe {
77 libc::mprotect(
78 map.start as *mut libc::c_void,
79 map.end - map.start,
80 libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
81 );
82 }
83 return Ok(map.start);
84 }
85 }
86 }
87
88 Err(SubstrateError::LibraryNotFound(lib_name.to_string()))
89}