#[cfg(all(feature = "stealth-mode", not(test)))]
use core::hint;
use crate::{exception::backend::Backend, ffi::binding};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonitorBackend {
IntelUmonitor,
AmdMonitorx,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonitorError {
Fault,
Unsupported,
}
#[inline]
pub fn backend() -> Option<MonitorBackend> {
let target_backend = unsafe { binding::catalejo_monitor_select() };
match target_backend {
binding::CATALEJO_MONITOR_BACKEND_INTEL_UMONITOR => Some(MonitorBackend::IntelUmonitor),
binding::CATALEJO_MONITOR_BACKEND_AMD_MONITORX => Some(MonitorBackend::AmdMonitorx),
binding::CATALEJO_MONITOR_BACKEND_UNSUPPORTED => None,
#[cfg(not(feature = "stealth-mode"))]
_ => unreachable!(),
#[cfg(all(feature = "stealth-mode", test))]
_ => std::process::abort(),
#[cfg(all(feature = "stealth-mode", not(test)))]
_ => unsafe { hint::unreachable_unchecked() },
}
}
#[inline]
pub unsafe fn arm(
fault_backend: &Backend,
target_address: *const u8,
) -> Result<MonitorBackend, MonitorError> {
if fault_backend.validate().is_err() {
return Err(MonitorError::Fault);
}
let target_outcome = unsafe { binding::catalejo_monitor_arm(target_address) };
match target_outcome {
binding::CATALEJO_MONITOR_ARM_INTEL_UMONITOR => Ok(MonitorBackend::IntelUmonitor),
binding::CATALEJO_MONITOR_ARM_AMD_MONITORX => Ok(MonitorBackend::AmdMonitorx),
binding::CATALEJO_MONITOR_ARM_FAULT => Err(MonitorError::Fault),
binding::CATALEJO_MONITOR_ARM_UNSUPPORTED => Err(MonitorError::Unsupported),
#[cfg(not(feature = "stealth-mode"))]
_ => unreachable!(),
#[cfg(all(feature = "stealth-mode", test))]
_ => std::process::abort(),
#[cfg(all(feature = "stealth-mode", not(test)))]
_ => unsafe { hint::unreachable_unchecked() },
}
}
#[inline]
pub unsafe fn wait(fault_backend: &Backend, backend: MonitorBackend) -> Result<(), MonitorError> {
if fault_backend.validate().is_err() {
return Err(MonitorError::Fault);
}
let backend = match backend {
MonitorBackend::IntelUmonitor => binding::CATALEJO_MONITOR_BACKEND_INTEL_UMONITOR,
MonitorBackend::AmdMonitorx => binding::CATALEJO_MONITOR_BACKEND_AMD_MONITORX,
};
let outcome = unsafe { binding::catalejo_monitor_wait(backend) };
match outcome {
binding::CATALEJO_OUTCOME_SUCCESS => Ok(()),
binding::CATALEJO_OUTCOME_ERROR => Err(MonitorError::Fault),
binding::CATALEJO_OUTCOME_INVALID_VALUE => Err(MonitorError::Unsupported),
#[cfg(not(feature = "stealth-mode"))]
_ => unreachable!(),
#[cfg(all(feature = "stealth-mode", test))]
_ => std::process::abort(),
#[cfg(all(feature = "stealth-mode", not(test)))]
_ => unsafe { hint::unreachable_unchecked() },
}
}