summary refs log tree commit diff
path: root/sys_util/src/mmap.rs
diff options
context:
space:
mode:
authorStephen Barber <smbarber@chromium.org>2017-08-07 16:01:53 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-08-09 11:47:55 -0700
commit2fb1969902f8b81466c21df02dfc283732998bbf (patch)
treeafd4e1256949b0ccc671b602e417cd8ce989e256 /sys_util/src/mmap.rs
parent09a95f5e74c47d43a1f6962fca108466d8cc31e5 (diff)
downloadcrosvm-2fb1969902f8b81466c21df02dfc283732998bbf.tar
crosvm-2fb1969902f8b81466c21df02dfc283732998bbf.tar.gz
crosvm-2fb1969902f8b81466c21df02dfc283732998bbf.tar.bz2
crosvm-2fb1969902f8b81466c21df02dfc283732998bbf.tar.lz
crosvm-2fb1969902f8b81466c21df02dfc283732998bbf.tar.xz
crosvm-2fb1969902f8b81466c21df02dfc283732998bbf.tar.zst
crosvm-2fb1969902f8b81466c21df02dfc283732998bbf.zip
sys_util: add read_slice_at_addr to GuestMemory
BUG=none
TEST=cargo test

Change-Id: Ifeda91de37bf83a2e5a00f5e308db786fa5d49d5
Signed-off-by: Stephen Barber <smbarber@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/604934
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'sys_util/src/mmap.rs')
-rw-r--r--sys_util/src/mmap.rs35
1 files changed, 33 insertions, 2 deletions
diff --git a/sys_util/src/mmap.rs b/sys_util/src/mmap.rs
index 732c4f0..78f533d 100644
--- a/sys_util/src/mmap.rs
+++ b/sys_util/src/mmap.rs
@@ -25,8 +25,10 @@ pub enum Error {
     ReadFromSource,
     /// `mmap` returned the given error.
     SystemCallFailed(errno::Error),
-    /// Wrting to memory failed
+    /// Writing to memory failed
     WriteToMemory(std::io::Error),
+    /// Reading from memory failed
+    ReadFromMemory(std::io::Error),
 }
 pub type Result<T> = std::result::Result<T, Error>;
 
@@ -115,7 +117,7 @@ impl MemoryMapping {
     /// ```
     /// #   use sys_util::MemoryMapping;
     /// #   let mut mem_map = MemoryMapping::new(1024).unwrap();
-    ///     let res = mem_map.write_slice(&[1,2,3,4,5], 0);
+    ///     let res = mem_map.write_slice(&[1,2,3,4,5], 256);
     ///     assert!(res.is_ok());
     ///     assert_eq!(res.unwrap(), 5);
     /// ```
@@ -132,6 +134,35 @@ impl MemoryMapping {
         }
     }
 
+    /// Reads to a slice from the memory region at the specified offset.
+    /// Returns the number of bytes read.  The number of bytes read can
+    /// be less than the length of the slice if there isn't enough room in the
+    /// memory region.
+    ///
+    /// # Examples
+    /// * Read a slice of size 16 at offset 256.
+    ///
+    /// ```
+    /// #   use sys_util::MemoryMapping;
+    /// #   let mut mem_map = MemoryMapping::new(1024).unwrap();
+    ///     let buf = &mut [0u8; 16];
+    ///     let res = mem_map.read_slice(buf, 256);
+    ///     assert!(res.is_ok());
+    ///     assert_eq!(res.unwrap(), 16);
+    /// ```
+    pub fn read_slice(&self, mut buf: &mut [u8], offset: usize) -> Result<usize> {
+        if offset >= self.size {
+            return Err(Error::InvalidAddress);
+        }
+        unsafe {
+            // Guest memory can't strictly be modeled as a slice because it is
+            // volatile.  Writing to it with what compiles down to a memcpy
+            // won't hurt anything as long as we get the bounds checks right.
+            let slice: &[u8] = &self.as_slice()[offset..];
+            Ok(buf.write(slice).map_err(Error::ReadFromMemory)?)
+        }
+    }
+
     /// Writes an object to the memory region at the specified offset.
     /// Returns Ok(()) if the object fits, or Err if it extends past the end.
     ///