diff --git a/aya/src/maps/perf/perf_buffer.rs b/aya/src/maps/perf/perf_buffer.rs index e04e1e2c..3fa4b0dd 100644 --- a/aya/src/maps/perf/perf_buffer.rs +++ b/aya/src/maps/perf/perf_buffer.rs @@ -145,28 +145,24 @@ impl PerfBuffer { return Err(PerfBufferError::NoBuffers); } let header = self.buf().as_ptr(); - let base = header as usize + self.page_size; + let base = unsafe { header.byte_add(self.page_size) }; let mut events = Events { read: 0, lost: 0 }; let mut buf_n = 0; - let fill_buf = |start_off, base, mmap_size, out_buf: &mut [u8]| { + let fill_buf = |start_off, base: *const u8, mmap_size, out_buf: &mut [u8]| { let len = out_buf.len(); let end = (start_off + len) % mmap_size; let start = start_off % mmap_size; if start < end { - out_buf.copy_from_slice(unsafe { - slice::from_raw_parts((base + start) as *const u8, len) - }); + out_buf.copy_from_slice(unsafe { slice::from_raw_parts(base.add(start), len) }); } else { let size = mmap_size - start; unsafe { - out_buf[..size] - .copy_from_slice(slice::from_raw_parts((base + start) as *const u8, size)); - out_buf[size..] - .copy_from_slice(slice::from_raw_parts(base as *const u8, len - size)); + out_buf[..size].copy_from_slice(slice::from_raw_parts(base.add(start), size)); + out_buf[size..].copy_from_slice(slice::from_raw_parts(base, len - size)); } } }; @@ -227,11 +223,11 @@ impl PerfBuffer { let buf = &mut buffers[buf_n]; let event_start = tail % self.size; - let event = - unsafe { ptr::read_unaligned((base + event_start) as *const perf_event_header) }; + let event: perf_event_header = + unsafe { ptr::read_unaligned(base.byte_add(event_start).cast()) }; let event_size = event.size as usize; - match read_event(event_start, event.type_, base, buf) { + match read_event(event_start, event.type_, base.cast(), buf) { Ok(Some((read, lost))) => { if read > 0 { buf_n += 1; @@ -290,14 +286,15 @@ mod tests { data: [u8; PAGE_SIZE * 2], } - fn fake_mmap(buf: &MMappedBuf) { + fn fake_mmap(buf: &mut MMappedBuf) { + let buf: *mut _ = buf; override_syscall(|call| match call { Syscall::PerfEventOpen { .. } | Syscall::PerfEventIoctl { .. } => { Ok(crate::MockableFd::mock_signed_fd().into()) } call => panic!("unexpected syscall: {:?}", call), }); - TEST_MMAP_RET.with(|ret| *ret.borrow_mut() = buf as *const _ as *mut _); + TEST_MMAP_RET.with(|ret| *ret.borrow_mut() = buf.cast()); } #[test] @@ -318,27 +315,25 @@ mod tests { #[test] fn test_no_out_bufs() { - let mmapped_buf = MMappedBuf { + let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); + fake_mmap(&mut mmapped_buf); let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); + assert_matches!(buf.read_events(&mut []), Err(PerfBufferError::NoBuffers)) } #[test] - #[cfg_attr( - miri, - ignore = "`unsafe { (*header).data_tail = tail as u64 };` is attempting a write access using using a tag that only grants SharedReadOnly permission" - )] fn test_no_events() { - let mmapped_buf = MMappedBuf { + let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); + fake_mmap(&mut mmapped_buf); let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); + let out_buf = BytesMut::with_capacity(4); assert_eq!( buf.read_events(&mut [out_buf]).unwrap(), @@ -346,13 +341,18 @@ mod tests { ); } + fn write(mmapped_buf: &mut MMappedBuf, offset: usize, value: T) -> usize { + let dst: *mut _ = mmapped_buf; + let head = offset + mem::size_of::(); + unsafe { + ptr::write_unaligned(dst.byte_add(PAGE_SIZE + offset).cast(), value); + mmapped_buf.mmap_page.data_head = head as u64; + } + head + } + #[test] fn test_read_first_lost() { - let mut mmapped_buf = MMappedBuf { - data: [0; PAGE_SIZE * 2], - }; - fake_mmap(&mmapped_buf); - #[repr(C)] #[derive(Debug)] struct LostSamples { @@ -361,18 +361,27 @@ mod tests { count: u64, } - let evt = LostSamples { - header: perf_event_header { - type_: PERF_RECORD_LOST as u32, - misc: 0, - size: mem::size_of::() as u16, - }, - id: 1, - count: 0xCAFEBABE, + let mut mmapped_buf = MMappedBuf { + data: [0; PAGE_SIZE * 2], }; - write(&mut mmapped_buf, 0, evt); + write( + &mut mmapped_buf, + 0, + LostSamples { + header: perf_event_header { + type_: PERF_RECORD_LOST as u32, + misc: 0, + size: mem::size_of::() as u16, + }, + id: 1, + count: 0xCAFEBABE, + }, + ); + + fake_mmap(&mut mmapped_buf); let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); + let out_buf = BytesMut::with_capacity(0); let events = buf.read_events(&mut [out_buf]).unwrap(); assert_eq!(events.lost, 0xCAFEBABE); @@ -385,28 +394,22 @@ mod tests { value: T, } - fn write(mmapped_buf: &mut MMappedBuf, offset: usize, value: T) -> usize { - let dst: *mut _ = mmapped_buf; - unsafe { - ptr::write_unaligned(dst.byte_add(PAGE_SIZE + offset).cast(), value); - mmapped_buf.mmap_page.data_head = (offset + mem::size_of::()) as u64; - mmapped_buf.mmap_page.data_head as usize - } - } - fn write_sample(mmapped_buf: &mut MMappedBuf, offset: usize, value: T) -> usize { - let sample = PerfSample { - s_hdr: Sample { - header: perf_event_header { - type_: PERF_RECORD_SAMPLE as u32, - misc: 0, - size: mem::size_of::>() as u16, + write( + mmapped_buf, + offset, + PerfSample { + s_hdr: Sample { + header: perf_event_header { + type_: PERF_RECORD_SAMPLE as u32, + misc: 0, + size: mem::size_of::>() as u16, + }, + size: mem::size_of::() as u32, }, - size: mem::size_of::() as u32, + value, }, - value, - }; - write(mmapped_buf, offset, sample) + ) } fn u32_from_buf(buf: &[u8]) -> u32 { @@ -422,11 +425,12 @@ mod tests { let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); - let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); write_sample(&mut mmapped_buf, 0, 0xCAFEBABEu32); + fake_mmap(&mut mmapped_buf); + let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); + let mut out_bufs = [BytesMut::with_capacity(4)]; let events = buf.read_events(&mut out_bufs).unwrap(); @@ -439,12 +443,13 @@ mod tests { let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); - let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); let next = write_sample(&mut mmapped_buf, 0, 0xCAFEBABEu32); write_sample(&mut mmapped_buf, next, 0xBADCAFEu32); + fake_mmap(&mut mmapped_buf); + let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); + let mut out_bufs = [BytesMut::with_capacity(4)]; let events = buf.read_events(&mut out_bufs).unwrap(); @@ -461,12 +466,13 @@ mod tests { let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); - let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); let next = write_sample(&mut mmapped_buf, 0, 0xCAFEBABEu32); write_sample(&mut mmapped_buf, next, 0xBADCAFEu32); + fake_mmap(&mut mmapped_buf); + let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); + let mut out_bufs = (0..3) .map(|_| BytesMut::with_capacity(4)) .collect::>(); @@ -482,12 +488,13 @@ mod tests { let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); - let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); let offset = PAGE_SIZE - mem::size_of::>(); - mmapped_buf.mmap_page.data_tail = offset as u64; write_sample(&mut mmapped_buf, offset, 0xCAFEBABEu32); + mmapped_buf.mmap_page.data_tail = offset as u64; + + fake_mmap(&mut mmapped_buf); + let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); let mut out_bufs = [BytesMut::with_capacity(4)]; @@ -501,31 +508,31 @@ mod tests { let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); - let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); - - let header = perf_event_header { - type_: PERF_RECORD_SAMPLE as u32, - misc: 0, - size: mem::size_of::>() as u16, - }; let offset = PAGE_SIZE - mem::size_of::() - 2; + write( + &mut mmapped_buf, + offset, + perf_event_header { + type_: PERF_RECORD_SAMPLE as u32, + misc: 0, + size: mem::size_of::>() as u16, + }, + ); mmapped_buf.mmap_page.data_tail = offset as u64; - write(&mut mmapped_buf, offset, header); - #[cfg(target_endian = "little")] - { - write(&mut mmapped_buf, PAGE_SIZE - 2, 0x0004u16); - write(&mut mmapped_buf, 0, 0x0000u16); - } - #[cfg(target_endian = "big")] - { - write(&mut mmapped_buf, PAGE_SIZE - 2, 0x0000u16); - write(&mut mmapped_buf, 0, 0x0004u16); - } + let (left, right) = if cfg!(target_endian = "little") { + (0x0004u16, 0x0000u16) + } else { + (0x0000u16, 0x0004u16) + }; + write(&mut mmapped_buf, PAGE_SIZE - 2, left); + write(&mut mmapped_buf, 0, right); write(&mut mmapped_buf, 2, 0xBAADCAFEu32); + fake_mmap(&mut mmapped_buf); + let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); + let mut out_bufs = [BytesMut::with_capacity(8)]; let events = buf.read_events(&mut out_bufs).unwrap(); @@ -538,31 +545,34 @@ mod tests { let mut mmapped_buf = MMappedBuf { data: [0; PAGE_SIZE * 2], }; - fake_mmap(&mmapped_buf); - let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); - let sample = PerfSample { - s_hdr: Sample { - header: perf_event_header { - type_: PERF_RECORD_SAMPLE as u32, - misc: 0, - size: mem::size_of::>() as u16, - }, - size: mem::size_of::() as u32, - }, - #[cfg(target_endian = "little")] - value: 0xCAFEBABEu32, - #[cfg(target_endian = "big")] - value: 0xBAADCAFEu32, + let (left, right) = if cfg!(target_endian = "little") { + (0xCAFEBABEu32, 0xBAADCAFEu32) + } else { + (0xBAADCAFEu32, 0xCAFEBABEu32) }; let offset = PAGE_SIZE - mem::size_of::>(); + write( + &mut mmapped_buf, + offset, + PerfSample { + s_hdr: Sample { + header: perf_event_header { + type_: PERF_RECORD_SAMPLE as u32, + misc: 0, + size: mem::size_of::>() as u16, + }, + size: mem::size_of::() as u32, + }, + value: left, + }, + ); + write(&mut mmapped_buf, 0, right); mmapped_buf.mmap_page.data_tail = offset as u64; - write(&mut mmapped_buf, offset, sample); - #[cfg(target_endian = "little")] - write(&mut mmapped_buf, 0, 0xBAADCAFEu32); - #[cfg(target_endian = "big")] - write(&mut mmapped_buf, 0, 0xCAFEBABEu32); + + fake_mmap(&mut mmapped_buf); + let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); let mut out_bufs = [BytesMut::with_capacity(8)];