mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-01-29 03:35:36 +00:00
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:
parent
09a95f5e74
commit
2fb1969902
2 changed files with 63 additions and 2 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue