diff --git a/src/os/linux.rs b/src/os/linux.rs index b22e2d0..330ca1c 100644 --- a/src/os/linux.rs +++ b/src/os/linux.rs @@ -76,8 +76,59 @@ pub fn walk_regions(pid: u32) -> Vec { regions } -/// Reads `/proc//smaps` and returns heap blocks for the process. pub fn walk_heap(pid: u32) -> Vec { + let mut blocks = Vec::new(); + + let maps_path = format!("/proc/{}/maps", pid); + let maps_content = match fs::read_to_string(&maps_path) { + Ok(c) => c, + Err(_) => return blocks, + }; + + let mut heap_start = 0usize; + let mut heap_end = 0usize; + let mut vm_protect = RegionProtect::NoAccess; + + for line in maps_content.lines() { + if !line.contains("[heap]") { + continue; + } + + let mut parts = line.splitn(6, ' '); + let range = parts.next().unwrap_or(""); + let perms = parts.next().unwrap_or(""); + + let mut range_parts = range.split('-'); + heap_start = usize::from_str_radix(range_parts.next().unwrap_or("0"), 16).unwrap_or(0); + heap_end = usize::from_str_radix(range_parts.next().unwrap_or("0"), 16).unwrap_or(0); + + vm_protect = if perms.contains('x') { + RegionProtect::Execute + } else if perms.contains('w') { + RegionProtect::ReadWrite + } else if perms.contains('r') { + RegionProtect::Readonly + } else { + RegionProtect::NoAccess + }; + + break; // only one [heap] entry exists, stop looking + } + + if heap_start > 0 && heap_end > heap_start { + blocks.push(HeapBlock { + address: heap_start, + size: heap_end - heap_start, + is_free: false, + vm_protect, + }); + } + + blocks +} + +/// Reads `/proc//smaps` (or `/proc//mem`) and returns individual glibc heap chunks. +pub fn walk_heap_granular(pid: u32) -> Vec { use std::io::{Read, Seek, SeekFrom}; let mut blocks = Vec::new(); diff --git a/src/os/mod.rs b/src/os/mod.rs index 6489e75..6521b7e 100644 --- a/src/os/mod.rs +++ b/src/os/mod.rs @@ -13,6 +13,9 @@ pub use windows::WindowsMemory as PlatformMemory; #[cfg(target_os = "linux")] mod linux; +#[cfg(target_os = "linux")] +pub use linux::walk_heap_granular; + #[cfg(target_os = "linux")] pub use linux::LinuxMemory as PlatformMemory; diff --git a/src/ui/commands.rs b/src/ui/commands.rs index 67589be..bfbaf59 100644 --- a/src/ui/commands.rs +++ b/src/ui/commands.rs @@ -238,7 +238,16 @@ fn get_heap_blocks(pid: u32, _granular: bool) -> Vec { } } - #[cfg(not(target_os = "windows"))] + #[cfg(target_os = "linux")] + { + if _granular { + crate::os::walk_heap_granular(pid) + } else { + mem.walk_heap(pid).unwrap_or_default() + } + } + + #[cfg(not(any(target_os = "windows", target_os = "linux")))] { mem.walk_heap(pid).unwrap_or_default() }