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>
This commit is contained in:
Stephen Barber 2017-08-07 16:01:53 -07:00 committed by chrome-bot
parent 09a95f5e74
commit 2fb1969902
2 changed files with 63 additions and 2 deletions

View file

@ -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

View file

@ -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.
///