From 95e26ef0bbb28f578bdb73c09d6f38f12378eb43 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Wed, 22 Oct 2025 11:58:27 -0700 Subject: [PATCH] Request host address translation via QMP Heuristics using the largest allocation chunk are often insufficient --- src/lib.rs | 10 +++++----- src/mem_map.rs | 43 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1d4939f..1d40e87 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,12 +145,12 @@ impl QemuProcfs

{ ); } - let qemu_map = biggest_map.ok_or_else(|| Error(ErrorOrigin::Connector, ErrorKind::NotFound) - .log_error("Unable to find the QEMU guest memory map. This usually indicates insufficient permissions to acquire the QEMU memory maps. Are you running with appropiate access rights?") - )?; - - info!("qemu memory map found {:?}", qemu_map); + if let Some(qemu_map) = &biggest_map { + info!("qemu memory map found {:?}", qemu_map); + } + let qemu_map = biggest_map + .unwrap_or(CTup2(Address::INVALID, 0)); Self::with_cmdline_and_mem(prc, &cmdline, qemu_map) } diff --git a/src/mem_map.rs b/src/mem_map.rs index b4d5794..e39d058 100644 --- a/src/mem_map.rs +++ b/src/mem_map.rs @@ -19,6 +19,7 @@ struct Mapping { pub range_start: umem, pub range_end: umem, pub remap_start: umem, + pub host_start: Option, } impl Mapping { @@ -27,6 +28,7 @@ impl Mapping { range_start, range_end, remap_start, + host_start: None, } } } @@ -35,6 +37,13 @@ pub fn qemu_mem_mappings( cmdline: &str, qemu_map: &CTup2, ) -> Result> { + let qemu_map = || match qemu_map { + qemu_map if qemu_map.0 != Address::INVALID => + Err(Error(ErrorOrigin::Connector, ErrorKind::NotFound) + .log_error("Unable to find the QEMU guest memory map. This usually indicates insufficient permissions to acquire the QEMU memory maps. Are you running with appropiate access rights?") + ), + qemu_map => Ok(qemu_map), + }; let mut mem_map = MemoryMap::new(); let mappings = if let Ok(mappings) = qmp_get_mtree(cmdline.split_whitespace()) { @@ -54,15 +63,21 @@ pub fn qemu_mem_mappings( .unwrap_or_else(|| "pc".into()) }; info!("qemu process started with machine: {}", machine); - qemu_get_mtree_fallback(&machine, qemu_map) + qemu_get_mtree_fallback(&machine, qemu_map()?) }; // add all mappings + let mut real_base = None; for mapping in mappings.iter() { + let real_base = match mapping.host_start.map(Address::from).or(real_base) { + Some(start) => start, + None => *real_base.insert(qemu_map()?.0) + mapping.remap_start, + }; + mem_map.push_range( mapping.range_start.into(), mapping.range_end.into(), - qemu_map.0 + mapping.remap_start, + real_base, ); } @@ -115,7 +130,29 @@ fn qmp_get_mtree_stream(stream: S) -> Result + mapping.host_start = Some(hva), + _ => { + log::warn!("failed to parse host address from {line:?}"); + }, + } + } + } + + Ok(mappings) } #[cfg(not(all(target_os = "linux", feature = "qmp")))]