Support interrupt hooks

This commit is contained in:
Maurice Heumann
2025-04-07 07:24:46 +02:00
parent 1ed997445d
commit baad36ccf2
3 changed files with 45 additions and 7 deletions

View File

@@ -49,6 +49,7 @@ enum HookType {
ExecuteGeneric,
ExecuteSpecific,
Violation,
Interrupt,
Unknown,
}
@@ -216,6 +217,7 @@ pub struct IcicleEmulator {
vm: icicle_vm::Vm,
reg: registers::X64RegisterNodes,
syscall_hooks: HookContainer<dyn Fn()>,
interrupt_hooks: HookContainer<dyn Fn(i32)>,
violation_hooks: HookContainer<dyn Fn(u64, u8, bool) -> bool>,
execution_hooks: Rc<RefCell<ExecutionHooks>>,
stop: Rc<RefCell<bool>>,
@@ -287,6 +289,7 @@ impl IcicleEmulator {
reg: registers::X64RegisterNodes::new(&virtual_machine.cpu.arch),
vm: virtual_machine,
syscall_hooks: HookContainer::new(),
interrupt_hooks: HookContainer::new(),
violation_hooks: HookContainer::new(),
execution_hooks: exec_hooks,
}
@@ -326,6 +329,14 @@ impl IcicleEmulator {
}
}
fn handle_interrupt(&self, code: i32) -> bool {
for (_key, func) in self.interrupt_hooks.get_hooks() {
func(code);
}
return true;
}
fn handle_exception(&mut self, code: ExceptionCode, value: u64) -> bool {
let continue_execution = match code {
ExceptionCode::Syscall => self.handle_syscall(),
@@ -333,7 +344,8 @@ impl IcicleEmulator {
ExceptionCode::WritePerm => self.handle_violation(value, FOREIGN_WRITE, false),
ExceptionCode::ReadUnmapped => self.handle_violation(value, FOREIGN_READ, true),
ExceptionCode::WriteUnmapped => self.handle_violation(value, FOREIGN_WRITE, true),
ExceptionCode::ExecViolation => self.handle_violation(value, FOREIGN_EXEC, true),
ExceptionCode::InvalidInstruction => self.handle_interrupt(6),
ExceptionCode::DivisionException => self.handle_interrupt(0),
_ => false,
};
@@ -392,6 +404,11 @@ impl IcicleEmulator {
return qualify_hook_id(hook_id, HookType::Syscall);
}
pub fn add_interrupt_hook(&mut self, callback: Box<dyn Fn(i32)>) -> u32 {
let hook_id = self.interrupt_hooks.add_hook(callback);
return qualify_hook_id(hook_id, HookType::Interrupt);
}
pub fn add_read_hook(
&mut self,
start: u64,
@@ -426,6 +443,7 @@ impl IcicleEmulator {
match hook_type {
HookType::Syscall => self.syscall_hooks.remove_hook(hook_id),
HookType::Violation => self.violation_hooks.remove_hook(hook_id),
HookType::Interrupt => self.interrupt_hooks.remove_hook(hook_id),
HookType::ExecuteGeneric => self.execution_hooks.borrow_mut().remove_generic_hook(hook_id),
HookType::ExecuteSpecific => self.execution_hooks.borrow_mut().remove_specific_hook(hook_id),
HookType::Read => {self.get_mem().remove_read_after_hook(hook_id);()},

View File

@@ -41,6 +41,7 @@ type DataFunction = extern "C" fn(*mut c_void, *const c_void, usize);
type MmioReadFunction = extern "C" fn(*mut c_void, u64, *mut c_void, usize);
type MmioWriteFunction = extern "C" fn(*mut c_void, u64, *const c_void, usize);
type ViolationFunction = extern "C" fn(*mut c_void, u64, u8, i32) -> i32;
type InterruptFunction = extern "C" fn(*mut c_void, i32);
type MemoryAccessFunction = MmioWriteFunction;
#[unsafe(no_mangle)]
@@ -165,6 +166,16 @@ pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, siz
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_interrupt_hook(ptr: *mut c_void, callback: InterruptFunction, data: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_interrupt_hook(Box::new(
move |code: i32| callback(data, code),
));
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_violation_hook(ptr: *mut c_void, callback: ViolationFunction, data: *mut c_void) -> u32 {
unsafe {