use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use eyre::{eyre, Result};
use procfs::{
process::{MemoryMap, MemoryMaps},
FromRead,
};
use crate::cli::memfault_core_handler::memory_range::MemoryRange;
use crate::cli::memfault_core_handler::ElfPtrSize;
pub fn proc_mem_stream(pid: i32) -> Result<File> {
let proc_mem_stream = File::open(format!("/proc/{}/mem", pid))?;
Ok(proc_mem_stream)
}
pub fn read_proc_mem<P: Read + Seek>(
proc_mem_stream: &mut P,
vaddr: ElfPtrSize,
size: ElfPtrSize,
) -> Result<Vec<u8>> {
proc_mem_stream.seek(SeekFrom::Start(vaddr as _))?;
let mut buf = vec![0; size as usize];
proc_mem_stream.read_exact(&mut buf)?;
Ok(buf)
}
pub trait ProcMaps {
fn get_process_maps(&mut self) -> Result<Vec<MemoryMap>>;
}
#[derive(Debug)]
pub struct ProcMapsImpl {
pid: i32,
}
impl ProcMapsImpl {
pub fn new(pid: i32) -> Self {
Self { pid }
}
}
impl ProcMaps for ProcMapsImpl {
fn get_process_maps(&mut self) -> Result<Vec<MemoryMap>> {
let maps_file_name = format!("/proc/{}/maps", self.pid);
Ok(MemoryMaps::from_file(maps_file_name)
.map_err(|e| eyre!("Failed to read /proc/{}/maps: {}", self.pid, e))?
.0)
}
}
impl From<&MemoryMap> for MemoryRange {
fn from(m: &MemoryMap) -> Self {
MemoryRange {
start: m.address.0 as ElfPtrSize,
end: m.address.1 as ElfPtrSize,
}
}
}