From 810054ca6daea6dee2682852ad58a341b45cf077 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 29 Aug 2015 10:23:53 +0800 Subject: [PATCH 1/2] uc_mem_read() & uc_mem_write() now can work on adjacent memory areas. this fixes issue #38 --- regress/memmap_segfault2.py | 2 +- uc.c | 86 ++++++++++++++++++++++++++++++------- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/regress/memmap_segfault2.py b/regress/memmap_segfault2.py index 1c077ac6..bd3845b7 100755 --- a/regress/memmap_segfault2.py +++ b/regress/memmap_segfault2.py @@ -5,4 +5,4 @@ uc = Uc(UC_ARCH_X86, UC_MODE_32) uc.mem_map(0x0000, 0x2000) uc.mem_map(0x2000, 0x4000) uc.mem_write(0x1000, 0x1004 * ' ') -print 'Not reached on x86_64 Linux.' +print 'If not reached, then we have BUG (crash on x86_64 Linux).' diff --git a/uc.c b/uc.c index 567d66dd..faf8439e 100644 --- a/uc.c +++ b/uc.c @@ -340,6 +340,26 @@ uc_err uc_reg_write(uch handle, int regid, const void *value) } +// check if a memory area is mapped +// this is complicated because an area can overlap adjacent blocks +static bool check_mem_area(struct uc_struct *uc, uint64_t address, size_t size) +{ + size_t count = 0, len; + + while(count < size) { + MemoryRegion *mr = memory_mapping(uc, address); + if (mr) { + len = MIN(size - count, mr->end - address); + count += len; + address += len; + } else // this address is not mapped in yet + break; + } + + return (count == size); +} + + UNICORN_EXPORT uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size) { @@ -349,39 +369,73 @@ uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size) // invalid handle return UC_ERR_UCH; - if (uc->read_mem(&uc->as, address, bytes, size) == false) + if (!check_mem_area(uc, address, size)) return UC_ERR_MEM_READ; - return UC_ERR_OK; + size_t count = 0, len; + + // memory area can overlap adjacent memory blocks + while(count < size) { + MemoryRegion *mr = memory_mapping(uc, address); + if (mr) { + len = MIN(size - count, mr->end - address); + if (uc->read_mem(&uc->as, address, bytes, len) == false) + break; + count += len; + address += len; + bytes += len; + } else // this address is not mapped in yet + break; + } + + if (count == size) + return UC_ERR_OK; + else + return UC_ERR_MEM_READ; } UNICORN_EXPORT uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size) { struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle; - uint32_t operms; if (handle == 0) // invalid handle return UC_ERR_UCH; - MemoryRegion *mr = memory_mapping(uc, address); - if (mr == NULL) + if (!check_mem_area(uc, address, size)) return UC_ERR_MEM_WRITE; - operms = mr->perms; - if (!(operms & UC_PROT_WRITE)) //write protected - //but this is not the program accessing memory, so temporarily mark writable - uc->readonly_mem(mr, false); + size_t count = 0, len; - if (uc->write_mem(&uc->as, address, bytes, size) == false) + // memory area can overlap adjacent memory blocks + while(count < size) { + MemoryRegion *mr = memory_mapping(uc, address); + if (mr) { + uint32_t operms = mr->perms; + if (!(operms & UC_PROT_WRITE)) // write protected + // but this is not the program accessing memory, so temporarily mark writable + uc->readonly_mem(mr, false); + + len = MIN(size - count, mr->end - address); + if (uc->write_mem(&uc->as, address, bytes, len) == false) + break; + + if (!(operms & UC_PROT_WRITE)) // write protected + // now write protect it again + uc->readonly_mem(mr, true); + + count += len; + address += len; + bytes += len; + } else // this address is not mapped in yet + break; + } + + if (count == size) + return UC_ERR_OK; + else return UC_ERR_MEM_WRITE; - - if (!(operms & UC_PROT_WRITE)) //write protected - //now write protect it again - uc->readonly_mem(mr, true); - - return UC_ERR_OK; } #define TIMEOUT_STEP 2 // microseconds From 6d71b970d3c77d6d21857c86d9841f9b6c146edd Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 29 Aug 2015 10:33:00 +0800 Subject: [PATCH 2/2] fix a constant in regress/ro_mem_test.c --- regress/ro_mem_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regress/ro_mem_test.c b/regress/ro_mem_test.c index 38e84cd0..576cac01 100644 --- a/regress/ro_mem_test.c +++ b/regress/ro_mem_test.c @@ -82,7 +82,7 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, printf(">>> Missing memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", address, size, value); return false; - case UC_MEM_WRITE_NR: + case UC_MEM_WRITE_NW: printf(">>> RO memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", address, size, value); return false;