1use std::borrow::Cow;
99use std::mem::MaybeUninit;
100
101use perf_event_open_sys::bindings;
102
103use crate::endian::Endian;
104use crate::parsebuf::{ParseBufCursor, TrackingParseBuf};
105use crate::util::cow::CowSliceExt;
106use crate::{Record, RecordMetadata, SampleId, Visitor};
107
108used_in_docs!(Record);
109
110pub use crate::config::ParseConfig;
111pub use crate::error::{ErrorKind, ParseError, ParseResult};
112pub use crate::parsebuf::{ParseBuf, ParseBufChunk};
113
114pub trait Parse<'p>: Sized {
116 fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
118 where
119 E: Endian,
120 B: ParseBuf<'p>;
121}
122
123#[derive(Clone)]
145pub struct Parser<B, E> {
146 config: ParseConfig<E>,
147 data: TrackingParseBuf<B>,
148}
149
150impl<'p, B, E> Parser<B, E>
151where
152 E: Endian,
153 B: ParseBuf<'p>,
154{
155 pub fn new(data: B, config: ParseConfig<E>) -> Self {
157 Self {
158 config,
159 data: TrackingParseBuf::new(data),
160 }
161 }
162
163 #[inline]
165 pub fn config(&self) -> &ParseConfig<E> {
166 &self.config
167 }
168
169 #[inline]
171 pub fn endian(&self) -> &E {
172 self.config.endian()
173 }
174
175 pub(crate) fn split_at(&mut self, offset: usize) -> ParseResult<Parser<ParseBufCursor<'p>, E>> {
178 let cursor = ParseBufCursor::new(&mut self.data, offset)?;
179 Ok(Parser::new(cursor, self.config().clone()))
180 }
181
182 fn safe_capacity_bound<T>(&self) -> usize {
189 const DEFAULT_LEN: usize = 16384;
190
191 let size = std::mem::size_of::<T>();
192 if size == 0 {
194 return usize::MAX;
195 }
196
197 self.data.remaining_hint().unwrap_or(DEFAULT_LEN) / size
201 }
202
203 fn parse_bytes_direct(&mut self, len: usize) -> ParseResult<Option<&'p [u8]>> {
204 let chunk = match self.data.chunk()? {
205 ParseBufChunk::External(chunk) => chunk,
206 _ => return Ok(None),
207 };
208
209 if chunk.len() < len {
210 return Ok(None);
211 }
212
213 self.data.advance(len);
214 Ok(Some(&chunk[..len]))
215 }
216
217 #[cold]
219 fn parse_bytes_slow(&mut self, mut len: usize) -> ParseResult<Vec<u8>> {
220 let mut bytes = Vec::with_capacity(self.safe_capacity_bound::<u8>().min(len));
221
222 while len > 0 {
223 let mut chunk = self.data.chunk()?;
224 chunk.truncate(len);
225 bytes.extend_from_slice(&chunk);
226
227 let chunk_len = chunk.len();
228 len -= chunk_len;
229 self.data.advance(chunk_len);
230 }
231
232 Ok(bytes)
233 }
234
235 pub fn parse_bytes(&mut self, len: usize) -> ParseResult<Cow<'p, [u8]>> {
237 if let Some(bytes) = self.parse_bytes_direct(len)? {
238 return Ok(Cow::Borrowed(bytes));
239 }
240
241 match self.data.remaining_hint() {
242 Some(hint) if hint >= len => (),
243 _ => return Ok(Cow::Owned(self.parse_bytes_slow(len)?)),
244 }
245
246 let mut bytes = Vec::with_capacity(len);
247 self.parse_to_slice(bytes.spare_capacity_mut())?;
248 unsafe { bytes.set_len(len) };
249 Ok(Cow::Owned(bytes))
250 }
251
252 fn parse_bytes_ignored(&mut self, mut len: usize) -> ParseResult<()> {
255 while len > 0 {
256 let chunk = self.data.chunk()?;
257 let consumed = chunk.len().min(len);
258
259 len -= consumed;
260 self.data.advance(consumed);
261 }
262
263 Ok(())
264 }
265
266 fn parse_to_slice(&mut self, slice: &mut [MaybeUninit<u8>]) -> ParseResult<()> {
269 let mut dst = slice.as_mut_ptr() as *mut u8;
270 let mut len = slice.len();
271
272 while len > 0 {
273 let chunk = self.data.chunk()?;
274 let chunk_len = chunk.len().min(len);
275
276 unsafe {
277 std::ptr::copy_nonoverlapping(chunk.as_ptr(), dst, chunk_len);
278 dst = dst.add(chunk_len);
279 len -= chunk_len;
280 };
281
282 self.data.advance(chunk_len);
283 }
284
285 Ok(())
286 }
287
288 #[cold]
289 fn parse_array_slow<const N: usize>(&mut self) -> ParseResult<[u8; N]> {
290 let mut array = [0u8; N];
291 self.parse_to_slice(unsafe { array.align_to_mut().1 })?;
292 Ok(array)
293 }
294
295 pub(crate) fn parse_array<const N: usize>(&mut self) -> ParseResult<[u8; N]> {
296 let chunk = self.data.chunk()?;
297
298 if chunk.len() < N {
299 return self.parse_array_slow();
300 }
301
302 let mut array = [0u8; N];
303 array.copy_from_slice(&chunk[..N]);
304 self.data.advance(N);
305 Ok(array)
306 }
307
308 pub fn parse<P: Parse<'p>>(&mut self) -> ParseResult<P> {
312 P::parse(self)
313 }
314
315 pub fn parse_with<F, R>(&mut self, func: F) -> ParseResult<R>
317 where
318 F: FnOnce(&mut Self) -> ParseResult<R>,
319 {
320 func(self)
321 }
322
323 pub fn parse_if<P: Parse<'p>>(&mut self, parse: bool) -> ParseResult<Option<P>> {
325 self.parse_if_with(parse, P::parse)
326 }
327
328 pub fn parse_if_with<F, R>(&mut self, parse: bool, func: F) -> ParseResult<Option<R>>
330 where
331 F: FnOnce(&mut Self) -> ParseResult<R>,
332 {
333 match parse {
334 true => self.parse_with(func).map(Some),
335 false => Ok(None),
336 }
337 }
338
339 pub(crate) fn parse_padded<F, R>(&mut self, padding: usize, func: F) -> ParseResult<R>
348 where
349 F: FnOnce(&mut Self) -> ParseResult<R>,
350 {
351 assert_ne!(padding, 0);
352
353 let offset = self.data.offset();
354 let value = func(self)?;
355 let parsed = self.data.offset() - offset;
356
357 match parsed % padding {
358 0 => (),
360 n => self.parse_bytes_ignored(padding - n)?,
361 }
362
363 Ok(value)
364 }
365
366 pub fn parse_u8(&mut self) -> ParseResult<u8> {
368 let [byte] = self.parse_array()?;
369 Ok(byte)
370 }
371
372 pub fn parse_u16(&mut self) -> ParseResult<u16> {
374 let array = self.parse_array()?;
375 Ok(self.endian().convert_u16(array))
376 }
377
378 pub fn parse_u32(&mut self) -> ParseResult<u32> {
380 let array = self.parse_array()?;
381 Ok(self.endian().convert_u32(array))
382 }
383
384 pub fn parse_u64(&mut self) -> ParseResult<u64> {
386 let array = self.parse_array()?;
387 Ok(self.endian().convert_u64(array))
388 }
389
390 pub fn parse_rest(&mut self) -> ParseResult<Cow<'p, [u8]>> {
392 let mut bytes = self.data.chunk()?.to_cow();
393 self.data.advance(bytes.len());
394
395 loop {
396 match self.data.chunk() {
397 Ok(chunk) => {
398 bytes.to_mut().extend_from_slice(&chunk);
399
400 let len = chunk.len();
401 self.data.advance(len);
402 }
403 Err(e) if e.kind() == ErrorKind::Eof => break,
404 Err(e) => return Err(e),
405 }
406 }
407
408 Ok(bytes)
409 }
410
411 pub fn parse_rest_trim_nul(&mut self) -> ParseResult<Cow<'p, [u8]>> {
413 let mut bytes = self.parse_rest()?;
414
415 let mut rest = &*bytes;
417 while let Some((b'\0', head)) = rest.split_last() {
418 rest = head;
419 }
420
421 bytes.truncate(rest.len());
422 Ok(bytes)
423 }
424
425 pub unsafe fn parse_slice_direct<T>(&mut self, len: usize) -> ParseResult<Option<&'p [T]>>
442 where
443 T: Copy,
444 {
445 if !self.endian().is_native() {
448 return Ok(None);
449 }
450
451 let byte_len = len.checked_mul(std::mem::size_of::<T>()).ok_or_else(|| {
452 ParseError::custom(
453 ErrorKind::InvalidRecord,
454 "array length in bytes larger than usize::MAX",
455 )
456 })?;
457 let bytes = match self.parse_bytes_direct(byte_len)? {
458 Some(bytes) => bytes,
459 None => return Ok(None),
460 };
461 let (head, slice, tail) = bytes.align_to();
462
463 if !head.is_empty() || !tail.is_empty() {
464 return Ok(None);
465 }
466
467 Ok(Some(slice))
468 }
469
470 pub unsafe fn parse_slice<T>(&mut self, len: usize) -> ParseResult<Cow<'p, [T]>>
478 where
479 T: Parse<'p> + Copy,
480 {
481 Ok(match self.parse_slice_direct(len)? {
482 Some(slice) => Cow::Borrowed(slice),
483 None => Cow::Owned(self.parse_repeated(len)?),
484 })
485 }
486
487 pub fn parse_repeated<T: Parse<'p>>(&mut self, len: usize) -> ParseResult<Vec<T>> {
489 let mut vec = Vec::with_capacity(len.min(self.safe_capacity_bound::<T>()));
490 for _ in 0..len {
491 vec.push(self.parse()?);
492 }
493
494 Ok(vec)
495 }
496
497 pub fn parse_metadata(
503 &mut self,
504 ) -> ParseResult<(Parser<impl ParseBuf<'p>, E>, RecordMetadata)> {
505 let header = self.parse()?;
506 self.parse_metadata_with_header(header)
507 }
508
509 fn parse_metadata_with_header_impl(
510 &mut self,
511 header: bindings::perf_event_header,
512 ) -> ParseResult<(Parser<ParseBufCursor<'p>, E>, RecordMetadata)> {
513 use perf_event_open_sys::bindings::*;
514 use std::mem;
515
516 let data_len = (header.size as usize)
517 .checked_sub(mem::size_of_val(&header))
518 .ok_or_else(|| {
519 ParseError::custom(
520 ErrorKind::InvalidRecord,
521 "header size was too small to be valid",
522 )
523 })?;
524 let mut rp = self.split_at(data_len)?;
525 let (p, sample_id) = match header.type_ {
528 PERF_RECORD_MMAP | PERF_RECORD_SAMPLE => (rp, SampleId::default()),
529 _ => {
530 let remaining_len = data_len
531 .checked_sub(SampleId::estimate_len(rp.config()))
532 .ok_or_else(|| ParseError::custom(
533 ErrorKind::InvalidRecord,
534 "config has sample_id_all bit set but record does not have enough data to store the sample_id"
535 ))?;
536
537 let p = rp.split_at(remaining_len)?;
538 (p, rp.parse()?)
539 }
540 };
541
542 let metadata = RecordMetadata::new(header, sample_id);
543 Ok((p, metadata))
544 }
545
546 pub fn parse_metadata_with_header(
548 &mut self,
549 header: bindings::perf_event_header,
550 ) -> ParseResult<(Parser<impl ParseBuf<'p>, E>, RecordMetadata)> {
551 self.parse_metadata_with_header_impl(header)
552 }
553
554 pub fn parse_record<V: Visitor<'p>>(&mut self, visitor: V) -> ParseResult<V::Output> {
556 let header = self.parse()?;
557 self.parse_record_with_header(visitor, header)
558 }
559
560 fn parse_record_impl<V: Visitor<'p>>(
561 self,
562 visitor: V,
563 metadata: RecordMetadata,
564 ) -> ParseResult<V::Output> {
565 use perf_event_open_sys::bindings::*;
566
567 let mut p = Parser::new(self.data, self.config.with_misc(metadata.misc()));
568
569 Ok(match metadata.ty() {
570 PERF_RECORD_MMAP => visitor.visit_mmap(p.parse()?, metadata),
571 PERF_RECORD_LOST => visitor.visit_lost(p.parse()?, metadata),
572 PERF_RECORD_COMM => visitor.visit_comm(p.parse()?, metadata),
573 PERF_RECORD_EXIT => visitor.visit_exit(p.parse()?, metadata),
574 PERF_RECORD_THROTTLE => visitor.visit_throttle(p.parse()?, metadata),
575 PERF_RECORD_UNTHROTTLE => visitor.visit_unthrottle(p.parse()?, metadata),
576 PERF_RECORD_FORK => visitor.visit_fork(p.parse()?, metadata),
577 PERF_RECORD_READ => visitor.visit_read(p.parse()?, metadata),
578 PERF_RECORD_SAMPLE => visitor.visit_sample(p.parse()?, metadata),
579 PERF_RECORD_MMAP2 => visitor.visit_mmap2(p.parse()?, metadata),
580 PERF_RECORD_AUX => visitor.visit_aux(p.parse()?, metadata),
581 PERF_RECORD_ITRACE_START => visitor.visit_itrace_start(p.parse()?, metadata),
582 PERF_RECORD_LOST_SAMPLES => visitor.visit_lost_samples(p.parse()?, metadata),
583 PERF_RECORD_SWITCH_CPU_WIDE => visitor.visit_switch_cpu_wide(p.parse()?, metadata),
584 PERF_RECORD_NAMESPACES => visitor.visit_namespaces(p.parse()?, metadata),
585 PERF_RECORD_KSYMBOL => visitor.visit_ksymbol(p.parse()?, metadata),
586 PERF_RECORD_BPF_EVENT => visitor.visit_bpf_event(p.parse()?, metadata),
587 PERF_RECORD_CGROUP => visitor.visit_cgroup(p.parse()?, metadata),
588 PERF_RECORD_TEXT_POKE => visitor.visit_text_poke(p.parse()?, metadata),
589 PERF_RECORD_AUX_OUTPUT_HW_ID => visitor.visit_aux_output_hw_id(p.parse()?, metadata),
590 _ => visitor.visit_unknown(p.parse_rest()?, metadata),
591 })
592 }
593
594 pub fn parse_record_with_header<V: Visitor<'p>>(
597 &mut self,
598 visitor: V,
599 header: bindings::perf_event_header,
600 ) -> ParseResult<V::Output> {
601 let (p, metadata) = self.parse_metadata_with_header_impl(header)?;
602
603 match p.data.as_slice() {
604 Some(data) => {
605 let p = Parser::new(data, p.config);
608 p.parse_record_impl(visitor, metadata)
609 }
610 None => p.parse_record_impl(visitor, metadata),
613 }
614 }
615}
616
617impl<'p> Parse<'p> for u8 {
618 fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
619 where
620 E: Endian,
621 B: ParseBuf<'p>,
622 {
623 p.parse_u8()
624 }
625}
626
627impl<'p> Parse<'p> for u16 {
628 fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
629 where
630 E: Endian,
631 B: ParseBuf<'p>,
632 {
633 p.parse_u16()
634 }
635}
636
637impl<'p> Parse<'p> for u32 {
638 fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
639 where
640 E: Endian,
641 B: ParseBuf<'p>,
642 {
643 p.parse_u32()
644 }
645}
646
647impl<'p> Parse<'p> for u64 {
648 fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
649 where
650 E: Endian,
651 B: ParseBuf<'p>,
652 {
653 p.parse_u64()
654 }
655}
656
657impl<'p, const N: usize> Parse<'p> for [u8; N] {
658 fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
659 where
660 E: Endian,
661 B: ParseBuf<'p>,
662 {
663 p.parse_array()
664 }
665}
666
667impl<'p> Parse<'p> for bindings::perf_event_header {
668 fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
669 where
670 E: Endian,
671 B: ParseBuf<'p>,
672 {
673 Ok(Self {
674 type_: p.parse()?,
675 misc: p.parse()?,
676 size: p.parse()?,
677 })
678 }
679}
680
681#[cfg(test)]
682mod tests {
683 use super::*;
684 use crate::endian::Native;
685
686 #[test]
687 fn parse_rest() {
688 let data: &[u8] = &[1, 2, 3, 4, 5];
689 let mut parser = Parser::new(data, ParseConfig::<Native>::default());
690 let rest = parser.parse_rest().unwrap();
691
692 assert_eq!(data, &*rest);
693 }
694}