1#[cfg(all(feature = "stealth-mode", not(test)))]
4use core::hint;
5
6use crate::{exception::backend::Backend, ffi::binding};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum MonitorBackend {
11 IntelUmonitor,
13
14 AmdMonitorx,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum MonitorError {
21 Fault,
23
24 Unsupported,
26}
27
28#[inline]
32pub fn backend() -> Option<MonitorBackend> {
33 let target_backend = unsafe { binding::catalejo_monitor_select() };
35
36 match target_backend {
37 binding::CATALEJO_MONITOR_BACKEND_INTEL_UMONITOR => Some(MonitorBackend::IntelUmonitor),
38 binding::CATALEJO_MONITOR_BACKEND_AMD_MONITORX => Some(MonitorBackend::AmdMonitorx),
39 binding::CATALEJO_MONITOR_BACKEND_UNSUPPORTED => None,
40 #[cfg(not(feature = "stealth-mode"))]
41 _ => unreachable!(),
42
43 #[cfg(all(feature = "stealth-mode", test))]
44 _ => std::process::abort(),
45
46 #[cfg(all(feature = "stealth-mode", not(test)))]
47 _ => unsafe { hint::unreachable_unchecked() },
49 }
50}
51
52#[inline]
59pub unsafe fn arm(
60 fault_backend: &Backend,
61 target_address: *const u8,
62) -> Result<MonitorBackend, MonitorError> {
63 if fault_backend.validate().is_err() {
64 return Err(MonitorError::Fault);
65 }
66
67 let target_outcome = unsafe { binding::catalejo_monitor_arm(target_address) };
70
71 match target_outcome {
72 binding::CATALEJO_MONITOR_ARM_INTEL_UMONITOR => Ok(MonitorBackend::IntelUmonitor),
73 binding::CATALEJO_MONITOR_ARM_AMD_MONITORX => Ok(MonitorBackend::AmdMonitorx),
74 binding::CATALEJO_MONITOR_ARM_FAULT => Err(MonitorError::Fault),
75 binding::CATALEJO_MONITOR_ARM_UNSUPPORTED => Err(MonitorError::Unsupported),
76 #[cfg(not(feature = "stealth-mode"))]
77 _ => unreachable!(),
78
79 #[cfg(all(feature = "stealth-mode", test))]
80 _ => std::process::abort(),
81
82 #[cfg(all(feature = "stealth-mode", not(test)))]
83 _ => unsafe { hint::unreachable_unchecked() },
85 }
86}
87
88#[inline]
95pub unsafe fn wait(fault_backend: &Backend, backend: MonitorBackend) -> Result<(), MonitorError> {
96 if fault_backend.validate().is_err() {
97 return Err(MonitorError::Fault);
98 }
99
100 let backend = match backend {
101 MonitorBackend::IntelUmonitor => binding::CATALEJO_MONITOR_BACKEND_INTEL_UMONITOR,
102 MonitorBackend::AmdMonitorx => binding::CATALEJO_MONITOR_BACKEND_AMD_MONITORX,
103 };
104
105 let outcome = unsafe { binding::catalejo_monitor_wait(backend) };
108
109 match outcome {
110 binding::CATALEJO_OUTCOME_SUCCESS => Ok(()),
111 binding::CATALEJO_OUTCOME_ERROR => Err(MonitorError::Fault),
112 binding::CATALEJO_OUTCOME_INVALID_VALUE => Err(MonitorError::Unsupported),
113 #[cfg(not(feature = "stealth-mode"))]
114 _ => unreachable!(),
115
116 #[cfg(all(feature = "stealth-mode", test))]
117 _ => std::process::abort(),
118
119 #[cfg(all(feature = "stealth-mode", not(test)))]
120 _ => unsafe { hint::unreachable_unchecked() },
122 }
123}