fn read()

in reverie-ptrace/src/trace/memory.rs [124:159]


    fn read<'a, A>(&self, addr: A, buf: &mut [u8]) -> Result<usize, Errno>
    where
        A: Into<Addr<'a, u8>>,
    {
        let addr = addr.into();
        let size = buf.len();
        if size == 0 {
            return Ok(0);
        } else if size <= mem::size_of::<u64>() {
            // This needs to be benchmarked, but according to @wangbj
            // PTRACE_PEEKDATA is faster than `process_vm_readv` for small
            // reads.
            let value = self.read_u64(addr.cast::<u64>())?;
            let bytes = value.to_ne_bytes();
            buf.copy_from_slice(&bytes[0..size]);
            return Ok(size);
        }

        let addr_slice = unsafe { AddrSlice::from_raw_parts(addr, buf.len()) };

        // Since process_vm_readv 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 read if it does. This helps ensure that
        // we get a read length >0 while there is still more data to read.
        if let Some((first, second)) = addr_slice.split_at_page_boundary() {
            let remote = unsafe { [first.as_ioslice(), second.as_ioslice()] };

            // The two remote reads are merged into a single local buffer.
            let mut local = [io::IoSliceMut::new(buf)];

            self.read_vectored(&remote, &mut local)
        } else {
            // The address range fits into one page. Nothing special to do.
            self.read_aligned(addr, buf)
        }
    }