in reverie-ptrace/src/trace/memory.rs [161:189]
fn write(&mut self, addr: AddrMut<u8>, buf: &[u8]) -> Result<usize, Errno> {
let size = buf.len();
if size == 0 {
return Ok(0);
} else if size == mem::size_of::<u64>() {
#[allow(clippy::cast_ptr_alignment)]
let value = unsafe { *(buf.as_ptr() as *const u64) };
self.write_u64(addr.cast::<u64>(), value)?;
return Ok(size);
}
let mut addr_slice = unsafe { AddrSliceMut::from_raw_parts(addr, buf.len()) };
// Since process_vm_writev partial transfers apply at the granularity of
// the iovec elements, we need to know if the address range spans a page
// boundary and split the remote write if it does. This helps ensure that
// we get a write length >0 before we hit a protected page.
if let Some((mut first, mut second)) = addr_slice.split_at_page_boundary() {
let mut remote = unsafe { [first.as_ioslice_mut(), second.as_ioslice_mut()] };
// The two remote writes come from a single local buffer.
let local = [io::IoSlice::new(buf)];
self.write_vectored(&local, &mut remote)
} else {
// The address range fits into one page. Nothing special to do.
self.write_aligned(addr, buf)
}
}