mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 03:33:56 +00:00
Support syscall hooks
This commit is contained in:
@@ -11,6 +11,8 @@ extern "C"
|
||||
int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length);
|
||||
int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length);
|
||||
int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length);
|
||||
uint32_t icicle_add_syscall_hook(icicle_emulator*, void (*callback)(void*), void* data);
|
||||
void icicle_remove_syscall_hook(icicle_emulator*, uint32_t id);
|
||||
size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length);
|
||||
size_t icicle_write_register(icicle_emulator*, int reg, const void* data, size_t length);
|
||||
void icicle_start(icicle_emulator*);
|
||||
@@ -111,7 +113,7 @@ namespace icicle
|
||||
void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb,
|
||||
mmio_write_callback write_cb) override
|
||||
{
|
||||
return;
|
||||
this->map_memory(address, size, memory_permission::read_write);
|
||||
// throw std::runtime_error("Not implemented");
|
||||
}
|
||||
|
||||
@@ -152,8 +154,23 @@ namespace icicle
|
||||
|
||||
emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override
|
||||
{
|
||||
return nullptr;
|
||||
// throw std::runtime_error("Not implemented");
|
||||
if (static_cast<x64_hookable_instructions>(instruction_type) != x64_hookable_instructions::syscall)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto callback_store = std::make_unique<std::function<void()>>([c = std::move(callback)] {
|
||||
(void)c(); //
|
||||
});
|
||||
|
||||
const auto invoker = +[](void* cb) {
|
||||
(*static_cast<std::function<void()>*>(cb))(); //
|
||||
};
|
||||
|
||||
const auto id = icicle_add_syscall_hook(this->emu_, invoker, callback_store.get());
|
||||
this->syscall_hooks_[id] = std::move(callback_store);
|
||||
|
||||
return reinterpret_cast<emulator_hook*>(static_cast<size_t>(id));
|
||||
}
|
||||
|
||||
emulator_hook* hook_basic_block(basic_block_hook_callback callback) override
|
||||
@@ -195,7 +212,15 @@ namespace icicle
|
||||
|
||||
void delete_hook(emulator_hook* hook) override
|
||||
{
|
||||
// throw std::runtime_error("Not implemented");
|
||||
const auto id = static_cast<uint32_t>(reinterpret_cast<size_t>(hook));
|
||||
const auto entry = this->syscall_hooks_.find(id);
|
||||
if (entry == this->syscall_hooks_.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
icicle_remove_syscall_hook(this->emu_, id);
|
||||
this->syscall_hooks_.erase(entry);
|
||||
}
|
||||
|
||||
void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override
|
||||
@@ -225,6 +250,8 @@ namespace icicle
|
||||
}
|
||||
|
||||
private:
|
||||
using syscall_hook_storage = std::unique_ptr<std::function<void()>>;
|
||||
std::unordered_map<uint32_t, syscall_hook_storage> syscall_hooks_{};
|
||||
icicle_emulator* emu_{};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use icicle_cpu::ValueSource;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn create_x64_vm() -> icicle_vm::Vm {
|
||||
let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none");
|
||||
@@ -31,6 +32,9 @@ fn map_permissions(foreign_permissions: u8) -> u8 {
|
||||
pub struct IcicleEmulator {
|
||||
vm: icicle_vm::Vm,
|
||||
reg: X64RegisterNodes,
|
||||
|
||||
syscall_hook_id: u32,
|
||||
syscall_hooks: HashMap<u32, Box<dyn Fn()>>,
|
||||
}
|
||||
|
||||
impl IcicleEmulator {
|
||||
@@ -39,6 +43,8 @@ impl IcicleEmulator {
|
||||
Self {
|
||||
reg: X64RegisterNodes::new(&vm_i.cpu.arch),
|
||||
vm: vm_i,
|
||||
syscall_hook_id: 0,
|
||||
syscall_hooks: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +53,33 @@ impl IcicleEmulator {
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
self.vm.run();
|
||||
loop {
|
||||
let reason = self.vm.run();
|
||||
|
||||
let invoke_syscall = match reason {
|
||||
icicle_vm::VmExit::UnhandledException((code, _)) => code == icicle_cpu::ExceptionCode::Syscall,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !invoke_syscall {
|
||||
break;
|
||||
}
|
||||
|
||||
for (_key, func) in &self.syscall_hooks {
|
||||
func();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop(&mut self) {
|
||||
//self.vm.stop();
|
||||
pub fn add_syscall_hook(&mut self, callback: Box<dyn Fn()>) -> u32 {
|
||||
self.syscall_hook_id += 1;
|
||||
let id = self.syscall_hook_id;
|
||||
self.syscall_hooks.insert(id, callback);
|
||||
return id;
|
||||
}
|
||||
|
||||
pub fn remove_syscall_hook(&mut self, id: u32) {
|
||||
self.syscall_hooks.remove(&id);
|
||||
}
|
||||
|
||||
pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool {
|
||||
|
||||
@@ -77,6 +77,24 @@ pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, siz
|
||||
}
|
||||
}
|
||||
|
||||
type CFunctionPointer = extern "C" fn(*mut c_void);
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: CFunctionPointer, data: *mut c_void) {
|
||||
unsafe {
|
||||
let emulator = &mut *(ptr as *mut IcicleEmulator);
|
||||
emulator.add_syscall_hook(Box::new(move || callback(data)));
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_remove_syscall_hook(ptr: *mut c_void, id: u32) {
|
||||
unsafe {
|
||||
let emulator = &mut *(ptr as *mut IcicleEmulator);
|
||||
emulator.remove_syscall_hook(id);
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_read_register(
|
||||
ptr: *mut c_void,
|
||||
|
||||
Reference in New Issue
Block a user