pub fn is_address_in_range(addr: u64, range_strings: &Vec<&str>) -> bool { for range_str in range_strings { if let Some((start, end)) = parse_address_range(range_str) { if addr >= start && addr < end { return true; } } } false } fn parse_address_range(range_str: &str) -> Option<(u64, u64)> { let parts: Vec<&str> = range_str.split_whitespace().collect(); if parts.is_empty() { return None; } let range_part = parts[0]; let range_parts: Vec<&str> = range_part.split('-').collect(); if range_parts.len() != 2 { return None; } let start_addr = u64::from_str_radix(range_parts[0], 16).ok()?; let end_addr = u64::from_str_radix(range_parts[1], 16).ok()?; Some((start_addr, end_addr)) } pub fn first_rw_segment(range_strings: &Vec<&str>) -> Option<(u64, u64)> { for range_str in range_strings { let parts: Vec<&str> = range_str.split_whitespace().collect(); if parts.len() < 2 { continue; } let perms = parts[1]; if perms.starts_with("rw") { if let Some((start, end)) = parse_address_range(range_str) { return Some((start, end)); } } } None } pub fn first_exec_segment(range_strings: &Vec<&str>) -> Option<(u64, u64)> { for range_str in range_strings { let parts: Vec<&str> = range_str.split_whitespace().collect(); if parts.len() < 2 { continue; } let perms = parts[1]; if perms.contains('x') { if let Some((start, end)) = parse_address_range(range_str) { return Some((start, end)); } } } None } pub fn module_base_address(range_strings: &Vec<&str>, module_name: &str) -> Option { let mut base_addr: Option = None; for range_str in range_strings { let parts: Vec<&str> = range_str.split_whitespace().collect(); if parts.len() < 6 { continue; } let path = parts.last().unwrap(); if let Some(filename) = std::path::Path::new(path).file_name().and_then(|f| f.to_str()) { if filename.contains(module_name) { if let Some((start, _)) = parse_address_range(range_str) { base_addr = match base_addr { Some(current_min) => Some(current_min.min(start)), None => Some(start), }; } } } } base_addr }