libipt/event/
exec_mode.rs1#![allow(clippy::unnecessary_cast)]
3
4use crate::error::{PtError, PtErrorCode};
5use crate::event::Event;
6use derive_more::Deref;
7use libipt_sys::{
8 pt_event_type_ptev_exec_mode, pt_exec_mode_ptem_16bit, pt_exec_mode_ptem_32bit,
9 pt_exec_mode_ptem_64bit, pt_exec_mode_ptem_unknown,
10};
11use num_enum::TryFromPrimitive;
12use std::convert::TryFrom;
13use std::fmt::{Debug, Formatter};
14
15#[derive(Clone, Copy, TryFromPrimitive, Debug, PartialEq)]
16#[repr(u32)]
17pub enum ExecModeType {
18 Bit16 = pt_exec_mode_ptem_16bit as u32,
19 Bit32 = pt_exec_mode_ptem_32bit as u32,
20 Bit64 = pt_exec_mode_ptem_64bit as u32,
21 Unknown = pt_exec_mode_ptem_unknown as u32,
22}
23
24#[derive(Clone, Copy, Deref)]
26#[repr(transparent)]
27pub struct ExecMode {
28 pub(super) event: Event,
29}
30impl ExecMode {
31 #[must_use]
33 pub const fn ip(&self) -> u64 {
34 unsafe { self.event.0.variant.exec_mode.ip }
35 }
36
37 #[must_use]
39 pub fn mode(&self) -> ExecModeType {
40 ExecModeType::try_from(unsafe { self.event.0.variant.exec_mode.mode } as u32).unwrap()
41 }
42}
43
44impl Debug for ExecMode {
45 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46 write!(f, "ExecMode {{")?;
47 self.fmt_common_fields(f)?;
48 write!(f, "ip: 0x{:x?}, mode: {:?} }}", self.ip(), self.mode())
49 }
50}
51
52impl TryFrom<Event> for ExecMode {
53 type Error = PtError;
54
55 fn try_from(event: Event) -> Result<Self, Self::Error> {
56 if event.0.type_ == pt_event_type_ptev_exec_mode {
57 Ok(Self { event })
58 } else {
59 Err(PtErrorCode::Invalid.into())
60 }
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use super::super::EventType;
67 use super::*;
68 use crate::event::Event;
69 use libipt_sys::{pt_event, pt_event_type_ptev_exec_mode};
70 use std::mem;
71
72 #[test]
73 fn test_exec_mode_payload() {
74 let mut evt: pt_event = unsafe { mem::zeroed() };
75 evt.type_ = pt_event_type_ptev_exec_mode;
76
77 evt.variant.exec_mode.ip = 11;
78 evt.variant.exec_mode.mode = pt_exec_mode_ptem_32bit;
79
80 let payload: EventType = Event(evt).into();
81 match payload {
82 EventType::ExecMode(e) => {
83 assert_eq!(e.ip(), 11);
84 assert_eq!(e.mode(), ExecModeType::Bit32);
85 }
86 _ => unreachable!("oof"),
87 }
88 }
89}