kernel: implement /proc/[pid]/maps — process memory map
New ProcMaps ContextHandle that iterates over addr_space.grants and formats each grant in Linux /proc/[pid]/maps format: address_start-address_end perms 00000000 00:00 0 path Where perms is rwxp based on GrantFlags (GRANT_READ/WRITE/EXEC), and path is [file]/[vdso]/[heap] based on whether the grant is file-backed and its address range. Cross-referenced with Linux 7.1 fs/proc/task_mmu.c proc_pid_maps_op and show_vma_header_prefix/show_map_vma().
This commit is contained in:
+38
-1
@@ -20,7 +20,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{CallerCtx, KernelSchemes, OpenResult};
|
||||
use ::syscall::{ProcSchemeAttrs, SigProcControl, Sigcontrol};
|
||||
use ::syscall::{GrantFlags, ProcSchemeAttrs, SigProcControl, Sigcontrol};
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
@@ -170,6 +170,9 @@ enum ContextHandle {
|
||||
ProcStatus {
|
||||
pid: usize,
|
||||
},
|
||||
ProcMaps {
|
||||
pid: usize,
|
||||
},
|
||||
}
|
||||
#[derive(Clone)]
|
||||
struct Handle {
|
||||
@@ -389,6 +392,7 @@ impl ProcScheme {
|
||||
(Some("comm"), None) => Some(ContextHandle::ProcComm { pid }),
|
||||
(Some("cmdline"), None) => Some(ContextHandle::ProcCmdline { pid }),
|
||||
(Some("status"), None) => Some(ContextHandle::ProcStatus { pid }),
|
||||
(Some("maps"), None) => Some(ContextHandle::ProcMaps { pid }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -1893,6 +1897,39 @@ impl ContextHandle {
|
||||
let context = context.read(token.token());
|
||||
read_from(buf, proc_status_text(&context, num_threads, vsize, rss).as_bytes(), offset)
|
||||
}
|
||||
ContextHandle::ProcMaps { pid } => {
|
||||
let context = proc_context(*pid, token).ok_or(Error::new(ESRCH))?;
|
||||
let addr_space = context.read(token.token()).addr_space.clone();
|
||||
let mut output = String::new();
|
||||
if let Some(addr_space) = addr_space {
|
||||
let token2 = token.downgrade();
|
||||
let guard = addr_space.acquire_read(token2);
|
||||
for (grant_base, grant_info) in guard.grants.iter() {
|
||||
let start = grant_base.start_address().data();
|
||||
let size = grant_info.page_count() * PAGE_SIZE;
|
||||
let end = start + size;
|
||||
let grant_flags = grant_info.grant_flags();
|
||||
let perms = alloc::format!(
|
||||
"{}{}{}p",
|
||||
if grant_flags.contains(GrantFlags::GRANT_READ) { 'r' } else { '-' },
|
||||
if grant_flags.contains(GrantFlags::GRANT_WRITE) { 'w' } else { '-' },
|
||||
if grant_flags.contains(GrantFlags::GRANT_EXEC) { 'x' } else { '-' },
|
||||
);
|
||||
let path_str = if grant_info.file_ref().is_some() {
|
||||
String::from("[file]")
|
||||
} else if start < 0x10000000 {
|
||||
String::from("[vdso]")
|
||||
} else {
|
||||
String::from("[heap]")
|
||||
};
|
||||
output.push_str(&alloc::format!(
|
||||
"{:08x}-{:08x} {} 00000000 00:00 0 {}\n",
|
||||
start, end, perms, path_str
|
||||
));
|
||||
}
|
||||
}
|
||||
read_from(buf, output.as_bytes(), offset)
|
||||
}
|
||||
ContextHandle::ProcRoot | ContextHandle::ProcDir { .. } => Err(Error::new(EBADF)),
|
||||
ContextHandle::MmapMinAddr(addrspace) => {
|
||||
let mut token = token.token();
|
||||
|
||||
Reference in New Issue
Block a user