#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub fn install() {
use std::sync::Once;
static ONCE: Once = Once::new();
if std::env::var_os("LOGOS_SEGV_TRAP").is_none() {
return;
}
ONCE.call_once(|| unsafe {
let mut sa: libc::sigaction = std::mem::zeroed();
sa.sa_sigaction = handler as usize;
sa.sa_flags = libc::SA_SIGINFO;
libc::sigemptyset(&mut sa.sa_mask);
libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
libc::sigaction(libc::SIGBUS, &sa, std::ptr::null_mut());
});
}
#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
pub fn install() {}
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
extern "C" fn handler(
sig: libc::c_int,
info: *mut libc::siginfo_t,
ucontext: *mut libc::c_void,
) {
unsafe {
let addr_ptr = (info as *const u8).add(16) as *const usize;
let fault_addr = addr_ptr.read_unaligned();
let uc = ucontext as *const u8;
let greg = |i: usize| (uc.add(40 + i * 8) as *const i64).read_unaligned();
let (rdi, rsi, rdx, rax, rcx, rip) =
(greg(8), greg(9), greg(12), greg(13), greg(14), greg(16));
let r8 = greg(0);
let r9 = greg(1);
let rbx = greg(11);
let mut code = [0u8; 16];
for (k, b) in code.iter_mut().enumerate() {
*b = (rip as *const u8).add(k).read();
}
let msg = format!(
"\n*** LOGOS_SEGV_TRAP: sig {sig} fault=0x{fault_addr:016x} rip=0x{rip:016x}\n rdi(base)=0x{rdi:016x} rsi(sp)=0x{rsi:016x} rax=0x{rax:016x} rdx=0x{rdx:016x} rcx=0x{rcx:016x}\n r8=0x{r8:016x} r9=0x{r9:016x} rbx=0x{rbx:016x}\n code@rip={code:02x?} ***\n"
);
libc::write(2, msg.as_ptr() as *const libc::c_void, msg.len());
let mut sa: libc::sigaction = std::mem::zeroed();
sa.sa_sigaction = libc::SIG_DFL;
libc::sigemptyset(&mut sa.sa_mask);
libc::sigaction(sig, &sa, std::ptr::null_mut());
libc::raise(sig);
}
}