use crate::types::{Arch, CpuFamily};
const SIGILL: u32 = 4;
const SIGBUS: u32 = 10;
const SIGSEGV: u32 = 11;
pub struct InstructionInfo {
pub addr: u64,
pub arch: Arch,
pub crashing_frame: bool,
pub signal: Option<u32>,
pub ip_reg: Option<u64>,
}
impl InstructionInfo {
pub fn aligned_address(&self) -> u64 {
if let Some(alignment) = self.arch.instruction_alignment() {
self.addr - (self.addr % alignment)
} else {
self.addr
}
}
pub fn previous_address(&self) -> u64 {
let instruction_size = self.arch.instruction_alignment().unwrap_or(1);
let pc_offset = match self.arch.cpu_family() {
CpuFamily::Mips32 | CpuFamily::Mips64 => 2 * instruction_size,
_ => instruction_size,
};
self.aligned_address() - pc_offset
}
pub fn is_crash_signal(&self) -> bool {
match self.signal {
Some(SIGILL) | Some(SIGBUS) | Some(SIGSEGV) => true,
_ => false,
}
}
pub fn should_adjust_caller(&self) -> bool {
if !self.crashing_frame {
return true;
}
if let Some(ip) = self.ip_reg {
if ip != self.addr && self.is_crash_signal() {
return true;
}
}
false
}
pub fn caller_address(&self) -> u64 {
if self.should_adjust_caller() {
self.previous_address()
} else {
self.aligned_address()
}
}
}