From 60bcdfce0c74d3d9edd047326b5e6922250fd436 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 10:52:20 -0400 Subject: [PATCH 01/35] modify uc_priv.h to use 64 bit hwaddr type for length for uc_write_mem_t and uc_read_mem_t --- include/uc_priv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 484fc53e3f..ac29f34efd 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -75,10 +75,10 @@ typedef struct { typedef void (*reg_reset_t)(struct uc_struct *uc); typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, - const uint8_t *buf, int len); + const uint8_t *buf, hwaddr len); typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, - int len); + hwaddr len); typedef MemoryRegion *(*uc_mem_cow_t)(struct uc_struct *uc, MemoryRegion *current, hwaddr begin, From 947b719362c725408427b8cc513ba764a065a311 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 10:55:47 -0400 Subject: [PATCH 02/35] propogate 64 bit address support to memory function inside unicorn.h --- include/unicorn/unicorn.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 5521262e8e..5a099d5717 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -916,7 +916,7 @@ uc_err uc_reg_read_batch2(uc_engine *uc, int const *regs, void *const *vals, */ UNICORN_EXPORT uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, - size_t size); + uint64_t size); /* Read a range of bytes in memory. @@ -932,7 +932,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); +uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, uint64_t size); /* Emulate machine code in a specific duration of time. @@ -1059,7 +1059,7 @@ typedef enum uc_context_content { for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); +uc_err uc_mem_map(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms); /* Map existing host memory in for emulation. @@ -1084,7 +1084,7 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, +uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms, void *ptr); /* @@ -1107,7 +1107,7 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, for detailed error). */ UNICORN_EXPORT -uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, +uc_err uc_mmio_map(uc_engine *uc, uint64_t address, uint64_t size, uc_cb_mmio_read_t read_cb, void *user_data_read, uc_cb_mmio_write_t write_cb, void *user_data_write); @@ -1127,7 +1127,7 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); +uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, uint64_t size); /* Set memory permissions for emulation memory. @@ -1148,7 +1148,7 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, +uc_err uc_mem_protect(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms); /* From 7a6c9ac58e4adf2df03314bbdbde6271d5a9a757 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 10:57:29 -0400 Subject: [PATCH 03/35] modify physical memory functions to ensure 64 bit support for size parameters --- qemu/unicorn_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 8ce54aaa9e..ab91c62ae9 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -17,13 +17,13 @@ bool unicorn_fill_tlb(CPUState *cs, vaddr address, int size, // return true on success, false on failure static inline bool cpu_physical_mem_read(AddressSpace *as, hwaddr addr, - uint8_t *buf, int len) + uint8_t *buf, hwaddr len) { return cpu_physical_memory_rw(as, addr, (void *)buf, len, 0); } static inline bool cpu_physical_mem_write(AddressSpace *as, hwaddr addr, - const uint8_t *buf, int len) + const uint8_t *buf, hwaddr len) { return cpu_physical_memory_rw(as, addr, (void *)buf, len, 1); } From d238d0122d3948c1ca4e732946786bc265aca5a6 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 11:09:35 -0400 Subject: [PATCH 04/35] apply uint64_t size handling inside the memory handling main functions --- uc.c | 66 +++++++++++++++++++++++++++--------------------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/uc.c b/uc.c index 57cb6e8c76..29b0daff24 100644 --- a/uc.c +++ b/uc.c @@ -742,15 +742,15 @@ uc_err uc_reg_write2(uc_engine *uc, int regid, const void *value, size_t *size) return UC_ERR_OK; } -static size_t memory_region_len(uc_engine *uc, MemoryRegion *mr, - uint64_t address, size_t count) +static uint64_t memory_region_len(uc_engine *uc, MemoryRegion *mr, + uint64_t address, uint64_t count) { hwaddr end = mr->end; while (mr->container != uc->system_memory) { mr = mr->container; end += mr->addr; } - return (size_t)MIN(count, end - address); + return (uint64_t)MIN(count, end - address); } // check if a memory area is mapped @@ -774,9 +774,9 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) } UNICORN_EXPORT -uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) +uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, uint64_t size) { - size_t count = 0, len; + uint64_t count = 0, len; uint8_t *bytes = _bytes; UC_INIT(uc); @@ -820,19 +820,13 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) UNICORN_EXPORT uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, - size_t size) + uint64_t size) { - size_t count = 0, len; + uint64_t count = 0, len; const uint8_t *bytes = _bytes; UC_INIT(uc); - // qemu cpu_physical_memory_rw() size is an int - if (size > INT_MAX) { - restore_jit_state(uc); - return UC_ERR_ARG; - } - if (!check_mem_area(uc, address, size)) { restore_jit_state(uc); return UC_ERR_WRITE_UNMAPPED; @@ -1226,7 +1220,7 @@ static uc_err mem_map(uc_engine *uc, MemoryRegion *block) return UC_ERR_OK; } -static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, +static uc_err mem_map_check(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms) { if (size == 0) { @@ -1234,7 +1228,7 @@ static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, return UC_ERR_ARG; } - // address cannot wrapp around + // address cannot wrap around if (address + size - 1 < address) { return UC_ERR_ARG; } @@ -1263,7 +1257,7 @@ static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, } UNICORN_EXPORT -uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) +uc_err uc_mem_map(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms) { uc_err res; @@ -1281,7 +1275,7 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) } UNICORN_EXPORT -uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, +uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms, void *ptr) { uc_err res; @@ -1305,7 +1299,7 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, } UNICORN_EXPORT -uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, +uc_err uc_mmio_map(uc_engine *uc, uint64_t address, uint64_t size, uc_cb_mmio_read_t read_cb, void *user_data_read, uc_cb_mmio_write_t write_cb, void *user_data_write) { @@ -1331,10 +1325,10 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, // Generally used in prepartion for splitting a MemoryRegion. static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) { - uint8_t *block = (uint8_t *)g_malloc0((size_t)int128_get64(mr->size)); + uint8_t *block = (uint8_t *)g_malloc0((uint64_t)int128_get64(mr->size)); if (block != NULL) { uc_err err = - uc_mem_read(uc, mr->addr, block, (size_t)int128_get64(mr->size)); + uc_mem_read(uc, mr->addr, block, (uint64_t)int128_get64(mr->size)); if (err != UC_ERR_OK) { free(block); block = NULL; @@ -1350,10 +1344,10 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) Note this function may be called recursively. */ static bool split_mmio_region(struct uc_struct *uc, MemoryRegion *mr, - uint64_t address, size_t size, bool do_delete) + uint64_t address, uint64_t size, bool do_delete) { uint64_t begin, end, chunk_end; - size_t l_size, r_size, m_size; + uint64_t l_size, r_size, m_size; mmio_cbs backup; chunk_end = address + size; @@ -1380,7 +1374,7 @@ static bool split_mmio_region(struct uc_struct *uc, MemoryRegion *mr, */ // unmap this region first, then do split it later - if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != + if (uc_mem_unmap(uc, mr->addr, (uint64_t)int128_get64(mr->size)) != UC_ERR_OK) { return false; } @@ -1394,9 +1388,9 @@ static bool split_mmio_region(struct uc_struct *uc, MemoryRegion *mr, } // compute sub region sizes - l_size = (size_t)(address - begin); - r_size = (size_t)(end - chunk_end); - m_size = (size_t)(chunk_end - address); + l_size = (uint64_t)(address - begin); + r_size = (uint64_t)(end - chunk_end); + m_size = (uint64_t)(chunk_end - address); if (l_size > 0) { if (uc_mmio_map(uc, begin, l_size, backup.read, backup.user_data_read, @@ -1439,12 +1433,12 @@ static bool split_mmio_region(struct uc_struct *uc, MemoryRegion *mr, // TODO: investigate whether qemu region manipulation functions already offered // this capability static bool split_region(struct uc_struct *uc, MemoryRegion *mr, - uint64_t address, size_t size, bool do_delete) + uint64_t address, uint64_t size, bool do_delete) { uint8_t *backup; uint32_t perms; uint64_t begin, end, chunk_end; - size_t l_size, m_size, r_size; + uint64_t l_size, m_size, r_size; RAMBlock *block = NULL; bool prealloc = false; @@ -1494,7 +1488,7 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, end = mr->end; // unmap this region first, then do split it later - if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != + if (uc_mem_unmap(uc, mr->addr, (uint64_t)int128_get64(mr->size)) != UC_ERR_OK) { goto error; } @@ -1515,9 +1509,9 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, } // compute sub region sizes - l_size = (size_t)(address - begin); - r_size = (size_t)(end - chunk_end); - m_size = (size_t)(chunk_end - address); + l_size = (uint64_t)(address - begin); + r_size = (uint64_t)(end - chunk_end); + m_size = (uint64_t)(chunk_end - address); // If there are error in any of the below operations, things are too far // gone at that point to recover. Could try to remap orignal region, but @@ -1585,13 +1579,13 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, } UNICORN_EXPORT -uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, +uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, uint64_t size, uint32_t perms) { MemoryRegion *mr; uint64_t addr = address; uint64_t pc; - size_t count, len; + uint64_t count, len; bool remove_exec = false; UC_INIT(uc); @@ -1685,7 +1679,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, } static uc_err uc_mem_unmap_snapshot(struct uc_struct *uc, uint64_t address, - size_t size, MemoryRegion **ret) + uint64_t size, MemoryRegion **ret) { MemoryRegion *mr; @@ -1712,7 +1706,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) { MemoryRegion *mr; uint64_t addr; - size_t count, len; + uint64_t count, len; UC_INIT(uc); From 41ae1578e1a5fe8f15fdb299fb8648bf639dab14 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 11:10:22 -0400 Subject: [PATCH 05/35] remove INT_MAX size check as we now use a 64 bit address --- uc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/uc.c b/uc.c index 29b0daff24..a9f42771be 100644 --- a/uc.c +++ b/uc.c @@ -781,12 +781,6 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, uint64_t size) UC_INIT(uc); - // qemu cpu_physical_memory_rw() size is an int - if (size > INT_MAX) { - restore_jit_state(uc); - return UC_ERR_ARG; - } - if (!check_mem_area(uc, address, size)) { restore_jit_state(uc); return UC_ERR_READ_UNMAPPED; From a115e0d88f477f2673619ae2841ad6f666b8d6ab Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 11:12:56 -0400 Subject: [PATCH 06/35] add @secretnonempty unit test for large memory addresses to avoid regression --- tests/unit/test_mem.c | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index eac4774085..bf2f9ee083 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -448,6 +448,78 @@ static void test_snapshot_unmap(void) OK(uc_context_free(ctx)); OK(uc_close(uc)); } +static void parts_increment(size_t idx, char parts[3]) +{ + if (idx && idx % 3 == 0) { + if (++parts[2] > '9') { + parts[2] = '0'; + if (++parts[1] > 'z') { + parts[1] = 'a'; + if (++parts[0] > 'Z') + parts[0] = 'A'; + } + } + } +} + +// Create a pattern string. It works the same as +// https://github.com/rapid7/metasploit-framework/blob/master/tools/exploit/pattern_create.rb +static void pattern_create(char *buf, size_t len) +{ + char parts[] = {'A', 'a', '0'}; + size_t i; + + for (i = 0; i < len; i++) { + buf[i] = parts[i % 3]; + parts_increment(i, parts); + } +} + +static bool pattern_verify(const char *buf, size_t len) +{ + char parts[] = {'A', 'a', '0'}; + size_t i; + + for (i = 0; i < len; i++) { + if (buf[i] != parts[i % 3]) + return false; + parts_increment(i, parts); + } + + return true; +} + +// Test for reading and writing memory block that are bigger than INT_MAX. +static void test_mem_read_and_write_large_memory_block(void) +{ + uc_engine *uc; + uint64_t mem_addr = 0x1000000; + uint64_t mem_size = 0x9f000000; + char *pmem = NULL; + + if (sizeof(void *) < 8) { + // Don't perform the test on a 32-bit platforms since we may not have + // enough memory space. + return; + } + + OK(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc)); + OK(uc_mem_map(uc, mem_addr, mem_size, UC_PROT_ALL)); + + pmem = malloc(mem_size); + if (TEST_CHECK(pmem != NULL)) { + pattern_create(pmem, mem_size); + + OK(uc_mem_write(uc, mem_addr, pmem, mem_size)); + memset(pmem, 'a', mem_size); + OK(uc_mem_read(uc, mem_addr, pmem, mem_size)); + TEST_CHECK(pattern_verify(pmem, mem_size)); + free(pmem); + } + + OK(uc_mem_unmap(uc, mem_addr, mem_size)); + OK(uc_close(uc)); +} TEST_LIST = {{"test_map_correct", test_map_correct}, {"test_map_wrapping", test_map_wrapping}, @@ -464,4 +536,6 @@ TEST_LIST = {{"test_map_correct", test_map_correct}, {"test_snapshot_with_vtlb", test_snapshot_with_vtlb}, {"test_context_snapshot", test_context_snapshot}, {"test_snapshot_unmap", test_snapshot_unmap}, + {"test_mem_read_and_write_large_memory_block", + test_mem_read_and_write_large_memory_block}, {NULL, NULL}}; From b5d0767acf149ab3636f3b8ffa17d405b20a6bcd Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 12:41:40 -0400 Subject: [PATCH 07/35] replace size_t in python3 bindings with u64 --- bindings/python/unicorn/unicorn_py3/unicorn.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/python/unicorn/unicorn_py3/unicorn.py b/bindings/python/unicorn/unicorn_py3/unicorn.py index f08e291410..f351d9b522 100644 --- a/bindings/python/unicorn/unicorn_py3/unicorn.py +++ b/bindings/python/unicorn/unicorn_py3/unicorn.py @@ -202,14 +202,14 @@ def __set_prototype(fname: str, restype: Type[ctypes._CData], *argtypes: Type[ct __set_prototype('uc_free', uc_err, void_p) __set_prototype('uc_hook_add', uc_err, uc_engine, PTR(uc_hook_h), s32, void_p, void_p, u64, u64) __set_prototype('uc_hook_del', uc_err, uc_engine, uc_hook_h) - __set_prototype('uc_mem_map', uc_err, uc_engine, u64, size_t, u32) - __set_prototype('uc_mem_map_ptr', uc_err, uc_engine, u64, size_t, u32, void_p) - __set_prototype('uc_mem_protect', uc_err, uc_engine, u64, size_t, u32) - __set_prototype('uc_mem_read', uc_err, uc_engine, u64, PTR(char), size_t) + __set_prototype('uc_mem_map', uc_err, uc_engine, u64, u64, u32) + __set_prototype('uc_mem_map_ptr', uc_err, uc_engine, u64, u64, u32, void_p) + __set_prototype('uc_mem_protect', uc_err, uc_engine, u64, u64, u32) + __set_prototype('uc_mem_read', uc_err, uc_engine, u64, PTR(char), u64) __set_prototype('uc_mem_regions', uc_err, uc_engine, PTR(PTR(uc_mem_region)), PTR(u32)) - __set_prototype('uc_mem_unmap', uc_err, uc_engine, u64, size_t) - __set_prototype('uc_mem_write', uc_err, uc_engine, u64, PTR(char), size_t) - __set_prototype('uc_mmio_map', uc_err, uc_engine, u64, size_t, void_p, void_p, void_p, void_p) + __set_prototype('uc_mem_unmap', uc_err, uc_engine, u64, u64) + __set_prototype('uc_mem_write', uc_err, uc_engine, u64, PTR(char), u64) + __set_prototype('uc_mmio_map', uc_err, uc_engine, u64, u64, void_p, void_p, void_p, void_p) __set_prototype('uc_open', uc_err, u32, u32, PTR(uc_engine)) __set_prototype('uc_query', uc_err, uc_engine, u32, PTR(size_t)) __set_prototype('uc_reg_read', uc_err, uc_engine, s32, void_p) From 19123415a41035bd5ce34b77ba539cfcdb0725ee Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 14:10:28 -0400 Subject: [PATCH 08/35] adjust rust bindings --- bindings/rust/src/ffi.rs | 14 +++++++------- bindings/rust/src/lib.rs | 25 +++++++++++++------------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/bindings/rust/src/ffi.rs b/bindings/rust/src/ffi.rs index 7f7a205bf9..7d5132cafe 100644 --- a/bindings/rust/src/ffi.rs +++ b/bindings/rust/src/ffi.rs @@ -40,36 +40,36 @@ extern "C" { engine: uc_handle, address: u64, bytes: *const u8, - size: libc::size_t, + size: u64, ) -> uc_error; pub fn uc_mem_read( engine: uc_handle, address: u64, bytes: *mut u8, - size: libc::size_t, + size: u64, ) -> uc_error; - pub fn uc_mem_map(engine: uc_handle, address: u64, size: libc::size_t, perms: u32) -> uc_error; + pub fn uc_mem_map(engine: uc_handle, address: u64, size: u64, perms: u32) -> uc_error; pub fn uc_mem_map_ptr( engine: uc_handle, address: u64, - size: libc::size_t, + size: u64, perms: u32, ptr: *mut c_void, ) -> uc_error; pub fn uc_mmio_map( engine: uc_handle, address: u64, - size: libc::size_t, + size: u64, read_cb: *mut c_void, user_data_read: *mut c_void, write_cb: *mut c_void, user_data_write: *mut c_void, ) -> uc_error; - pub fn uc_mem_unmap(engine: uc_handle, address: u64, size: libc::size_t) -> uc_error; + pub fn uc_mem_unmap(engine: uc_handle, address: u64, size: u64) -> uc_error; pub fn uc_mem_protect( engine: uc_handle, address: u64, - size: libc::size_t, + size: u64, perms: u32, ) -> uc_error; pub fn uc_mem_regions( diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 7cc95a3946..862a8957df 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -141,7 +141,7 @@ impl<'a> MmioCallbackScope<'a> { !self.regions.is_empty() } - fn unmap(&mut self, begin: u64, size: usize) { + fn unmap(&mut self, begin: u64, size: u64) { let end: u64 = begin + size as u64; self.regions = self .regions @@ -327,18 +327,18 @@ impl<'a, D> Unicorn<'a, D> { /// Read a range of bytes from memory at the specified emulated physical address. pub fn mem_read(&self, address: u64, buf: &mut [u8]) -> Result<(), uc_error> { - unsafe { ffi::uc_mem_read(self.get_handle(), address, buf.as_mut_ptr(), buf.len()) }.into() + unsafe { ffi::uc_mem_read(self.get_handle(), address, buf.as_mut_ptr(), buf.len().try_into().unwrap()) }.into() } /// Return a range of bytes from memory at the specified emulated physical address as vector. - pub fn mem_read_as_vec(&self, address: u64, size: usize) -> Result, uc_error> { + pub fn mem_read_as_vec(&self, address: u64, size: u64) -> Result, uc_error> { let mut buf = vec![0; size]; - unsafe { ffi::uc_mem_read(self.get_handle(), address, buf.as_mut_ptr(), size) }.and(Ok(buf)) + unsafe { ffi::uc_mem_read(self.get_handle(), address, buf.as_mut_ptr(), size.try_into().unwrap()) }.and(Ok(buf)) } /// Write the data in `bytes` to the emulated physical address `address` pub fn mem_write(&mut self, address: u64, bytes: &[u8]) -> Result<(), uc_error> { - unsafe { ffi::uc_mem_write(self.get_handle(), address, bytes.as_ptr(), bytes.len()) }.into() + unsafe { ffi::uc_mem_write(self.get_handle(), address, bytes.as_ptr(), bytes.len().try_into().unwrap()) }.into() } /// Map an existing memory region in the emulator at the specified address. @@ -371,7 +371,7 @@ impl<'a, D> Unicorn<'a, D> { pub fn mem_map( &mut self, address: u64, - size: libc::size_t, + size: u64, perms: Permission, ) -> Result<(), uc_error> { unsafe { ffi::uc_mem_map(self.get_handle(), address, size, perms.bits()) }.into() @@ -384,7 +384,7 @@ impl<'a, D> Unicorn<'a, D> { pub fn mmio_map( &mut self, address: u64, - size: libc::size_t, + size: u64, read_callback: Option, write_callback: Option, ) -> Result<(), uc_error> @@ -431,8 +431,9 @@ impl<'a, D> Unicorn<'a, D> { .and_then(|| { let rd = read_data.map(|c| c as Box); let wd = write_data.map(|c| c as Box); + let u64_size : u64 = size.try_into.unwrap(); self.inner_mut().mmio_callbacks.push(MmioCallbackScope { - regions: vec![(address, size)], + regions: vec![(address, u64_size)], read_callback: rd, write_callback: wd, }); @@ -448,7 +449,7 @@ impl<'a, D> Unicorn<'a, D> { pub fn mmio_map_ro( &mut self, address: u64, - size: libc::size_t, + size: u64, callback: F, ) -> Result<(), uc_error> where @@ -469,7 +470,7 @@ impl<'a, D> Unicorn<'a, D> { pub fn mmio_map_wo( &mut self, address: u64, - size: libc::size_t, + size: u64, callback: F, ) -> Result<(), uc_error> where @@ -487,7 +488,7 @@ impl<'a, D> Unicorn<'a, D> { /// /// `address` must be aligned to 4kb or this will return `Error::ARG`. /// `size` must be a multiple of 4kb or this will return `Error::ARG`. - pub fn mem_unmap(&mut self, address: u64, size: libc::size_t) -> Result<(), uc_error> { + pub fn mem_unmap(&mut self, address: u64, size: u64) -> Result<(), uc_error> { let err = unsafe { ffi::uc_mem_unmap(self.get_handle(), address, size) }; self.mmio_unmap(address, size); err.into() @@ -509,7 +510,7 @@ impl<'a, D> Unicorn<'a, D> { pub fn mem_protect( &mut self, address: u64, - size: libc::size_t, + size: u64, perms: Permission, ) -> Result<(), uc_error> { unsafe { ffi::uc_mem_protect(self.get_handle(), address, size, perms.bits()) }.into() From 4a92fd190b979476e5fb79fabfa5e5c103de1ba8 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 14:21:17 -0400 Subject: [PATCH 09/35] use format.sh script to improve formatting --- bindings/java/unicorn_Unicorn.c | 5 +++-- include/unicorn/unicorn.h | 3 ++- tests/unit/test_arm.c | 11 ++++++----- tests/unit/test_mem.c | 2 +- tests/unit/unicorn_test.h | 19 +++++++++---------- uc.c | 3 ++- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/bindings/java/unicorn_Unicorn.c b/bindings/java/unicorn_Unicorn.c index 61cf93ba09..785ff55bfd 100644 --- a/bindings/java/unicorn_Unicorn.c +++ b/bindings/java/unicorn_Unicorn.c @@ -760,7 +760,7 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn__1mem_1read(JNIEnv *env, { jsize size = (*env)->GetArrayLength(env, dest); jbyte *arr = (*env)->GetByteArrayElements(env, dest, NULL); - uc_err err = uc_mem_read((uc_engine *)uc, address, arr, size); + uc_err err = uc_mem_read((uc_engine *)uc, address, arr, *size); (*env)->ReleaseByteArrayElements(env, dest, arr, 0); if (err != UC_ERR_OK) { throwUnicornException(env, err); @@ -780,7 +780,8 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn__1mem_1write(JNIEnv *env, { jsize size = (*env)->GetArrayLength(env, src); jbyte *arr = (*env)->GetByteArrayElements(env, src, NULL); - uc_err err = uc_mem_write((uc_engine *)uc, address, arr, size); + // add type cast in case that type inflection does not work + uc_err err = uc_mem_write((uc_engine *)uc, address, arr, (uint64_t)size); (*env)->ReleaseByteArrayElements(env, src, arr, JNI_ABORT); if (err != UC_ERR_OK) { throwUnicornException(env, err); diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 5a099d5717..7e33e1b1bc 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -1059,7 +1059,8 @@ typedef enum uc_context_content { for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_map(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms); +uc_err uc_mem_map(uc_engine *uc, uint64_t address, uint64_t size, + uint32_t perms); /* Map existing host memory in for emulation. diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 309b5ccbc5..dd71642d6b 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -966,8 +966,8 @@ static bool test_arm_v7_lpae_hook_tlb(uc_engine *uc, uint64_t addr, } static void test_arm_v7_lpae_hook_read(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, uint64_t value, - void *user_data) + uint64_t address, int size, + uint64_t value, void *user_data) { TEST_CHECK(address == 0x100001000); } @@ -981,10 +981,11 @@ static void test_arm_v7_lpae(void) OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc)); OK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_A7)); - OK(uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL)); - OK(uc_hook_add(uc, &hook_tlb, UC_HOOK_TLB_FILL, test_arm_v7_lpae_hook_tlb, NULL, 1, 0)); - OK(uc_hook_add(uc, &hook_read, UC_HOOK_MEM_READ, test_arm_v7_lpae_hook_read, NULL, 1, 0)); + OK(uc_hook_add(uc, &hook_tlb, UC_HOOK_TLB_FILL, test_arm_v7_lpae_hook_tlb, + NULL, 1, 0)); + OK(uc_hook_add(uc, &hook_read, UC_HOOK_MEM_READ, test_arm_v7_lpae_hook_read, + NULL, 1, 0)); reg = 0x1000; OK(uc_reg_write(uc, UC_ARM_REG_R0, ®)); diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index bf2f9ee083..7ecf58dae0 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -536,6 +536,6 @@ TEST_LIST = {{"test_map_correct", test_map_correct}, {"test_snapshot_with_vtlb", test_snapshot_with_vtlb}, {"test_context_snapshot", test_context_snapshot}, {"test_snapshot_unmap", test_snapshot_unmap}, - {"test_mem_read_and_write_large_memory_block", + {"test_mem_read_and_write_large_memory_block", test_mem_read_and_write_large_memory_block}, {NULL, NULL}}; diff --git a/tests/unit/unicorn_test.h b/tests/unit/unicorn_test.h index 159a1cbd97..336757a942 100644 --- a/tests/unit/unicorn_test.h +++ b/tests/unit/unicorn_test.h @@ -11,19 +11,18 @@ /* Swap bytes in 32 bit value. */ #define bswap_32(x) \ - ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \ - (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) + ((((x)&0xff000000u) >> 24) | (((x)&0x00ff0000u) >> 8) | \ + (((x)&0x0000ff00u) << 8) | (((x)&0x000000ffu) << 24)) /* Swap bytes in 64 bit value. */ #define bswap_64(x) \ - ((((x) & 0xff00000000000000ull) >> 56) | \ - (((x) & 0x00ff000000000000ull) >> 40) | \ - (((x) & 0x0000ff0000000000ull) >> 24) | \ - (((x) & 0x000000ff00000000ull) >> 8) | \ - (((x) & 0x00000000ff000000ull) << 8) | \ - (((x) & 0x0000000000ff0000ull) << 24) | \ - (((x) & 0x000000000000ff00ull) << 40) | \ - (((x) & 0x00000000000000ffull) << 56)) + ((((x)&0xff00000000000000ull) >> 56) | \ + (((x)&0x00ff000000000000ull) >> 40) | \ + (((x)&0x0000ff0000000000ull) >> 24) | \ + (((x)&0x000000ff00000000ull) >> 8) | (((x)&0x00000000ff000000ull) << 8) | \ + (((x)&0x0000000000ff0000ull) << 24) | \ + (((x)&0x000000000000ff00ull) << 40) | \ + (((x)&0x00000000000000ffull) << 56)) /** * Assert that err matches expect diff --git a/uc.c b/uc.c index a9f42771be..e065621755 100644 --- a/uc.c +++ b/uc.c @@ -1251,7 +1251,8 @@ static uc_err mem_map_check(uc_engine *uc, uint64_t address, uint64_t size, } UNICORN_EXPORT -uc_err uc_mem_map(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms) +uc_err uc_mem_map(uc_engine *uc, uint64_t address, uint64_t size, + uint32_t perms) { uc_err res; From d32b25d94dfd7b7c17913fadd39982c4f540eefb Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 15:22:19 -0400 Subject: [PATCH 10/35] small adjustments to java bindings, because jlong type is sometimes already used --- bindings/java/unicorn_Unicorn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/java/unicorn_Unicorn.c b/bindings/java/unicorn_Unicorn.c index 785ff55bfd..739ca36c2c 100644 --- a/bindings/java/unicorn_Unicorn.c +++ b/bindings/java/unicorn_Unicorn.c @@ -758,7 +758,7 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn__1mem_1read(JNIEnv *env, jlong address, jbyteArray dest) { - jsize size = (*env)->GetArrayLength(env, dest); + jlong size = (*env)->GetArrayLength(env, dest); jbyte *arr = (*env)->GetByteArrayElements(env, dest, NULL); uc_err err = uc_mem_read((uc_engine *)uc, address, arr, *size); (*env)->ReleaseByteArrayElements(env, dest, arr, 0); From 37cb96bdc5e7e2d329481e82ec43329a6d211f46 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 15:28:24 -0400 Subject: [PATCH 11/35] adjust dotnet bindings to reflect new type sizes --- .../dotnet/UnicornEngine/Binding/NativeBinding.fs | 14 +++++++------- bindings/go/unicorn/unicorn.go | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bindings/dotnet/UnicornEngine/Binding/NativeBinding.fs b/bindings/dotnet/UnicornEngine/Binding/NativeBinding.fs index efaccc48aa..ecd7d27562 100644 --- a/bindings/dotnet/UnicornEngine/Binding/NativeBinding.fs +++ b/bindings/dotnet/UnicornEngine/Binding/NativeBinding.fs @@ -18,22 +18,22 @@ module NativeBinding = extern Int32 uc_close(UIntPtr eng) [] - extern Int32 uc_mem_map(UIntPtr eng, UInt64 address, UIntPtr size, UInt32 perm) + extern Int32 uc_mem_map(UIntPtr eng, UInt64 address, UInt64 size, UInt32 perm) [] - extern Int32 uc_mem_map_ptr(UIntPtr eng, UInt64 address, UIntPtr size, UInt32 perm, UIntPtr ptr) + extern Int32 uc_mem_map_ptr(UIntPtr eng, UInt64 address, UInt64 size, UInt32 perm, UIntPtr ptr) [] - extern Int32 uc_mem_unmap(UIntPtr eng, UInt64 address, UIntPtr size) + extern Int32 uc_mem_unmap(UIntPtr eng, UInt64 address, UInt64 size) [] - extern Int32 uc_mem_protect(UIntPtr eng, UInt64 address, UIntPtr size, UInt32 perms) + extern Int32 uc_mem_protect(UIntPtr eng, UInt64 address, UInt64 size, UInt32 perms) [] - extern Int32 uc_mem_write(UIntPtr eng, UInt64 address, Byte[] value, UIntPtr size) + extern Int32 uc_mem_write(UIntPtr eng, UInt64 address, Byte[] value, UInt64 size) [] - extern Int32 uc_mem_read(UIntPtr eng, UInt64 address, Byte[] value, UIntPtr size) + extern Int32 uc_mem_read(UIntPtr eng, UInt64 address, Byte[] value, UInt64 size) [] extern Int32 uc_reg_write(UIntPtr eng, Int32 regId, Byte[] value) @@ -90,4 +90,4 @@ module NativeBinding = member thi.HookAddNoarg(eng, hh, callbackType, callback, userData, hookBegin, hookEnd) = uc_hook_add_noarg(eng, hh, callbackType, callback, userData, hookBegin, hookEnd) member thi.HookAddArg0(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0) = uc_hook_add_arg0(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0) member thi.HookAddArg0Arg1(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0, arg1) = uc_hook_add_arg0_arg1(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0, arg1) - } \ No newline at end of file + } diff --git a/bindings/go/unicorn/unicorn.go b/bindings/go/unicorn/unicorn.go index 802c816367..c1e5793cfc 100644 --- a/bindings/go/unicorn/unicorn.go +++ b/bindings/go/unicorn/unicorn.go @@ -187,14 +187,14 @@ func (u *uc) MemWrite(addr uint64, data []byte) error { if len(data) == 0 { return nil } - return errReturn(C.uc_mem_write(u.handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.size_t(len(data)))) + return errReturn(C.uc_mem_write(u.handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.uint64_t(len(data)))) } func (u *uc) MemReadInto(dst []byte, addr uint64) error { if len(dst) == 0 { return nil } - return errReturn(C.uc_mem_read(u.handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.size_t(len(dst)))) + return errReturn(C.uc_mem_read(u.handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.uint64_t(len(dst)))) } func (u *uc) MemRead(addr, size uint64) ([]byte, error) { @@ -203,7 +203,7 @@ func (u *uc) MemRead(addr, size uint64) ([]byte, error) { } func (u *uc) MemMapProt(addr, size uint64, prot int) error { - return errReturn(C.uc_mem_map(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot))) + return errReturn(C.uc_mem_map(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot))) } func (u *uc) MemMap(addr, size uint64) error { @@ -211,15 +211,15 @@ func (u *uc) MemMap(addr, size uint64) error { } func (u *uc) MemMapPtr(addr, size uint64, prot int, ptr unsafe.Pointer) error { - return errReturn(C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot), ptr)) + return errReturn(C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot), ptr)) } func (u *uc) MemProtect(addr, size uint64, prot int) error { - return errReturn(C.uc_mem_protect(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot))) + return errReturn(C.uc_mem_protect(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot))) } func (u *uc) MemUnmap(addr, size uint64) error { - return errReturn(C.uc_mem_unmap(u.handle, C.uint64_t(addr), C.size_t(size))) + return errReturn(C.uc_mem_unmap(u.handle, C.uint64_t(addr), C.uint64_t(size))) } func (u *uc) Query(queryType int) (uint64, error) { From 731c08f46d6f9d6576c6989f36f4b912d5162ffd Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 15:32:49 -0400 Subject: [PATCH 12/35] adjust pascal bindings --- bindings/pascal/unicorn/Unicorn_dyn.pas | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bindings/pascal/unicorn/Unicorn_dyn.pas b/bindings/pascal/unicorn/Unicorn_dyn.pas index 427813cf75..96f296587c 100755 --- a/bindings/pascal/unicorn/Unicorn_dyn.pas +++ b/bindings/pascal/unicorn/Unicorn_dyn.pas @@ -291,7 +291,7 @@ uc_mem_region = record for detailed error). *) uc_mem_write_ : function (uc : uc_engine; address : UInt64; const bytes : Pointer; - size : Cardinal) : uc_err; cdecl; + size : UInt64) : uc_err; cdecl; (* Read a range of bytes in memory. @@ -307,7 +307,7 @@ uc_mem_region = record for detailed error). *) uc_mem_read_ : function (uc : uc_engine; address : UInt64; bytes : Pointer; - size : Cardinal) : uc_err; cdecl; + size : UInt64) : uc_err; cdecl; (* Emulate machine code in a specific duration of time. @@ -400,7 +400,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer; @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). *) - uc_mem_map : function (uc : uc_engine; address : UInt64; size : Cardinal; perms : UInt32) : uc_err; cdecl; + uc_mem_map : function (uc : uc_engine; address : UInt64; size : UInt64; perms : UInt32) : uc_err; cdecl; (* @@ -422,7 +422,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer; @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). *) - uc_mem_map_ptr : function(uc : uc_engine; address : UInt64; size : Cardinal; perms : UInt32; ptr : Pointer) : uc_err; cdecl; + uc_mem_map_ptr : function(uc : uc_engine; address : UInt64; size : UInt64; perms : UInt32; ptr : Pointer) : uc_err; cdecl; (* @@ -438,7 +438,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer; @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum \ for detailed error). *) - uc_mem_unmap : function (uc : uc_engine; address : UInt64; size : Cardinal) : uc_err; cdecl ; + uc_mem_unmap : function (uc : uc_engine; address : UInt64; size : UInt64) : uc_err; cdecl ; (* Set memory permissions for emulation memory. @@ -456,7 +456,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer; @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum \ for detailed error). *) - uc_mem_protect : function (uc : uc_engine; address : UInt64; size : Cardinal; perms : UInt32) : uc_err; cdecl ; + uc_mem_protect : function (uc : uc_engine; address : UInt64; size : UInt64; perms : UInt32) : uc_err; cdecl ; (* Retrieve all memory regions mapped by uc_mem_map() and uc_mem_map_ptr() From eddc3223557e7aa2861eb82f2148ba3dc93bfe0d Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 15:37:35 -0400 Subject: [PATCH 13/35] adjust ruby bindings --- bindings/ruby/unicorn_gem/ext/unicorn.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/ruby/unicorn_gem/ext/unicorn.c b/bindings/ruby/unicorn_gem/ext/unicorn.c index 77346d2bfd..7bce97b2cf 100644 --- a/bindings/ruby/unicorn_gem/ext/unicorn.c +++ b/bindings/ruby/unicorn_gem/ext/unicorn.c @@ -275,7 +275,7 @@ VALUE m_uc_reg_write(VALUE self, VALUE reg_id, VALUE reg_value){ } VALUE m_uc_mem_read(VALUE self, VALUE address, VALUE size){ - size_t isize = NUM2UINT(size); + uint64_t isize = NUM2ULL(size); uint8_t bytes[isize]; uc_err err; uc_engine *_uc; @@ -310,7 +310,7 @@ VALUE m_uc_mem_map(int argc, VALUE* argv, VALUE self){ if (NIL_P(perms)) perms = INT2NUM(UC_PROT_ALL); - err = uc_mem_map(_uc, NUM2ULL(address), NUM2UINT(size), NUM2UINT(perms)); + err = uc_mem_map(_uc, NUM2ULL(address), NUM2ULL(size), NUM2UINT(perms)); if (err != UC_ERR_OK) { rb_raise(UcError, "%s", uc_strerror(err)); } @@ -321,7 +321,7 @@ VALUE m_uc_mem_unmap(VALUE self, VALUE address, VALUE size){ uc_err err; uc_engine *_uc; Data_Get_Struct(rb_iv_get(self, "@uch"), uc_engine, _uc); - err = uc_mem_unmap(_uc, NUM2ULL(address), NUM2UINT(size)); + err = uc_mem_unmap(_uc, NUM2ULL(address), NUM2ULL(size)); if (err != UC_ERR_OK) { rb_raise(UcError, "%s", uc_strerror(err)); } @@ -332,7 +332,7 @@ VALUE m_uc_mem_protect(VALUE self, VALUE address, VALUE size, VALUE perms){ uc_err err; uc_engine *_uc; Data_Get_Struct(rb_iv_get(self,"@uch"), uc_engine, _uc); - err = uc_mem_protect(_uc, NUM2ULL(address), NUM2UINT(size), NUM2UINT(perms)); + err = uc_mem_protect(_uc, NUM2ULL(address), NUM2UINT(size), NUM2ULL(perms)); if (err != UC_ERR_OK) { rb_raise(UcError, "%s", uc_strerror(err)); } From caf81dc9266671629c0666a26b3b42291d730d10 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 15:46:20 -0400 Subject: [PATCH 14/35] adjust vb6 bindings --- bindings/vb6/main.cpp | 18 +++++++++--------- bindings/vb6/uc_def.bas | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bindings/vb6/main.cpp b/bindings/vb6/main.cpp index 140d44981a..fb05c5b43c 100644 --- a/bindings/vb6/main.cpp +++ b/bindings/vb6/main.cpp @@ -230,12 +230,12 @@ uc_err __stdcall ucs_reg_read_batch(uc_engine *uc, int *regs, void **vals, int c return uc_reg_read_batch(uc, regs, vals, count); } -uc_err __stdcall ucs_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size){ +uc_err __stdcall ucs_mem_write(uc_engine *uc, uint64_t address, const void *bytes, uint64_t size){ #pragma EXPORT return uc_mem_write(uc, address, bytes, size); } -uc_err __stdcall ucs_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size){ +uc_err __stdcall ucs_mem_read(uc_engine *uc, uint64_t address, void *bytes, uint64_t size){ #pragma EXPORT return uc_mem_read(uc, address, bytes, size); } @@ -255,24 +255,24 @@ uc_err __stdcall ucs_hook_del(uc_engine *uc, uc_hook hh){ return uc_hook_del(uc, hh); } -uc_err __stdcall ucs_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms){ +uc_err __stdcall ucs_mem_map(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms){ #pragma EXPORT return uc_mem_map(uc, address, size, perms); } //requires link against v1.0 -uc_err __stdcall ucs_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr){ +uc_err __stdcall ucs_mem_map_ptr(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms, void *ptr){ #pragma EXPORT return uc_mem_map_ptr(uc, address, size, perms, ptr); } -uc_err __stdcall ucs_mem_unmap(uc_engine *uc, uint64_t address, size_t size){ +uc_err __stdcall ucs_mem_unmap(uc_engine *uc, uint64_t address, uint64_t size){ #pragma EXPORT return uc_mem_unmap(uc, address, size); } -uc_err __stdcall ucs_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms){ +uc_err __stdcall ucs_mem_protect(uc_engine *uc, uint64_t address, uint64_t size, uint32_t perms){ #pragma EXPORT return uc_mem_protect(uc, address, size, perms); } @@ -363,12 +363,12 @@ int __stdcall disasm_addr(uc_engine *uc, uint32_t va, char *str, int bufLen){ //maps and write in one shot, auto handles alignment.. -uc_err __stdcall mem_write_block(uc_engine *uc, uint64_t address, void* data, uint32_t size, uint32_t perm){ +uc_err __stdcall mem_write_block(uc_engine *uc, uint64_t address, void* data, uint64_t size, uint32_t perm){ #pragma EXPORT uc_err x; uint64_t base = address; - uint32_t sz = size; + uint64_t sz = size; while(base % 0x1000 !=0){ base--; @@ -456,4 +456,4 @@ unsigned int __stdcall ULong(unsigned int v1, unsigned int v2, int operation){ return -1; -} \ No newline at end of file +} diff --git a/bindings/vb6/uc_def.bas b/bindings/vb6/uc_def.bas index 43193a8a15..6baa23615c 100644 --- a/bindings/vb6/uc_def.bas +++ b/bindings/vb6/uc_def.bas @@ -2078,7 +2078,7 @@ Public Declare Function ucs_reg_read Lib "ucvbshim.dll" (ByVal hEngine As Long, '*/ 'UNICORN_EXPORT 'uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size); -Public Declare Function ucs_mem_write Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByRef b As Byte, ByVal size As Long) As uc_err +Public Declare Function ucs_mem_write Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByRef b As Byte, ByVal size As Currency) As uc_err @@ -2097,7 +2097,7 @@ Public Declare Function ucs_mem_write Lib "ucvbshim.dll" (ByVal hEngine As Long, '*/ 'UNICORN_EXPORT 'uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); -Public Declare Function ucs_mem_read Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByRef b As Byte, ByVal size As Long) As uc_err +Public Declare Function ucs_mem_read Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByRef b As Byte, ByVal size As Currency) As uc_err @@ -2203,7 +2203,7 @@ Public Declare Function ucs_hook_del Lib "ucvbshim.dll" (ByVal hEngine As Long, '*/ 'UNICORN_EXPORT 'uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); -Public Declare Function ucs_mem_map Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Long, ByVal perms As uc_prot) As uc_err +Public Declare Function ucs_mem_map Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Currency, ByVal perms As uc_prot) As uc_err @@ -2228,7 +2228,7 @@ Public Declare Function ucs_mem_map Lib "ucvbshim.dll" (ByVal hEngine As Long, B '*/ 'UNICORN_EXPORT 'uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr); -Public Declare Function ucs_mem_map_ptr Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Long, ByVal perms As uc_prot, ByVal ptr As Long) As uc_err +Public Declare Function ucs_mem_map_ptr Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Currency, ByVal perms As uc_prot, ByVal ptr As Long) As uc_err @@ -2247,7 +2247,7 @@ Public Declare Function ucs_mem_map_ptr Lib "ucvbshim.dll" (ByVal hEngine As Lon '*/ 'UNICORN_EXPORT 'uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); -Public Declare Function ucs_mem_unmap Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Long) As uc_err +Public Declare Function ucs_mem_unmap Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Currency) As uc_err '/* @@ -2268,7 +2268,7 @@ Public Declare Function ucs_mem_unmap Lib "ucvbshim.dll" (ByVal hEngine As Long, '*/ 'UNICORN_EXPORT 'uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); -Public Declare Function ucs_mem_protect Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Long, ByVal perm As uc_prot) As uc_err +Public Declare Function ucs_mem_protect Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByVal size As Currency, ByVal perm As uc_prot) As uc_err @@ -2368,7 +2368,7 @@ Public Declare Function disasm_addr Lib "ucvbshim.dll" (ByVal hEngine As Long, B 'simplified access to map and write data to emu memory 'uc_err __stdcall mem_write_block(uc_engine *uc, uint64_t address, void* data, uint32_t size, uint32_t perm){ -Public Declare Function mem_write_block Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByRef data As Byte, ByVal size As Long, ByVal perm As Long) As uc_err +Public Declare Function mem_write_block Lib "ucvbshim.dll" (ByVal hEngine As Long, ByVal addr As Currency, ByRef data As Byte, ByVal size As Currency, ByVal perm As Long) As uc_err Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long From 4d10b6222c86d8c91b4e35f9a1215846d0a4a41e Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 15:50:48 -0400 Subject: [PATCH 15/35] adjust zig bindings for 64 bit size support --- bindings/zig/unicorn/unicorn.zig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/zig/unicorn/unicorn.zig b/bindings/zig/unicorn/unicorn.zig index 270d007d72..25e9a09c6a 100644 --- a/bindings/zig/unicorn/unicorn.zig +++ b/bindings/zig/unicorn/unicorn.zig @@ -75,10 +75,10 @@ pub fn uc_reg_write_batch(uc: ?*c.uc_engine, regs: [*c]c_int, vals: [*c]const ?* pub fn uc_reg_read_batch(uc: ?*c.uc_engine, regs: [*c]c_int, vals: [*c]?*anyopaque, count: c_int) !void { try getErrors(c.uc_reg_read_batch(uc, regs, vals, count)); } -pub fn uc_mem_write(uc: ?*c.uc_engine, address: u64, bytes: ?*const anyopaque, size: usize) !void { +pub fn uc_mem_write(uc: ?*c.uc_engine, address: u64, bytes: ?*const anyopaque, size: u64) !void { try getErrors(c.uc_mem_write(uc, address, bytes, size)); } -pub fn uc_mem_read(uc: ?*c.uc_engine, address: u64, bytes: ?*anyopaque, size: usize) !void { +pub fn uc_mem_read(uc: ?*c.uc_engine, address: u64, bytes: ?*anyopaque, size: u64) !void { try getErrors(c.uc_mem_read(uc, address, bytes, size)); } pub fn uc_emu_start(uc: ?*c.uc_engine, begin: u64, until: u64, timeout: u64, count: usize) !void { @@ -93,19 +93,19 @@ pub fn uc_hook_add(uc: ?*c.uc_engine, hh: [*c]c.uc_hook, @"type": c_int, callbac pub fn uc_hook_del(uc: ?*c.uc_engine, hh: c.uc_hook) !void { try getErrors(c.uc_hook_del(uc, hh)); } -pub fn uc_mem_map(uc: ?*c.uc_engine, address: u64, size: usize, perms: u32) !void { +pub fn uc_mem_map(uc: ?*c.uc_engine, address: u64, size: u64, perms: u32) !void { try getErrors(c.uc_mem_map(uc, address, size, perms)); } -pub fn uc_mem_map_ptr(uc: ?*c.uc_engine, address: u64, size: usize, perms: u32, ptr: ?*anyopaque) !void { +pub fn uc_mem_map_ptr(uc: ?*c.uc_engine, address: u64, size: u64, perms: u32, ptr: ?*anyopaque) !void { try getErrors(c.uc_mem_map_ptr(uc, address, size, perms, ptr)); } -pub fn uc_mmio_map(uc: ?*c.uc_engine, address: u64, size: usize, read_cb: c.uc_cb_mmio_read_t, user_data_read: ?*anyopaque, write_cb: c.uc_cb_mmio_write_t, user_data_write: ?*anyopaque) !void { +pub fn uc_mmio_map(uc: ?*c.uc_engine, address: u64, size: u64, read_cb: c.uc_cb_mmio_read_t, user_data_read: ?*anyopaque, write_cb: c.uc_cb_mmio_write_t, user_data_write: ?*anyopaque) !void { try getErrors(c.uc_mmio_map(uc, address, size, read_cb, user_data_read, write_cb, user_data_write)); } -pub fn uc_mem_unmap(uc: ?*c.uc_engine, address: u64, size: usize) !void { +pub fn uc_mem_unmap(uc: ?*c.uc_engine, address: u64, size: u64) !void { try getErrors(c.uc_mem_unmap(uc, address, size)); } -pub fn uc_mem_protect(uc: ?*c.uc_engine, address: u64, size: usize, perms: u32) !void { +pub fn uc_mem_protect(uc: ?*c.uc_engine, address: u64, size: u64, perms: u32) !void { try getErrors(c.uc_mem_protect(uc, address, size, perms)); } pub fn uc_mem_regions(uc: ?*c.uc_engine, regions: [*c][*c]c.uc_mem_region, count: [*c]u32) !void { From a115d6f3faf05dd69c8af556b4f1fdc7698745e2 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 16:23:49 -0400 Subject: [PATCH 16/35] fix build.zig.zon for newer zig versions --- build.zig.zon | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.zig.zon b/build.zig.zon index de7392c748..ce9de9d143 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,5 +1,7 @@ .{ - .name = "unicorn", + .name = .unicorn, .version = "2.1.3", + .minimum_zig_version = "0.14.0-dev.3445+6c3cbb0c8", + .fingerprint = 0x58fbd83f3bf465b6, .paths = .{""}, } From d8ed6c99012dc99af2dab2051e23c9ffe44c5d26 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sat, 5 Apr 2025 16:26:17 -0400 Subject: [PATCH 17/35] add haskell binding support for 64 bit sizes --- bindings/haskell/src/Unicorn.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/haskell/src/Unicorn.hs b/bindings/haskell/src/Unicorn.hs index 7ea638e5a5..ce37f26b67 100644 --- a/bindings/haskell/src/Unicorn.hs +++ b/bindings/haskell/src/Unicorn.hs @@ -217,7 +217,7 @@ memWrite uc address bytes = do memRead :: Engine -- ^ 'Unicorn' engine handle -> Word64 -- ^ Starting memory address to read -- from - -> Int -- ^ Size of memory to read (in bytes) + -> Word64 -- ^ Size of memory to read (in bytes) -> Emulator ByteString -- ^ The memory contents on success, or -- an 'Error' on failure memRead uc address size = do @@ -238,7 +238,7 @@ memMap :: Engine -- ^ 'Unicorn' engine handle -- be mapped in. This address must be -- aligned to 4KB, or this will return with -- 'ErrArg' error - -> Int -- ^ Size of the new memory region to be mapped + -> Word64 -- ^ Size of the new memory region to be mapped -- in. This size must be a multiple of 4KB, or -- this will return with an 'ErrArg' error -> [MemoryPermission] -- ^ Permissions for the newly mapped region @@ -255,7 +255,7 @@ memUnmap :: Engine -- ^ 'Unicorn' engine handle -> Word64 -- ^ Start addres of the memory region to be unmapped. -- This address must be aligned to 4KB or this will -- return with an 'ErrArg' error - -> Int -- ^ Size of the memory region to be modified. This + -> Word64 -- ^ Size of the memory region to be modified. This -- must be a multiple of 4KB, or this will return with -- an 'ErrArg' error -> Emulator () -- ^ An 'Error' on failure @@ -272,7 +272,7 @@ memProtect :: Engine -- ^ 'Unicorn' engine handle -- modify. This address must be aligned to -- 4KB, or this will return with an -- 'ErrArg' error - -> Int -- ^ Size of the memory region to be + -> Word64 -- ^ Size of the memory region to be -- modified. This size must be a multiple -- of 4KB, or this will return with an -- 'ErrArg' error From 500be158b5b3b7a8537186f5d93a4f13b6c48e7d Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 05:47:02 -0400 Subject: [PATCH 18/35] use mlugg/setup-zig instead of goto-bus-stop/setup-zig github action to get access to current zig releases --- .github/workflows/zigbuild.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/zigbuild.yml b/.github/workflows/zigbuild.yml index 810e24f646..34037a5c8e 100644 --- a/.github/workflows/zigbuild.yml +++ b/.github/workflows/zigbuild.yml @@ -26,9 +26,9 @@ jobs: with: submodules: recursive fetch-depth: 0 - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v1 with: - version: 0.13.0 + version: 0.15.0 - uses: lukka/get-cmake@latest with: cmakeVersion: latest @@ -50,9 +50,9 @@ jobs: with: submodules: recursive fetch-depth: 0 - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v1 with: - version: 0.13.0 + version: 0.15.0 - uses: lukka/get-cmake@latest with: cmakeVersion: latest From 7aec74a2137d326a24bf4cf0a9b2bf1fc8bbfd49 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 05:49:41 -0400 Subject: [PATCH 19/35] use uint64_t instead of size_t for uc_mem_unmap --- uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uc.c b/uc.c index e065621755..0c7a26b1e0 100644 --- a/uc.c +++ b/uc.c @@ -1697,7 +1697,7 @@ static uc_err uc_mem_unmap_snapshot(struct uc_struct *uc, uint64_t address, } UNICORN_EXPORT -uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) +uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, uint64_t size) { MemoryRegion *mr; uint64_t addr; From c2bc937c8f606c3aef16241257d4a549a3e0aefe Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 07:30:35 -0400 Subject: [PATCH 20/35] add whitespace between functions to preserver formatting --- tests/unit/test_mem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 7ecf58dae0..fd2788544f 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -448,6 +448,7 @@ static void test_snapshot_unmap(void) OK(uc_context_free(ctx)); OK(uc_close(uc)); } + static void parts_increment(size_t idx, char parts[3]) { if (idx && idx % 3 == 0) { From c0d67b2dab593afe47a974c946e0b257da12096d Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 07:35:37 -0400 Subject: [PATCH 21/35] add precompiler check for android and abort execution of testcase to avoid infinite low memory killer loop --- tests/unit/test_mem.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index fd2788544f..950b542b32 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -503,6 +503,12 @@ static void test_mem_read_and_write_large_memory_block(void) // enough memory space. return; } + // Android CI/CD services do not have enough memory capacity for this + // test to work. Executing it will result in a permanent loop with the + // low memory killer daemon. +#ifdef __ANDROID__ + return; +#endif OK(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc)); OK(uc_mem_map(uc, mem_addr, mem_size, UC_PROT_ALL)); From 47bd239a1fbbed251c915763f6e389bd48535082 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 07:37:44 -0400 Subject: [PATCH 22/35] downgrade zig version to 0.14.0 again to ensure that pipeline can run through --- .github/workflows/zigbuild.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/zigbuild.yml b/.github/workflows/zigbuild.yml index 34037a5c8e..ae39dd730e 100644 --- a/.github/workflows/zigbuild.yml +++ b/.github/workflows/zigbuild.yml @@ -28,7 +28,7 @@ jobs: fetch-depth: 0 - uses: mlugg/setup-zig@v1 with: - version: 0.15.0 + version: 0.14.0 - uses: lukka/get-cmake@latest with: cmakeVersion: latest @@ -52,7 +52,7 @@ jobs: fetch-depth: 0 - uses: mlugg/setup-zig@v1 with: - version: 0.15.0 + version: 0.14.0 - uses: lukka/get-cmake@latest with: cmakeVersion: latest From 8714b872a035d48da2922a4b252b5fca4347db86 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 07:41:05 -0400 Subject: [PATCH 23/35] adjust rust mmio_unwrap type to use u64 --- bindings/rust/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 862a8957df..a1ff333a9b 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -431,7 +431,7 @@ impl<'a, D> Unicorn<'a, D> { .and_then(|| { let rd = read_data.map(|c| c as Box); let wd = write_data.map(|c| c as Box); - let u64_size : u64 = size.try_into.unwrap(); + let u64_size : u64 = size.try_into().unwrap(); self.inner_mut().mmio_callbacks.push(MmioCallbackScope { regions: vec![(address, u64_size)], read_callback: rd, @@ -494,7 +494,7 @@ impl<'a, D> Unicorn<'a, D> { err.into() } - fn mmio_unmap(&mut self, address: u64, size: libc::size_t) { + fn mmio_unmap(&mut self, address: u64, size: u64) { for scope in self.inner_mut().mmio_callbacks.iter_mut() { scope.unmap(address, size); } From 8a5673d4a154ea2159735b1c28da536b9e386ed9 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 07:56:52 -0400 Subject: [PATCH 24/35] change ffi size type of uc_mem_map_ptr into u64 --- bindings/rust/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index a1ff333a9b..6a66fb02d7 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -357,7 +357,7 @@ impl<'a, D> Unicorn<'a, D> { pub unsafe fn mem_map_ptr( &mut self, address: u64, - size: usize, + size: u64, perms: Permission, ptr: *mut c_void, ) -> Result<(), uc_error> { From 448ea881ffbe3cdf6bc815fb462ce2a0f0972c80 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 08:02:14 -0400 Subject: [PATCH 25/35] add warning to rust slicing --- bindings/rust/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 6a66fb02d7..30b2dee80f 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -332,7 +332,14 @@ impl<'a, D> Unicorn<'a, D> { /// Return a range of bytes from memory at the specified emulated physical address as vector. pub fn mem_read_as_vec(&self, address: u64, size: u64) -> Result, uc_error> { - let mut buf = vec![0; size]; + if size <= usize::MAX as u64 { + // Necessary because of the rust type of vec![] + // can only handle usize types as argument. + // Type coercion using try_into().unwrap() therefore + // would supress the addresses larger >= usize::MAX + panic!("mem_read_as_vec can only be used with size <= usize::MAX"); + } + let mut buf = vec![0; size.try_into().unwrap()]; unsafe { ffi::uc_mem_read(self.get_handle(), address, buf.as_mut_ptr(), size.try_into().unwrap()) }.and(Ok(buf)) } From 189ffb2021acb65fa39e8ba7ee6767c65c15738d Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 08:06:21 -0400 Subject: [PATCH 26/35] return read_mem_as_vec to earlier state, leave usize as argument because there cannot be larger vec![] anyway --- bindings/rust/src/lib.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 30b2dee80f..3cb8459c20 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -331,15 +331,8 @@ impl<'a, D> Unicorn<'a, D> { } /// Return a range of bytes from memory at the specified emulated physical address as vector. - pub fn mem_read_as_vec(&self, address: u64, size: u64) -> Result, uc_error> { - if size <= usize::MAX as u64 { - // Necessary because of the rust type of vec![] - // can only handle usize types as argument. - // Type coercion using try_into().unwrap() therefore - // would supress the addresses larger >= usize::MAX - panic!("mem_read_as_vec can only be used with size <= usize::MAX"); - } - let mut buf = vec![0; size.try_into().unwrap()]; + pub fn mem_read_as_vec(&self, address: u64, size: usize) -> Result, uc_error> { + let mut buf = vec![0; size]; unsafe { ffi::uc_mem_read(self.get_handle(), address, buf.as_mut_ptr(), size.try_into().unwrap()) }.and(Ok(buf)) } From aad8200b67105c80ea645173ed16980fd5f7d248 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 08:34:31 -0400 Subject: [PATCH 27/35] adjust regions inside MmioCallbackScope to use u64 for region sizes --- bindings/rust/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 3cb8459c20..fb8d273138 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -131,7 +131,7 @@ impl Drop for Context { } pub struct MmioCallbackScope<'a> { - pub regions: Vec<(u64, usize)>, + pub regions: Vec<(u64, u64)>, pub read_callback: Option + 'a>>, pub write_callback: Option + 'a>>, } From 79574229587a8f1c8a84bf32a0e4471bcca3508e Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 08:52:26 -0400 Subject: [PATCH 28/35] adjust regions inside MmioCallbackScope to use u64 for region sizes inside search vec --- bindings/rust/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index fb8d273138..2aaff25da8 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -154,13 +154,13 @@ impl<'a> MmioCallbackScope<'a> { vec![(*b, *s)] } else if end >= e { // The unmapped region overlaps with the end of this region - vec![(*b, (begin - *b) as usize)] + vec![(*b, (begin - *b) as u64)] } else { // The unmapped region is in the middle of this region let second_b = end + 1; vec![ - (*b, (begin - *b) as usize), - (second_b, (e - second_b) as usize), + (*b, (begin - *b) as u64), + (second_b, (e - second_b) as u64), ] } } else if end > *b { @@ -169,7 +169,7 @@ impl<'a> MmioCallbackScope<'a> { vec![] } else { // The unmapped region overlaps with the start of this region - vec![(end, (e - end) as usize)] + vec![(end, (e - end) as u64)] } } else { // The unmapped region is completely before this region From 17535b43cdf31b342ae7bb5e8c9af76884efc221 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 10:23:02 -0400 Subject: [PATCH 29/35] finalize dotnet bindings inside IBinding.fs --- bindings/dotnet/UnicornEngine/Binding/IBinding.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs index b6c3edc09c..218f7b9100 100644 --- a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs +++ b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs @@ -17,10 +17,10 @@ type IBinding = abstract EmuStart : UIntPtr * UInt64 * UInt64 * UInt64 * UInt64 -> Int32 abstract EmuStop : UIntPtr -> Int32 abstract HookDel : UIntPtr * UIntPtr -> Int32 - abstract MemMap : UIntPtr * UInt64 * UIntPtr * UInt32 -> Int32 - abstract MemMapPtr : UIntPtr * UInt64 * UIntPtr * UInt32 * UIntPtr -> Int32 - abstract MemUnmap : UIntPtr * UInt64 * UIntPtr -> Int32 - abstract MemProtect : UIntPtr * UInt64 * UIntPtr * UInt32 -> Int32 + abstract MemMap : UIntPtr * UInt64 * UInt64 * UInt32 -> Int32 + abstract MemMapPtr : UIntPtr * UInt64 * UIn64 * UInt32 * UIntPtr -> Int32 + abstract MemUnmap : UIntPtr * UInt64 * UInt64 -> Int32 + abstract MemProtect : UIntPtr * UInt64 * UInt64 * UInt32 -> Int32 abstract HookAddNoarg : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * UInt64 * UInt64 -> Int32 abstract HookAddArg0 : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * UInt64 * UInt64 * Int32 -> Int32 abstract HookAddArg0Arg1 : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * UInt64 * UInt64 * UInt64 * UInt64 -> Int32 From 5cdfb51c2cbabcdbe1d622e166a5f9f1ddc00bb2 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 11:15:51 -0400 Subject: [PATCH 30/35] fix typo --- bindings/dotnet/UnicornEngine/Binding/IBinding.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs index 218f7b9100..c7eb11fd40 100644 --- a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs +++ b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs @@ -18,7 +18,7 @@ type IBinding = abstract EmuStop : UIntPtr -> Int32 abstract HookDel : UIntPtr * UIntPtr -> Int32 abstract MemMap : UIntPtr * UInt64 * UInt64 * UInt32 -> Int32 - abstract MemMapPtr : UIntPtr * UInt64 * UIn64 * UInt32 * UIntPtr -> Int32 + abstract MemMapPtr : UIntPtr * UInt64 * UInt64 * UInt32 * UIntPtr -> Int32 abstract MemUnmap : UIntPtr * UInt64 * UInt64 -> Int32 abstract MemProtect : UIntPtr * UInt64 * UInt64 * UInt32 -> Int32 abstract HookAddNoarg : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * UInt64 * UInt64 -> Int32 From aa87075b3ac7da83386edb9f5578dee57675781d Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 11:18:17 -0400 Subject: [PATCH 31/35] adjust types inside Unicorn.fs --- bindings/dotnet/UnicornEngine/Unicorn.fs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bindings/dotnet/UnicornEngine/Unicorn.fs b/bindings/dotnet/UnicornEngine/Unicorn.fs index 56a683b0b8..2a446d83a6 100644 --- a/bindings/dotnet/UnicornEngine/Unicorn.fs +++ b/bindings/dotnet/UnicornEngine/Unicorn.fs @@ -84,34 +84,34 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault()) - member this.MemMap(address: Int64, size: Int64, perm: Int32) = + member this.MemMap(address: Int64, size: UInt64, perm: Int32) = let size = new UIntPtr(uint64 size) match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with | Some e -> raise e | None -> () - member this.MemMapPtr(address: Int64, size: Int64, perm: Int32, ptr: IntPtr) = + member this.MemMapPtr(address: Int64, size: UInt64, perm: Int32, ptr: IntPtr) = let size = new UIntPtr(uint64 size) let ptr = new UIntPtr(ptr.ToPointer()) match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> checkResult with | Some e -> raise e | None -> () - member this.MemUnmap(address: Int64, size: Int64) = + member this.MemUnmap(address: Int64, size: UInt64) = let size = new UIntPtr(uint64 size) match binding.MemUnmap(_eng.[0], uint64 address, size) |> checkResult with | Some e -> raise e | None -> () - member this.MemProtect(address: Int64, size: Int64, ?perm: Int32) = + member this.MemProtect(address: Int64, size: UInt64, ?perm: Int32) = let size = new UIntPtr(uint64 size) let perm = defaultArg perm Common.UC_PROT_ALL match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with | Some e -> raise e | None -> () member this.MemWrite(address: Int64, value: Byte array) = - match binding.MemWrite(_eng.[0], uint64 address, value, new UIntPtr(uint32 value.Length)) |> checkResult with + match binding.MemWrite(_eng.[0], uint64 address, value, new UInt64(uint32 value.Length)) |> checkResult with | Some e -> raise e | None -> () member this.MemRead(address: Int64, memValue: Byte array) = - match binding.MemRead(_eng.[0], uint64 address, memValue, new UIntPtr(uint32 memValue.Length)) |> checkResult with + match binding.MemRead(_eng.[0], uint64 address, memValue, new UInt64(uint32 memValue.Length)) |> checkResult with | Some e -> raise e | None -> () member this.RegWrite(regId: Int32, value: Byte array) = From 769a49c92c9e70280517c5f7df70bb07dd288a88 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 6 Apr 2025 11:44:14 -0400 Subject: [PATCH 32/35] finalize type wrangling inside F# bindings, setting MemRead and MemWrite to correct types --- bindings/dotnet/UnicornEngine/Binding/IBinding.fs | 4 ++-- bindings/dotnet/UnicornEngine/Unicorn.fs | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs index c7eb11fd40..4870fc6b62 100644 --- a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs +++ b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs @@ -12,8 +12,8 @@ type IBinding = abstract Errono : UIntPtr -> Int32 abstract RegRead : UIntPtr * Int32 * Byte array -> Int32 abstract RegWrite : UIntPtr * Int32 * Byte array -> Int32 - abstract MemRead : UIntPtr * UInt64 * Byte array * UIntPtr -> Int32 - abstract MemWrite : UIntPtr * UInt64 * Byte array * UIntPtr -> Int32 + abstract MemRead : UIntPtr * UInt64 * Byte array * UInt64 -> Int32 + abstract MemWrite : UIntPtr * UInt64 * Byte array * UInt64 -> Int32 abstract EmuStart : UIntPtr * UInt64 * UInt64 * UInt64 * UInt64 -> Int32 abstract EmuStop : UIntPtr -> Int32 abstract HookDel : UIntPtr * UIntPtr -> Int32 diff --git a/bindings/dotnet/UnicornEngine/Unicorn.fs b/bindings/dotnet/UnicornEngine/Unicorn.fs index 2a446d83a6..335a25091a 100644 --- a/bindings/dotnet/UnicornEngine/Unicorn.fs +++ b/bindings/dotnet/UnicornEngine/Unicorn.fs @@ -85,33 +85,29 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault()) member this.MemMap(address: Int64, size: UInt64, perm: Int32) = - let size = new UIntPtr(uint64 size) match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with | Some e -> raise e | None -> () member this.MemMapPtr(address: Int64, size: UInt64, perm: Int32, ptr: IntPtr) = - let size = new UIntPtr(uint64 size) let ptr = new UIntPtr(ptr.ToPointer()) match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> checkResult with | Some e -> raise e | None -> () member this.MemUnmap(address: Int64, size: UInt64) = - let size = new UIntPtr(uint64 size) match binding.MemUnmap(_eng.[0], uint64 address, size) |> checkResult with | Some e -> raise e | None -> () member this.MemProtect(address: Int64, size: UInt64, ?perm: Int32) = - let size = new UIntPtr(uint64 size) let perm = defaultArg perm Common.UC_PROT_ALL match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with | Some e -> raise e | None -> () member this.MemWrite(address: Int64, value: Byte array) = - match binding.MemWrite(_eng.[0], uint64 address, value, new UInt64(uint32 value.Length)) |> checkResult with + match binding.MemWrite(_eng.[0], uint64 address, value, uint64 value.Length) |> checkResult with | Some e -> raise e | None -> () member this.MemRead(address: Int64, memValue: Byte array) = - match binding.MemRead(_eng.[0], uint64 address, memValue, new UInt64(uint32 memValue.Length)) |> checkResult with + match binding.MemRead(_eng.[0], uint64 address, memValue, uint64 memValue.Length) |> checkResult with | Some e -> raise e | None -> () member this.RegWrite(regId: Int32, value: Byte array) = From 758135ba08b939aa2b6ccff3bf6f695735677d92 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 13 Apr 2025 16:32:18 -0400 Subject: [PATCH 33/35] fix missing bracket inside bindings/rust/src/lib.rs --- bindings/rust/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index f0acd7d7b2..0b83c39cc8 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -297,7 +297,7 @@ impl<'a, D> Unicorn<'a, D> { /// Return a range of bytes from memory at the specified emulated physical address as vector. pub fn mem_read_as_vec(&self, address: u64, size: usize) -> Result, uc_error> { let mut buf = vec![0; size]; - unsafe { uc_mem_read(self.get_handle(), address, buf.as_mut_ptr().cast(), size.try_into().unwrap() } + unsafe { uc_mem_read(self.get_handle(), address, buf.as_mut_ptr().cast(), size.try_into().unwrap()); } .and(Ok(buf)) } From 1f25e8f479e69132abf3178d1cf7fc522837056c Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 13 Apr 2025 16:36:48 -0400 Subject: [PATCH 34/35] replace ffi interface to hook interface inside rust lib --- bindings/rust/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 0b83c39cc8..605ff1ba5a 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -89,8 +89,8 @@ impl Drop for Context { pub struct MmioCallbackScope<'a> { pub regions: Vec<(u64, u64)>, - pub read_callback: Option + 'a>>, - pub write_callback: Option + 'a>>, + pub read_callback: Option + 'a>>, + pub write_callback: Option + 'a>>, } impl MmioCallbackScope<'_> { From a353300467349d098a8dc37103da9a7327750da6 Mon Sep 17 00:00:00 2001 From: rliebig Date: Sun, 13 Apr 2025 16:57:04 -0400 Subject: [PATCH 35/35] fix testcases to use u64 for longer references --- bindings/rust/src/lib.rs | 4 ++-- bindings/rust/src/tests/ctl.rs | 6 +++--- bindings/rust/src/tests/m68k.rs | 6 ++++-- bindings/rust/src/tests/mem.rs | 2 +- bindings/rust/src/tests/mips.rs | 2 +- bindings/rust/src/tests/mod.rs | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 605ff1ba5a..7fd447537c 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -288,7 +288,7 @@ impl<'a, D> Unicorn<'a, D> { self.get_handle(), address, buf.as_mut_ptr().cast(), - buf.len().try_into.unwrap(), + buf.len().try_into().unwrap(), ) } .into() @@ -297,7 +297,7 @@ impl<'a, D> Unicorn<'a, D> { /// Return a range of bytes from memory at the specified emulated physical address as vector. pub fn mem_read_as_vec(&self, address: u64, size: usize) -> Result, uc_error> { let mut buf = vec![0; size]; - unsafe { uc_mem_read(self.get_handle(), address, buf.as_mut_ptr().cast(), size.try_into().unwrap()); } + unsafe { uc_mem_read(self.get_handle(), address, buf.as_mut_ptr().cast(), size.try_into().unwrap()) } .and(Ok(buf)) } diff --git a/bindings/rust/src/tests/ctl.rs b/bindings/rust/src/tests/ctl.rs index c10af73903..436f86795c 100644 --- a/bindings/rust/src/tests/ctl.rs +++ b/bindings/rust/src/tests/ctl.rs @@ -83,7 +83,7 @@ fn test_uc_ctl_tb_cache() { let code = [0x90; CODE_LEN]; // nop let mut uc = Unicorn::new(Arch::X86, Mode::MODE_32).unwrap(); - uc.mem_map(CODE_START, CODE_LEN, Prot::ALL).unwrap(); + uc.mem_map(CODE_START, CODE_LEN.try_into().unwrap(), Prot::ALL).unwrap(); uc.mem_write(CODE_START, &code).unwrap(); let standard = time_emulation(&mut uc, CODE_START, CODE_START + code.len() as u64); @@ -232,7 +232,7 @@ fn test_tlb_clear() { ]; let mut uc = Unicorn::new_with_data(Arch::X86, Mode::MODE_64, 0usize).unwrap(); - uc.mem_map(CODE_START, CODE_LEN, Prot::ALL).unwrap(); + uc.mem_map(CODE_START, CODE_LEN.try_into().unwrap(), Prot::ALL).unwrap(); uc.mem_write(CODE_START, code).unwrap(); uc.mem_map(0x200000, 0x1000, Prot::ALL).unwrap(); @@ -271,7 +271,7 @@ fn test_noexec() { uc.mem_write(CODE_START, code).unwrap(); uc.ctl_set_tlb_type(TlbType::VIRTUAL).unwrap(); - uc.mem_protect(CODE_START, CODE_START as usize + 0x1000, Prot::EXEC) + uc.mem_protect(CODE_START, CODE_START as u64 + 0x1000, Prot::EXEC) .unwrap(); let err = uc diff --git a/bindings/rust/src/tests/m68k.rs b/bindings/rust/src/tests/m68k.rs index 4a7fcca0cf..a6f14e063d 100644 --- a/bindings/rust/src/tests/m68k.rs +++ b/bindings/rust/src/tests/m68k.rs @@ -28,8 +28,10 @@ fn test_sr_contains_flags() { ]; let mut uc = uc_common_setup(Arch::M68K, Mode::BIG_ENDIAN, None, &code, ()); - - uc.emu_start(CODE_START, CODE_START + code.len() as u64, 0, 0) + let code_start_u64 : usize = CODE_START.try_into().unwrap(); + let code_len_u64 : usize= code.len().try_into().unwrap(); + let code_len_addition : usize = code_start_u64 + code_len_u64; + uc.emu_start(CODE_START, code_len_addition.try_into().unwrap(), 0, 0) .unwrap(); let d3 = uc.reg_read(RegisterM68K::D3).unwrap(); diff --git a/bindings/rust/src/tests/mem.rs b/bindings/rust/src/tests/mem.rs index a17b760fde..3a34010f11 100644 --- a/bindings/rust/src/tests/mem.rs +++ b/bindings/rust/src/tests/mem.rs @@ -161,7 +161,7 @@ fn test_map_big_memory() { let mut uc = Unicorn::new(Arch::X86, Mode::MODE_64).unwrap(); let requested_size = !(page_size::get() - 1); assert_eq!( - uc.mem_map(0x0, requested_size, Prot::ALL), + uc.mem_map(0x0, requested_size.try_into().unwrap(), Prot::ALL), Err(uc_error::NOMEM) ); } diff --git a/bindings/rust/src/tests/mips.rs b/bindings/rust/src/tests/mips.rs index 288ffa80b8..da4e4ed598 100644 --- a/bindings/rust/src/tests/mips.rs +++ b/bindings/rust/src/tests/mips.rs @@ -3,7 +3,7 @@ use unicorn_engine_sys::RegisterMIPS; use super::*; const CODE_START: u64 = 0x10000000; -const CODE_LEN: usize = 0x4000; +const CODE_LEN: u64 = 0x4000; fn uc_common_setup( arch: Arch, diff --git a/bindings/rust/src/tests/mod.rs b/bindings/rust/src/tests/mod.rs index cc5b9488bb..463776760f 100644 --- a/bindings/rust/src/tests/mod.rs +++ b/bindings/rust/src/tests/mod.rs @@ -20,7 +20,7 @@ mod s390x; use crate::{Arch, HookType, Mode, Prot, TlbEntry, TlbType, Unicorn, uc_error}; pub const CODE_START: u64 = 0x1000; -pub const CODE_LEN: usize = 0x4000; +pub const CODE_LEN: u64 = 0x4000; fn uc_common_setup( arch: Arch,