1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "std")]
5use std::{
6 ops::Range,
7 path::Path,
8 fs::File,
9 io::{Result, BufReader, BufRead, Error, ErrorKind},
10};
11
12pub const BUFFER_SIZE: usize = 256; pub const QUEUE_SIZE: u32 = 64;
15pub const MAX_QUEUE_SIZE: usize = QUEUE_SIZE as usize * BUFFER_SIZE;
16
17pub const PROC_IOMEM: &str = "/proc/iomem";
19pub const SEPARATOR_SYSTEM_RAM: &str = " : System RAM";
20pub const SEPARATOR_HYPHEN: char = '-';
21
22pub const PROC_KALLSYMS: &str = "/proc/kallsyms";
24pub const PAGE_OFFSET_BASE: &str = "page_offset_base";
25
26pub const PROC_SELF_EXE: &str = "/proc/self/exe";
28
29pub const READ_KERNEL_MEM: &str = "read_kernel_memory";
31
32pub const ERROR_DUMP_MEMORY_IOMEM_SEPARATE_KEY_VAL_MAP: &str = "There is no left side in key/value pair";
34pub const ERROR_DUMP_MEMORY_IOMEM_CAPSYSADM: &str = "Need CAP_SYS_ADMIN to read /proc/iomem";
35pub const ERROR_PATH_READ_SYS: &str = "An error occured while trying to read necessary data from /sys";
36
37pub fn calc_queue_elements(dump_size: usize) -> usize {
38 if dump_size % BUFFER_SIZE == 0 {
39 dump_size / BUFFER_SIZE
40 } else {
41 dump_size / BUFFER_SIZE + 1
42 }
43}
44
45#[cfg(feature = "std")]
76pub fn extract_mem_range<I: Into<String>>(identifier: I) -> Result<Vec<Range<u64>>> {
77 let identifier = identifier.into();
78 let path = Path::new(PROC_IOMEM);
79 let file = File::open(path)?;
80 let reader = BufReader::new(file);
81 let mut ranges = Vec::new();
82
83 for line in reader.lines() {
84 let line = line?;
85 if line.contains(&identifier) {
86 if let Some((start, end)) = parse_memory_range(&line) {
87 ranges.push(start..(end + 1));
88 }
89 }
90 }
91
92 Ok(ranges)
93}
94
95#[cfg(feature = "std")]
96pub fn get_page_offset_base_address() -> Result<u64>{
97 let path = Path::new(PROC_KALLSYMS);
98 let file = File::open(path)?;
99 let reader = BufReader::new(file);
100 for line in reader.lines() {
101 let line = line?;
102 if line.contains(PAGE_OFFSET_BASE) {
103 let parts: Vec<&str> = line.split_whitespace().collect();
104 if let Some(offset_str) = parts.first() {
105 return u64::from_str_radix(offset_str, 16)
106 .map_err(|e| Error::new(ErrorKind::InvalidData, e))
107 }
108 }
109 }
110 Ok(0)
112}
113
114#[cfg(feature = "std")]
115fn parse_memory_range(line: &str) -> Option<(u64, u64)> {
116 let parts: Vec<&str> = line.split_whitespace().collect();
117 if let Some(range_part) = parts.first() {
118 let bounds: Vec<&str> = range_part.split(SEPARATOR_HYPHEN).collect();
119 if bounds.len() == 2 {
120 if let (Ok(start), Ok(end)) = (u64::from_str_radix(bounds[0], 16), u64::from_str_radix(bounds[1], 16)) {
121 return Some((start, end));
122 }
123 }
124 }
125 None
126}