mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-20 04:03:57 +00:00
Support reading and writing memory
This commit is contained in:
@@ -6,13 +6,27 @@ using icicle_emulator = struct icicle_emulator_;
|
||||
extern "C"
|
||||
{
|
||||
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);
|
||||
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);
|
||||
void icicle_destroy_emulator(icicle_emulator*);
|
||||
}
|
||||
|
||||
namespace icicle
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void ice(const bool result, const std::string_view error)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
throw std::runtime_error(std::string(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class icicle_x64_emulator : public x64_emulator
|
||||
{
|
||||
public:
|
||||
@@ -66,42 +80,36 @@ namespace icicle
|
||||
void map_memory(const uint64_t address, const size_t size, memory_permission permissions) override
|
||||
{
|
||||
const auto res = icicle_map_memory(this->emu_, address, size, static_cast<uint8_t>(permissions));
|
||||
if (!res)
|
||||
{
|
||||
throw std::runtime_error("Failed to map memory");
|
||||
}
|
||||
ice(res, "Failed to map memory");
|
||||
}
|
||||
|
||||
void unmap_memory(const uint64_t address, const size_t size) override
|
||||
{
|
||||
const auto res = icicle_unmap_memory(this->emu_, address, size);
|
||||
if (!res)
|
||||
{
|
||||
throw std::runtime_error("Failed to map memory");
|
||||
}
|
||||
ice(res, "Failed to unmap memory");
|
||||
}
|
||||
|
||||
bool try_read_memory(const uint64_t address, void* data, const size_t size) const override
|
||||
{
|
||||
throw std::runtime_error("Not implemented");
|
||||
return icicle_read_memory(this->emu_, address, data, size);
|
||||
}
|
||||
|
||||
void read_memory(const uint64_t address, void* data, const size_t size) const override
|
||||
{
|
||||
if (!this->try_read_memory(address, data, size))
|
||||
{
|
||||
throw std::runtime_error("Failed to read memory");
|
||||
}
|
||||
const auto res = this->try_read_memory(address, data, size);
|
||||
ice(res, "Failed to read memory");
|
||||
}
|
||||
|
||||
void write_memory(const uint64_t address, const void* data, const size_t size) override
|
||||
{
|
||||
throw std::runtime_error("Not implemented");
|
||||
const auto res = icicle_write_memory(this->emu_, address, data, size);
|
||||
ice(res, "Failed to write memory");
|
||||
}
|
||||
|
||||
void apply_memory_protection(const uint64_t address, const size_t size, memory_permission permissions) override
|
||||
{
|
||||
throw std::runtime_error("Not implemented");
|
||||
const auto res = icicle_protect_memory(this->emu_, address, size, static_cast<uint8_t>(permissions));
|
||||
ice(res, "Failed to apply permissions");
|
||||
}
|
||||
|
||||
emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override
|
||||
|
||||
2
src/icicle/.gitignore
vendored
Normal file
2
src/icicle/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
/Ghidra
|
||||
@@ -37,6 +37,10 @@ impl IcicleEmulator {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mem(&mut self) -> &mut icicle_vm::cpu::Mmu {
|
||||
return &mut self.vm.cpu.mem;
|
||||
}
|
||||
|
||||
pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool {
|
||||
const MAPPING_PERMISSIONS: u8 = icicle_vm::cpu::mem::perm::MAP
|
||||
| icicle_vm::cpu::mem::perm::INIT
|
||||
@@ -55,11 +59,27 @@ impl IcicleEmulator {
|
||||
align: 0x1000,
|
||||
};
|
||||
|
||||
let res = self.vm.cpu.mem.alloc_memory(layout, mapping);
|
||||
let res = self.get_mem().alloc_memory(layout, mapping);
|
||||
return res.is_ok();
|
||||
}
|
||||
|
||||
pub fn unmap_memory(&mut self, address: u64, length: u64) -> bool {
|
||||
return self.vm.cpu.mem.unmap_memory_len(address, length);
|
||||
return self.get_mem().unmap_memory_len(address, length);
|
||||
}
|
||||
|
||||
pub fn protect_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool {
|
||||
let native_permissions = map_permissions(permissions);
|
||||
let res = self.get_mem().update_perm(address, length, native_permissions);
|
||||
return res.is_ok();
|
||||
}
|
||||
|
||||
pub fn write_memory(&mut self, address: u64, data: &[u8]) -> bool {
|
||||
let res = self.get_mem().write_bytes(address, data, icicle_vm::cpu::mem::perm::WRITE);
|
||||
return res.is_ok();
|
||||
}
|
||||
|
||||
pub fn read_memory(&mut self, address: u64, data: &mut [u8]) -> bool {
|
||||
let res = self.get_mem().read_bytes(address, data, icicle_vm::cpu::mem::perm::READ);
|
||||
return res.is_ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@ mod icicle;
|
||||
use icicle::IcicleEmulator;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
fn to_cbool(value: bool) -> i32 {
|
||||
if value {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_create_emulator() -> *mut c_void {
|
||||
let emulator = Box::new(IcicleEmulator::new());
|
||||
@@ -10,21 +18,11 @@ pub fn icicle_create_emulator() -> *mut c_void {
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_map_memory(
|
||||
ptr: *mut c_void,
|
||||
address: u64,
|
||||
length: u64,
|
||||
permissions: u8,
|
||||
) -> i32 {
|
||||
pub fn icicle_map_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 {
|
||||
unsafe {
|
||||
let emulator = &mut *(ptr as *mut IcicleEmulator);
|
||||
let res = emulator.map_memory(address, length, permissions);
|
||||
|
||||
if res {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return to_cbool(res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,12 +31,38 @@ pub fn icicle_unmap_memory(ptr: *mut c_void, address: u64, length: u64) -> i32 {
|
||||
unsafe {
|
||||
let emulator = &mut *(ptr as *mut IcicleEmulator);
|
||||
let res = emulator.unmap_memory(address, length);
|
||||
return to_cbool(res);
|
||||
}
|
||||
}
|
||||
|
||||
if res {
|
||||
return 1;
|
||||
}
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_protect_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 {
|
||||
unsafe {
|
||||
let emulator = &mut *(ptr as *mut IcicleEmulator);
|
||||
let res = emulator.protect_memory(address, length, permissions);
|
||||
return to_cbool(res);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_write_memory(ptr: *mut c_void, address: u64, data: *const c_void, size: usize) -> i32 {
|
||||
unsafe {
|
||||
let emulator = &mut *(ptr as *mut IcicleEmulator);
|
||||
let u8_ptr = data as *const u8;
|
||||
let u8_slice = std::slice::from_raw_parts(u8_ptr, size);
|
||||
let res = emulator.write_memory(address, u8_slice);
|
||||
return to_cbool(res);
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, size: usize) -> i32 {
|
||||
unsafe {
|
||||
let emulator = &mut *(ptr as *mut IcicleEmulator);
|
||||
let u8_ptr = data as *mut u8;
|
||||
let u8_slice = std::slice::from_raw_parts_mut(u8_ptr, size);
|
||||
let res = emulator.read_memory(address, u8_slice);
|
||||
return to_cbool(res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user