diff --git a/.github/workflows/zigbuild.yml b/.github/workflows/zigbuild.yml index 810e24f646..ae39dd730e 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.14.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.14.0 - uses: lukka/get-cmake@latest with: cmakeVersion: latest diff --git a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs index b6c3edc09c..4870fc6b62 100644 --- a/bindings/dotnet/UnicornEngine/Binding/IBinding.fs +++ b/bindings/dotnet/UnicornEngine/Binding/IBinding.fs @@ -12,15 +12,15 @@ 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 - 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 * 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 abstract HookAddArg0 : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * UInt64 * UInt64 * Int32 -> Int32 abstract HookAddArg0Arg1 : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * UInt64 * UInt64 * UInt64 * UInt64 -> Int32 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/dotnet/UnicornEngine/Unicorn.fs b/bindings/dotnet/UnicornEngine/Unicorn.fs index 56a683b0b8..335a25091a 100644 --- a/bindings/dotnet/UnicornEngine/Unicorn.fs +++ b/bindings/dotnet/UnicornEngine/Unicorn.fs @@ -84,34 +84,30 @@ 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) = - let size = new UIntPtr(uint64 size) + member this.MemMap(address: Int64, size: UInt64, perm: Int32) = 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) = - let size = new UIntPtr(uint64 size) + member this.MemMapPtr(address: Int64, size: UInt64, perm: Int32, ptr: IntPtr) = 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) = - let size = new UIntPtr(uint64 size) + member this.MemUnmap(address: Int64, size: UInt64) = match binding.MemUnmap(_eng.[0], uint64 address, size) |> checkResult with | Some e -> raise e | None -> () - member this.MemProtect(address: Int64, size: Int64, ?perm: Int32) = - let size = new UIntPtr(uint64 size) + member this.MemProtect(address: Int64, size: UInt64, ?perm: Int32) = 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, 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 UIntPtr(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) = 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) { 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 diff --git a/bindings/java/unicorn_Unicorn.c b/bindings/java/unicorn_Unicorn.c index 61cf93ba09..739ca36c2c 100644 --- a/bindings/java/unicorn_Unicorn.c +++ b/bindings/java/unicorn_Unicorn.c @@ -758,9 +758,9 @@ 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); + 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/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() 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) 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)); } diff --git a/bindings/rust/src/ffi.rs b/bindings/rust/src/ffi.rs new file mode 100644 index 0000000000..7d5132cafe --- /dev/null +++ b/bindings/rust/src/ffi.rs @@ -0,0 +1,297 @@ +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +use crate::{Unicorn, UnicornInner}; + +use super::unicorn_const::{uc_error, Arch, HookType, MemRegion, MemType, Mode, Query, TlbEntry}; +use alloc::rc::Weak; +use core::cell::UnsafeCell; +use core::ffi::c_void; +use libc::{c_char, c_int}; + +pub type uc_handle = *mut c_void; +// TODO: Use c_size_t as soon as it is stable. The c api exposes uc_hook as size_t +pub type uc_hook = *mut c_void; +pub type uc_context = *mut c_void; + +extern "C" { + pub fn uc_version(major: *mut u32, minor: *mut u32) -> u32; + pub fn uc_arch_supported(arch: Arch) -> bool; + pub fn uc_open(arch: Arch, mode: Mode, engine: *mut uc_handle) -> uc_error; + pub fn uc_close(engine: uc_handle) -> uc_error; + pub fn uc_context_free(mem: uc_context) -> uc_error; + pub fn uc_errno(engine: uc_handle) -> uc_error; + pub fn uc_strerror(error_code: uc_error) -> *const c_char; + pub fn uc_reg_write(engine: uc_handle, regid: c_int, value: *const c_void) -> uc_error; + pub fn uc_reg_write_batch( + engine: uc_handle, + regids: *const c_int, + values: *const *const c_void, + count: c_int, + ) -> uc_error; + pub fn uc_reg_read(engine: uc_handle, regid: c_int, value: *mut c_void) -> uc_error; + pub fn uc_reg_read_batch( + engine: uc_handle, + regids: *const c_int, + values: *const *mut c_void, + count: c_int, + ) -> uc_error; + pub fn uc_mem_write( + engine: uc_handle, + address: u64, + bytes: *const u8, + size: u64, + ) -> uc_error; + pub fn uc_mem_read( + engine: uc_handle, + address: u64, + bytes: *mut u8, + size: u64, + ) -> 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: u64, + perms: u32, + ptr: *mut c_void, + ) -> uc_error; + pub fn uc_mmio_map( + engine: uc_handle, + address: u64, + 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: u64) -> uc_error; + pub fn uc_mem_protect( + engine: uc_handle, + address: u64, + size: u64, + perms: u32, + ) -> uc_error; + pub fn uc_mem_regions( + engine: uc_handle, + regions: *const *const MemRegion, + count: *mut u32, + ) -> uc_error; + pub fn uc_emu_start( + engine: uc_handle, + begin: u64, + until: u64, + timeout: u64, + count: libc::size_t, + ) -> uc_error; + pub fn uc_emu_stop(engine: uc_handle) -> uc_error; + pub fn uc_hook_add( + engine: uc_handle, + hook: *mut uc_hook, + hook_type: HookType, + callback: *mut c_void, + user_data: *mut c_void, + begin: u64, + end: u64, + ... + ) -> uc_error; + pub fn uc_hook_del(engine: uc_handle, hook: uc_hook) -> uc_error; + pub fn uc_query(engine: uc_handle, query_type: Query, result: *mut libc::size_t) -> uc_error; + pub fn uc_context_alloc(engine: uc_handle, context: *mut uc_context) -> uc_error; + pub fn uc_context_save(engine: uc_handle, context: uc_context) -> uc_error; + pub fn uc_context_restore(engine: uc_handle, context: uc_context) -> uc_error; + pub fn uc_ctl(engine: uc_handle, control: u32, ...) -> uc_error; +} + +pub struct UcHook<'a, D: 'a, F: 'a> { + pub callback: F, + pub uc: Weak>>, +} + +pub trait IsUcHook<'a> {} + +impl<'a, D, F> IsUcHook<'a> for UcHook<'a, D, F> {} + +pub unsafe extern "C" fn mmio_read_callback_proxy( + uc: uc_handle, + offset: u64, + size: usize, + user_data: *mut UcHook, +) -> u64 +where + F: FnMut(&mut crate::Unicorn, u64, usize) -> u64, +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, offset, size) +} + +pub unsafe extern "C" fn mmio_write_callback_proxy( + uc: uc_handle, + offset: u64, + size: usize, + value: u64, + user_data: *mut UcHook, +) where + F: FnMut(&mut crate::Unicorn, u64, usize, u64), +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, offset, size, value); +} + +pub unsafe extern "C" fn code_hook_proxy( + uc: uc_handle, + address: u64, + size: u32, + user_data: *mut UcHook, +) where + F: FnMut(&mut crate::Unicorn, u64, u32), +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, address, size); +} + +pub unsafe extern "C" fn block_hook_proxy( + uc: uc_handle, + address: u64, + size: u32, + user_data: *mut UcHook, +) where + F: FnMut(&mut crate::Unicorn, u64, u32), +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, address, size); +} + +pub unsafe extern "C" fn mem_hook_proxy( + uc: uc_handle, + mem_type: MemType, + address: u64, + size: u32, + value: i64, + user_data: *mut UcHook, +) -> bool +where + F: FnMut(&mut crate::Unicorn, MemType, u64, usize, i64) -> bool, +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, mem_type, address, size as usize, value) +} + +pub unsafe extern "C" fn intr_hook_proxy( + uc: uc_handle, + value: u32, + user_data: *mut UcHook, +) where + F: FnMut(&mut crate::Unicorn, u32), +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, value); +} + +pub unsafe extern "C" fn insn_in_hook_proxy( + uc: uc_handle, + port: u32, + size: usize, + user_data: *mut UcHook, +) -> u32 +where + F: FnMut(&mut crate::Unicorn, u32, usize) -> u32, +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, port, size) +} + +pub unsafe extern "C" fn insn_invalid_hook_proxy( + uc: uc_handle, + user_data: *mut UcHook, +) -> bool +where + F: FnMut(&mut crate::Unicorn) -> bool, +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc) +} + +pub unsafe extern "C" fn insn_out_hook_proxy( + uc: uc_handle, + port: u32, + size: usize, + value: u32, + user_data: *mut UcHook, +) where + F: FnMut(&mut crate::Unicorn, u32, usize, u32), +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc, port, size, value); +} + +pub unsafe extern "C" fn insn_sys_hook_proxy(uc: uc_handle, user_data: *mut UcHook) +where + F: FnMut(&mut crate::Unicorn), +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + (user_data.callback)(&mut user_data_uc); +} + +pub unsafe extern "C" fn tlb_lookup_hook_proxy( + uc: uc_handle, + vaddr: u64, + mem_type: MemType, + result: *mut TlbEntry, + user_data: *mut UcHook, +) -> bool +where + F: FnMut(&mut crate::Unicorn, u64, MemType) -> Option, +{ + let user_data = &mut *user_data; + let mut user_data_uc = Unicorn { + inner: user_data.uc.upgrade().unwrap(), + }; + debug_assert_eq!(uc, user_data_uc.get_handle()); + let r = (user_data.callback)(&mut user_data_uc, vaddr, mem_type); + if let Some(ref e) = r { + let ref_result: &mut TlbEntry = &mut *result; + *ref_result = *e; + }; + r.is_some() +} diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 775e9172b8..7fd447537c 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -88,7 +88,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>>, } @@ -98,8 +98,8 @@ impl MmioCallbackScope<'_> { !self.regions.is_empty() } - fn unmap(&mut self, begin: u64, size: usize) { - let end = begin + size as u64; + fn unmap(&mut self, begin: u64, size: u64) { + let end: u64 = begin + size as u64; self.regions = self .regions .iter() @@ -111,13 +111,13 @@ impl MmioCallbackScope<'_> { 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 { @@ -126,7 +126,7 @@ impl MmioCallbackScope<'_> { 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 @@ -288,7 +288,7 @@ impl<'a, D> Unicorn<'a, D> { self.get_handle(), address, buf.as_mut_ptr().cast(), - buf.len(), + 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) } + unsafe { uc_mem_read(self.get_handle(), address, buf.as_mut_ptr().cast(), size.try_into().unwrap()) } .and(Ok(buf)) } @@ -308,7 +308,7 @@ impl<'a, D> Unicorn<'a, D> { self.get_handle(), address, bytes.as_ptr().cast(), - bytes.len(), + bytes.len().try_into().unwrap(), ) } .into() @@ -330,7 +330,7 @@ impl<'a, D> Unicorn<'a, D> { pub unsafe fn mem_map_ptr( &mut self, address: u64, - size: usize, + size: u64, perms: Prot, ptr: *mut c_void, ) -> Result<(), uc_error> { @@ -341,7 +341,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_map(&mut self, address: u64, size: usize, perms: Prot) -> Result<(), uc_error> { + pub fn mem_map(&mut self, address: u64, size: u64, perms: Prot) -> Result<(), uc_error> { unsafe { uc_mem_map(self.get_handle(), address, size, perms.0 as _) }.into() } @@ -352,7 +352,7 @@ impl<'a, D> Unicorn<'a, D> { pub fn mmio_map( &mut self, address: u64, - size: usize, + size: u64, read_callback: Option, write_callback: Option, ) -> Result<(), uc_error> @@ -400,10 +400,11 @@ impl<'a, D> Unicorn<'a, D> { ) } .and_then(|| { + let u64_size : u64 = size.try_into().unwrap(); let rd = read_data.map(|c| c as Box); let wd = write_data.map(|c| c as Box); self.inner_mut().mmio_callbacks.push(MmioCallbackScope { - regions: vec![(address, size)], + regions: vec![(address, u64_size)], read_callback: rd, write_callback: wd, }); @@ -416,7 +417,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 mmio_map_ro(&mut self, address: u64, size: usize, callback: F) -> Result<(), uc_error> + pub fn mmio_map_ro(&mut self, address: u64, size: u64, callback: F) -> Result<(), uc_error> where F: FnMut(&mut Unicorn, u64, usize) -> u64 + 'a, { @@ -432,7 +433,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 mmio_map_wo(&mut self, address: u64, size: usize, callback: F) -> Result<(), uc_error> + pub fn mmio_map_wo(&mut self, address: u64, size: u64, callback: F) -> Result<(), uc_error> where F: FnMut(&mut Unicorn, u64, usize, u64) + 'a, { @@ -448,13 +449,13 @@ 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: usize) -> Result<(), uc_error> { + pub fn mem_unmap(&mut self, address: u64, size: u64) -> Result<(), uc_error> { let err = unsafe { uc_mem_unmap(self.get_handle(), address, size) }; self.mmio_unmap(address, size); err.into() } - fn mmio_unmap(&mut self, address: u64, size: usize) { + fn mmio_unmap(&mut self, address: u64, size: u64) { for scope in &mut self.inner_mut().mmio_callbacks { scope.unmap(address, size); } @@ -467,7 +468,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_protect(&mut self, address: u64, size: usize, perms: Prot) -> Result<(), uc_error> { + pub fn mem_protect(&mut self, address: u64, size: u64, perms: Prot) -> Result<(), uc_error> { unsafe { uc_mem_protect(self.get_handle(), address, size, perms.0 as _) }.into() } 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, 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 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 { 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 = .{""}, } diff --git a/include/uc_priv.h b/include/uc_priv.h index 9785e82467..a74a554d07 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, diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 5521262e8e..7e33e1b1bc 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,8 @@ 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 +1085,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 +1108,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 +1128,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 +1149,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); /* 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); } diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 6e3056ffb1..7262f25a76 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -449,6 +449,85 @@ static void test_snapshot_unmap(void) 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; + } + // 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)); + + 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}, {"test_mem_protect", test_mem_protect}, @@ -464,4 +543,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}}; 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 bf8cb8b462..2ea169074e 100644 --- a/uc.c +++ b/uc.c @@ -746,15 +746,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 @@ -778,19 +778,13 @@ 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); - // 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; @@ -824,19 +818,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; @@ -1230,7 +1218,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) { @@ -1238,7 +1226,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; } @@ -1267,7 +1255,8 @@ 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; @@ -1285,7 +1274,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; @@ -1309,7 +1298,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) { @@ -1335,10 +1324,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; @@ -1354,10 +1343,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; @@ -1384,7 +1373,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; } @@ -1398,9 +1387,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, @@ -1443,12 +1432,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; @@ -1498,7 +1487,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; } @@ -1519,9 +1508,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 @@ -1589,13 +1578,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); @@ -1689,7 +1678,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,11 +1701,11 @@ 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; - size_t count, len; + uint64_t count, len; UC_INIT(uc);