Support saving and restoring registers

This commit is contained in:
momo5502
2025-04-01 18:23:24 +02:00
parent 7222c0fc1d
commit fd018c46b4
3 changed files with 56 additions and 7 deletions

View File

@@ -10,6 +10,8 @@ extern "C"
using icicle_mmio_read_func = void(void* user, uint64_t address, size_t length, void* data);
using icicle_mmio_write_func = void(void* user, uint64_t address, size_t length, const void* data);
using data_accessor_func = void(void* user, const void* data, size_t length);
icicle_emulator* icicle_create_emulator();
int32_t icicle_protect_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions);
int32_t icicle_map_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions);
@@ -18,6 +20,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);
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*, 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);
@@ -295,14 +299,21 @@ namespace icicle
std::vector<std::byte> save_registers() override
{
// throw std::runtime_error("Not implemented");
return {};
std::vector<std::byte> data{};
auto* accessor = +[](void* user, const void* data, const size_t length) {
auto& vec = *static_cast<std::vector<std::byte>*>(user);
vec.resize(length);
memcpy(vec.data(), data, length);
};
icicle_save_registers(this->emu_, accessor, &data);
return data;
}
void restore_registers(const std::vector<std::byte>& register_data) override
{
(void)register_data;
// throw std::runtime_error("Not implemented");
icicle_restore_registers(this->emu_, register_data.data(), register_data.size());
}
bool has_violation() const override

View File

@@ -251,6 +251,26 @@ impl IcicleEmulator {
return res.is_ok();
}
pub fn save_registers(&self) -> Vec<u8> {
const REG_SIZE: usize = std::mem::size_of::<icicle_cpu::Regs>();
unsafe {
let data: [u8; REG_SIZE] = self.vm.cpu.regs.read_at(0);
return data.to_vec();
}
}
pub fn restore_registers(&mut self, data: &[u8]) {
const REG_SIZE: usize = std::mem::size_of::<icicle_cpu::Regs>();
let mut buffer: [u8; REG_SIZE] = [0; REG_SIZE];
let size = std::cmp::min(REG_SIZE, data.len());
buffer.copy_from_slice(&data[..size]);
unsafe {
self.vm.cpu.regs.write_at(0, buffer);
};
}
pub fn read_register(&mut self, reg: X64Register, buffer: &mut [u8]) -> usize {
let reg_node = self.reg.get_node(reg);

View File

@@ -25,6 +25,8 @@ pub fn icicle_start(ptr: *mut c_void) {
}
}
type RawFunction = extern "C" fn(*mut c_void);
type DataFunction = extern "C" fn(*mut c_void, *const c_void, usize);
type MmioReadFunction = extern "C" fn(*mut c_void, u64, usize, *mut c_void);
type MmioWriteFunction = extern "C" fn(*mut c_void, u64, usize, *const c_void);
@@ -98,6 +100,24 @@ pub fn icicle_write_memory(
}
}
#[unsafe(no_mangle)]
pub fn icicle_save_registers(ptr: *mut c_void, accessor: DataFunction, accessor_data: *mut c_void) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let registers = emulator.save_registers();
accessor(accessor_data, registers.as_ptr() as *const c_void, registers.len());
}
}
#[unsafe(no_mangle)]
pub fn icicle_restore_registers(ptr: *mut c_void, data: *const c_void, size: usize) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts(data as *const u8, size);
emulator.restore_registers(u8_slice);
}
}
#[unsafe(no_mangle)]
pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, size: usize) -> i32 {
unsafe {
@@ -108,10 +128,8 @@ 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) {
pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: RawFunction, data: *mut c_void) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
emulator.add_syscall_hook(Box::new(move || callback(data)));