diff --git a/bindings/go/unicorn/unicorn.go b/bindings/go/unicorn/unicorn.go index ca210c43..a9aeca2d 100644 --- a/bindings/go/unicorn/unicorn.go +++ b/bindings/go/unicorn/unicorn.go @@ -28,7 +28,7 @@ func errReturn(err C.uc_err) error { type Unicorn interface { MemMap(addr, size uint64) error MemMapProt(addr, size uint64, prot int) error - MemMapPtr(addr, size uint64, ptr unsafe.Pointer) error + MemMapPtr(addr, size uint64, prot int, ptr unsafe.Pointer) error MemUnmap(addr, size uint64) error MemRead(addr, size uint64) ([]byte, error) MemReadInto(dst []byte, addr uint64) error @@ -129,8 +129,8 @@ func (u *uc) MemMap(addr, size uint64) error { return u.MemMapProt(addr, size, PROT_ALL) } -func (u *uc) MemMapPtr(addr, size uint64, ptr unsafe.Pointer) error { - return errReturn(C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.size_t(size), ptr)) +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)) } func (u *uc) MemUnmap(addr, size uint64) error { diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index 2ccb02ae..08be9632 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -104,7 +104,7 @@ _setup_prototype(_uc, "uc_emu_start", ucerr, uc_engine, ctypes.c_uint64, ctypes. _setup_prototype(_uc, "uc_emu_stop", ucerr, uc_engine) _setup_prototype(_uc, "uc_hook_del", ucerr, uc_engine, uc_hook_h) _setup_prototype(_uc, "uc_mem_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32) -_setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) +_setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p) _setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t) _setup_prototype(_uc, "uc_mem_protect", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32) @@ -243,8 +243,8 @@ class Uc(object): # map a range of memory from a raw host memory address - def mem_map_ptr(self, address, size, ptr): - status = _uc.uc_mem_map_ptr(self._uch, address, size, ptr) + def mem_map_ptr(self, address, size, perms, ptr): + status = _uc.uc_mem_map_ptr(self._uch, address, size, perms, ptr) if status != UC_ERR_OK: raise UcError(status) diff --git a/include/uc_priv.h b/include/uc_priv.h index c24a21f9..5cdf6557 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -48,7 +48,7 @@ typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr); typedef MemoryRegion* (*uc_args_uc_ram_size_t)(struct uc_struct*, ram_addr_t begin, size_t size, uint32_t perms); -typedef MemoryRegion* (*uc_args_uc_ram_size_ptr_t)(struct uc_struct*, ram_addr_t begin, size_t size, void *ptr); +typedef MemoryRegion* (*uc_args_uc_ram_size_ptr_t)(struct uc_struct*, ram_addr_t begin, size_t size, uint32_t perms, void *ptr); typedef void (*uc_mem_unmap_t)(struct uc_struct*, MemoryRegion *mr); diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 561e48b6..719cbcf6 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -455,14 +455,18 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. @size: size of the new memory region to be mapped in. This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. - @ptr: pointer to host memory backing the newly mapped memory. Existing host - memory permissions are preserved. + @perms: Permissions for the newly mapped region. + This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, + or this will return with UC_ERR_ARG error. + @ptr: pointer to host memory backing the newly mapped memory. This host memory is + expected to be an equal or larger size than provided, and be mapped with at + least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, void *ptr); +uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr); /* Unmap a region of emulation memory. diff --git a/qemu/include/exec/memory.h b/qemu/include/exec/memory.h index b6f7d1b3..3a707522 100644 --- a/qemu/include/exec/memory.h +++ b/qemu/include/exec/memory.h @@ -939,7 +939,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, void memory_register_types(struct uc_struct *uc); MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms); -MemoryRegion *memory_map_ptr(struct uc_struct *uc, ram_addr_t begin, size_t size, void *ptr); +MemoryRegion *memory_map_ptr(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms, void *ptr); void memory_unmap(struct uc_struct *uc, MemoryRegion *mr); int memory_free(struct uc_struct *uc); diff --git a/qemu/memory.c b/qemu/memory.c index 36672f9b..2d2e21a4 100644 --- a/qemu/memory.c +++ b/qemu/memory.c @@ -48,12 +48,12 @@ MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, ui return ram; } -MemoryRegion *memory_map_ptr(struct uc_struct *uc, ram_addr_t begin, size_t size, void *ptr) +MemoryRegion *memory_map_ptr(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms, void *ptr) { MemoryRegion *ram = g_new(MemoryRegion, 1); memory_region_init_ram_ptr(uc, ram, NULL, "pc.ram", size, ptr); - ram->perms = UC_PROT_ALL; + ram->perms = perms; if (ram->ram_addr == -1) // out of memory return NULL; diff --git a/samples/sample_x86.c b/samples/sample_x86.c index c5fb540c..910af989 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -256,7 +256,7 @@ static void test_i386_map_ptr(void) return; } - uc_mem_map_ptr(uc, ADDRESS, 2 * 1024 * 1024, mem); + uc_mem_map_ptr(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL, mem); // write machine code to be emulated to memory if (!memcpy(mem, X86_CODE32, sizeof(X86_CODE32) - 1)) { diff --git a/tests/unit/test_mem_map_ptr.c b/tests/unit/test_mem_map_ptr.c index 1b91211f..fff4e6c7 100644 --- a/tests/unit/test_mem_map_ptr.c +++ b/tests/unit/test_mem_map_ptr.c @@ -45,7 +45,7 @@ static void test_basic(void **state) void *host_mem = calloc(1, mem_len); /* Map a region */ - uc_assert_success(uc_mem_map_ptr(uc, mem_start, mem_len, host_mem)); + uc_assert_success(uc_mem_map_ptr(uc, mem_start, mem_len, UC_PROT_ALL, host_mem)); /* Write some data to it */ uc_assert_success(uc_mem_write(uc, test_addr, "test", 4)); diff --git a/uc.c b/uc.c index 25ff1fb9..603cf068 100644 --- a/uc.c +++ b/uc.c @@ -616,12 +616,12 @@ 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, void *ptr) +uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr) { if (ptr == NULL) return UC_ERR_ARG; - return mem_map(uc, address, size, UC_PROT_ALL, uc->memory_map_ptr(uc, address, size, ptr)); + return mem_map(uc, address, size, UC_PROT_ALL, uc->memory_map_ptr(uc, address, size, perms, ptr)); } // Create a backup copy of the indicated MemoryRegion.