mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-18 19:23:56 +00:00
Support interrupt hooks
This commit is contained in:
@@ -12,6 +12,7 @@ extern "C"
|
||||
|
||||
using raw_func = void(void*);
|
||||
using ptr_func = void(void*, uint64_t);
|
||||
using interrupt_func = void(void*, int32_t);
|
||||
using violation_func = int32_t(void*, uint64_t address, uint8_t operation, int32_t unmapped);
|
||||
using data_accessor_func = void(void* user, const void* data, size_t length);
|
||||
using memory_access_func = icicle_mmio_write_func;
|
||||
@@ -27,6 +28,7 @@ extern "C"
|
||||
int32_t icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data);
|
||||
int32_t icicle_restore_registers(icicle_emulator*, const void* data, size_t length);
|
||||
uint32_t icicle_add_syscall_hook(icicle_emulator*, raw_func* callback, void* data);
|
||||
uint32_t icicle_add_interrupt_hook(icicle_emulator*, interrupt_func* callback, void* data);
|
||||
uint32_t icicle_add_execution_hook(icicle_emulator*, uint64_t address, ptr_func* callback, void* data);
|
||||
uint32_t icicle_add_generic_execution_hook(icicle_emulator*, ptr_func* callback, void* data);
|
||||
uint32_t icicle_add_violation_hook(icicle_emulator*, violation_func* callback, void* data);
|
||||
@@ -260,10 +262,17 @@ namespace icicle
|
||||
|
||||
emulator_hook* hook_interrupt(interrupt_hook_callback callback) override
|
||||
{
|
||||
// TODO
|
||||
(void)callback;
|
||||
return nullptr;
|
||||
// throw std::runtime_error("Not implemented");
|
||||
auto obj = make_function_object(std::move(callback));
|
||||
auto* ptr = obj.get();
|
||||
auto* wrapper = +[](void* user, const int32_t code) {
|
||||
const auto& func = *static_cast<decltype(ptr)>(user);
|
||||
func(code);
|
||||
};
|
||||
|
||||
const auto id = icicle_add_interrupt_hook(this->emu_, wrapper, ptr);
|
||||
this->hooks_[id] = std::move(obj);
|
||||
|
||||
return wrap_hook(id);
|
||||
}
|
||||
|
||||
emulator_hook* hook_memory_violation(memory_violation_hook_callback callback) override
|
||||
@@ -292,7 +301,7 @@ namespace icicle
|
||||
auto object = make_function_object(std::move(callback));
|
||||
auto* ptr = object.get();
|
||||
auto* wrapper = +[](void* user, const uint64_t addr) {
|
||||
auto& func = *static_cast<decltype(ptr)>(user);
|
||||
const auto& func = *static_cast<decltype(ptr)>(user);
|
||||
(func)(addr);
|
||||
};
|
||||
|
||||
@@ -307,7 +316,7 @@ namespace icicle
|
||||
auto object = make_function_object(std::move(callback));
|
||||
auto* ptr = object.get();
|
||||
auto* wrapper = +[](void* user, const uint64_t addr) {
|
||||
auto& func = *static_cast<decltype(ptr)>(user);
|
||||
const auto& func = *static_cast<decltype(ptr)>(user);
|
||||
(func)(addr);
|
||||
};
|
||||
|
||||
|
||||
@@ -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);()},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user