summary refs log tree commit diff
path: root/sys_util
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
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')
-rw-r--r--sys_util/src/guest_memory.rs30
-rw-r--r--sys_util/src/mmap.rs35
2 files changed, 63 insertions, 2 deletions
diff --git a/sys_util/src/guest_memory.rs b/sys_util/src/guest_memory.rs
index f8f7874..4a41e05 100644
--- a/sys_util/src/guest_memory.rs
+++ b/sys_util/src/guest_memory.rs
@@ -155,6 +155,36 @@ impl GuestMemory {
         })
     }
 
+    /// Reads to a slice from guest memory at the specified guest address.
+    /// 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 length 16 at guestaddress 0x200.
+    ///
+    /// ```
+    /// # use sys_util::{GuestAddress, GuestMemory, MemoryMapping};
+    /// # fn test_write_u64() -> Result<(), ()> {
+    /// #   let start_addr = GuestAddress(0x1000);
+    /// #   let mut gm = GuestMemory::new(&vec![(start_addr, 0x400)]).map_err(|_| ())?;
+    ///     let buf = &mut [0u8; 16];
+    ///     let res = gm.read_slice_at_addr(buf, GuestAddress(0x200));
+    ///     assert_eq!(Ok(16), res);
+    ///     Ok(())
+    /// # }
+    /// ```
+    pub fn read_slice_at_addr(&self,
+                              mut buf: &mut [u8],
+                              guest_addr: GuestAddress)
+                              -> Result<usize> {
+        self.do_in_region(guest_addr, move |mapping, offset| {
+            mapping
+                .read_slice(buf, offset)
+                .map_err(|_| Error::InvalidGuestAddress(guest_addr))
+        })
+    }
+
     /// Reads an object from guest memory at the given guest address.
     /// Reading from a volatile area isn't strictly safe as it could change
     /// mid-read.  However, as long as the type T is plain old data and can
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.
     ///