[feat] more powerful modules
This commit is contained in:
@@ -1,90 +1,109 @@
|
||||
|
||||
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
|
||||
use crate::helper::ExecuteLinkFile;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MemoryRegion {
|
||||
pub start_addr: u64,
|
||||
pub end_addr: u64,
|
||||
pub perms: String,
|
||||
pub offset: Option<u64>,
|
||||
pub dev: Option<String>,
|
||||
pub inode: Option<u64>,
|
||||
pub pathname: Option<String>,
|
||||
}
|
||||
|
||||
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();
|
||||
impl MemoryRegion {
|
||||
pub fn parse(line: &str) -> Option<Self> {
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if parts.len() < 2 {
|
||||
continue;
|
||||
return None;
|
||||
}
|
||||
|
||||
let perms = parts[1];
|
||||
if perms.starts_with("rw") {
|
||||
if let Some((start, end)) = parse_address_range(range_str) {
|
||||
return Some((start, end));
|
||||
}
|
||||
let range_part = parts[0];
|
||||
let range_parts: Vec<&str> = range_part.split('-').collect();
|
||||
if range_parts.len() != 2 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
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()?;
|
||||
|
||||
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].to_string();
|
||||
|
||||
let perms = parts[1];
|
||||
if perms.contains('x') {
|
||||
if let Some((start, end)) = parse_address_range(range_str) {
|
||||
return Some((start, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
let offset = parts.get(2).and_then(|s| u64::from_str_radix(s, 16).ok());
|
||||
let dev = parts.get(3).map(|s| s.to_string());
|
||||
let inode = parts.get(4).and_then(|s| s.parse::<u64>().ok());
|
||||
let pathname = parts.get(5).map(|s| s.to_string());
|
||||
|
||||
pub fn module_base_address(range_strings: &Vec<&str>, module_name: &str) -> Option<u64> {
|
||||
let mut base_addr: Option<u64> = 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),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Self {
|
||||
start_addr,
|
||||
end_addr,
|
||||
perms,
|
||||
offset,
|
||||
dev,
|
||||
inode,
|
||||
pathname,
|
||||
})
|
||||
}
|
||||
|
||||
base_addr
|
||||
pub fn is_read_write(&self) -> bool {
|
||||
self.perms.starts_with("rw")
|
||||
}
|
||||
|
||||
pub fn is_executable(&self) -> bool {
|
||||
self.perms.contains('x')
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MemoryMap {
|
||||
regions: Vec<MemoryRegion>,
|
||||
}
|
||||
|
||||
impl MemoryMap {
|
||||
pub fn new(lines: &Vec<&str>) -> Self {
|
||||
let regions = lines
|
||||
.iter()
|
||||
.filter_map(|line| MemoryRegion::parse(line))
|
||||
.collect();
|
||||
Self { regions }
|
||||
}
|
||||
|
||||
pub fn first_rw_segment(&self, module: &str) -> Option<(u64, u64)> {
|
||||
self.regions
|
||||
.iter()
|
||||
.find(|r| r.is_read_write() && r.pathname.as_deref() == Some(module))
|
||||
.map(|r| (r.start_addr, r.end_addr))
|
||||
}
|
||||
|
||||
pub fn first_exec_segment(&self, module: &str) -> Option<(u64, u64)> {
|
||||
self.regions
|
||||
.iter()
|
||||
.find(|r| r.is_executable() && r.pathname.as_deref() == Some(module))
|
||||
.map(|r| (r.start_addr, r.end_addr))
|
||||
}
|
||||
|
||||
pub fn module_base_address(&self, module: &str) -> Option<u64> {
|
||||
let elf = ExecuteLinkFile::prase(&module).ok()?;
|
||||
let loads = elf.get_loads().ok()?;
|
||||
let Some(first_load) = loads.first() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(map_item) = self.regions.iter().find(|r| {
|
||||
r.offset.unwrap_or(0) == first_load.p_offset && r.pathname.as_deref() == Some(module)
|
||||
}) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(map_item.start_addr - first_load.p_vaddr)
|
||||
}
|
||||
|
||||
pub fn collect_module(&self, module: &str) -> Vec<MemoryRegion>
|
||||
{
|
||||
let r = self.regions.iter()
|
||||
.filter_map(|r| if r.pathname.as_deref() == Some(module) { Some(r.clone()) } else { None })
|
||||
.collect::<Vec<MemoryRegion>>();
|
||||
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user