use crate::Result;
#[derive(Debug, Clone, Default)]
pub struct SignalConfig {
pub handle_sigsegv: bool,
pub handle_sigtrap: bool,
pub handle_access_violation: bool,
}
pub struct SignalHandler {
config: SignalConfig,
installed: bool,
}
impl SignalHandler {
pub fn new(config: SignalConfig) -> Self {
Self {
config,
installed: false,
}
}
pub fn install(&mut self) -> Result<()> {
if self.installed {
return Ok(());
}
cfg_if::cfg_if! {
if #[cfg(unix)] {
self.install_unix_handlers()?;
} else if #[cfg(windows)] {
self.install_windows_handlers()?;
}
}
self.installed = true;
log::info!("Signal handlers installed");
Ok(())
}
pub fn uninstall(&mut self) -> Result<()> {
if !self.installed {
return Ok(());
}
self.installed = false;
log::info!("Signal handlers uninstalled");
Ok(())
}
#[cfg(unix)]
fn install_unix_handlers(&self) -> Result<()> {
use libc::{signal, SIGSEGV, SIGTRAP};
unsafe {
if self.config.handle_sigsegv {
signal(SIGSEGV, signal_handler as usize);
}
if self.config.handle_sigtrap {
signal(SIGTRAP, signal_handler as usize);
}
}
Ok(())
}
#[cfg(windows)]
fn install_windows_handlers(&self) -> Result<()> {
log::warn!("Windows signal handling not yet fully implemented");
Ok(())
}
#[cfg(not(any(unix, windows)))]
fn install_unix_handlers(&self) -> Result<()> {
Err(Error::PlatformError("Unsupported platform".into()))
}
#[cfg(not(any(unix, windows)))]
fn install_windows_handlers(&self) -> Result<()> {
Err(Error::PlatformError("Unsupported platform".into()))
}
}
#[cfg(unix)]
extern "C" fn signal_handler(sig: i32) {
match sig {
libc::SIGSEGV => {
log::error!("SIGSEGV caught - possible memory corruption or tampering");
}
libc::SIGTRAP => {
log::warn!("SIGTRAP caught - possible debugging attempt");
}
_ => {
log::warn!("Unexpected signal: {}", sig);
}
}
unsafe {
libc::signal(sig, libc::SIG_DFL);
libc::raise(sig);
}
}
#[derive(Debug, Clone)]
pub struct SignalEvent {
pub signal: i32,
pub address: Option<usize>,
pub timestamp: std::time::SystemTime,
}
impl SignalEvent {
pub fn new(signal: i32, address: Option<usize>) -> Self {
Self {
signal,
address,
timestamp: std::time::SystemTime::now(),
}
}
pub fn signal_name(&self) -> &'static str {
cfg_if::cfg_if! {
if #[cfg(unix)] {
match self.signal {
libc::SIGSEGV => "SIGSEGV",
libc::SIGTRAP => "SIGTRAP",
_ => "UNKNOWN",
}
} else {
"UNKNOWN"
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_signal_config_default() {
let config = SignalConfig::default();
assert!(!config.handle_sigsegv);
assert!(!config.handle_sigtrap);
}
#[test]
fn test_signal_handler_creation() {
let config = SignalConfig::default();
let handler = SignalHandler::new(config);
assert!(!handler.installed);
}
#[test]
fn test_signal_event() {
let event = SignalEvent::new(11, Some(0x1000));
assert_eq!(event.signal, 11);
assert_eq!(event.address, Some(0x1000));
}
}