From 2da46caef72905ae4c3b5beaf7f21ca76ad543e6 Mon Sep 17 00:00:00 2001 From: Chris Eagle Date: Thu, 3 Sep 2015 12:26:36 -0700 Subject: [PATCH] smooth out split_region related code --- qemu/memory.c | 11 +++++++++ samples/mem_exec.c | 4 +-- samples/mem_protect.c | 4 +-- samples/mem_unmap.c | 4 +-- uc.c | 57 ++++++++++++++----------------------------- 5 files changed, 35 insertions(+), 45 deletions(-) diff --git a/qemu/memory.c b/qemu/memory.c index e04d59b7..be7933d5 100644 --- a/qemu/memory.c +++ b/qemu/memory.c @@ -47,6 +47,7 @@ MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, ui void memory_unmap(struct uc_struct *uc, MemoryRegion *mr) { + int i; target_ulong addr; //make sure all pages associated with the MemoryRegion are flushed for (addr = mr->addr; addr < mr->end; addr += uc->target_page_size) { @@ -54,6 +55,16 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr) } mr->enabled = false; memory_region_del_subregion(get_system_memory(uc), mr); + + for (i = 0; i < uc->mapped_block_count; i++) { + if (uc->mapped_blocks[i] == mr) { + uc->mapped_block_count--; + //shift remainder of array down over deleted pointer + memcpy(&uc->mapped_blocks[i], &uc->mapped_blocks[i + 1], sizeof(MemoryRegion*) * (uc->mapped_block_count - i)); + break; + } + } + g_free(mr); } diff --git a/samples/mem_exec.c b/samples/mem_exec.c index 370fd1ea..19153b46 100644 --- a/samples/mem_exec.c +++ b/samples/mem_exec.c @@ -204,7 +204,7 @@ int main(int argc, char **argv, char **envp) printf("ok %d - Program written to memory\n", log_num++); } - if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); return 6; } else { @@ -212,7 +212,7 @@ int main(int argc, char **argv, char **envp) } // intercept memory write events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); return 7; } else { diff --git a/samples/mem_protect.c b/samples/mem_protect.c index 5739563e..d9644d51 100644 --- a/samples/mem_protect.c +++ b/samples/mem_protect.c @@ -212,7 +212,7 @@ int main(int argc, char **argv, char **envp) printf("ok %d - Program written to memory\n", log_num++); } - if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); return 5; } else { @@ -220,7 +220,7 @@ int main(int argc, char **argv, char **envp) } // intercept memory write events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); return 6; } else { diff --git a/samples/mem_unmap.c b/samples/mem_unmap.c index b31bf220..e35b95ba 100644 --- a/samples/mem_unmap.c +++ b/samples/mem_unmap.c @@ -207,7 +207,7 @@ int main(int argc, char **argv, char **envp) printf("ok %d - Program written to memory\n", log_num++); } - if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); return 5; } else { @@ -215,7 +215,7 @@ int main(int argc, char **argv, char **envp) } // intercept memory write events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); return 6; } else { diff --git a/uc.c b/uc.c index 099af362..eaf1219a 100644 --- a/uc.c +++ b/uc.c @@ -32,7 +32,7 @@ #include "qemu/include/hw/boards.h" static uint8_t *copy_region(uch uc, MemoryRegion *mr); -static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, size_t size); +static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, size_t size, bool do_delete); UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor) @@ -678,11 +678,15 @@ static uint8_t *copy_region(uch handle, MemoryRegion *mr) This is a static function and callers have already done some preliminary parameter validation. + + The do_delete argument indicates that we are being called to support + uc_mem_unmap. In this case we save some time by choosing NOT to remap + the areas that are intended to get unmapped */ // TODO: investigate whether qemu region manipulation functions already offered // this capability static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, - size_t size) + size_t size, bool do_delete) { uint8_t *backup; uint32_t perms; @@ -690,9 +694,8 @@ static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, size_t l_size, m_size, r_size; chunk_end = address + size; - if (address <= mr->addr && chunk_end >= mr->end) { + if (address <= mr->addr && chunk_end >= mr->end) return true; - } if (size == 0) //trivial case @@ -742,7 +745,7 @@ static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, if (uc_mem_write(handle, begin, backup, l_size) != UC_ERR_OK) goto error; } - if (m_size > 0) { + if (m_size > 0 && !do_delete) { if (uc_mem_map(handle, address, m_size, perms) != UC_ERR_OK) goto error; if (uc_mem_write(handle, address, backup + l_size, m_size) != UC_ERR_OK) @@ -788,7 +791,7 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms) if ((perms & ~UC_PROT_ALL) != 0) return UC_ERR_INVAL; - //check that user's entire requested block is mapped + // check that user's entire requested block is mapped if (!check_mem_area(uc, address, size)) return UC_ERR_NOMEM; @@ -799,24 +802,16 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms) while(count < size) { mr = memory_mapping(uc, addr); len = MIN(size - count, mr->end - addr); - if (!split_region(handle, mr, addr, len)) + if (!split_region(handle, mr, addr, len, false)) return UC_ERR_NOMEM; - count += len; - addr += len; - } - // Now iterate all the regions to set permission - addr = address; - count = 0; - while(count < size) { mr = memory_mapping(uc, addr); - len = MIN(size - count, mr->end - addr); mr->perms = perms; uc->readonly_mem(mr, (perms & UC_PROT_WRITE) == 0); + count += len; addr += len; } - return UC_ERR_OK; } @@ -824,7 +819,6 @@ UNICORN_EXPORT uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size) { MemoryRegion *mr; - unsigned int i; struct uc_struct* uc = (struct uc_struct *)handle; uint64_t addr; size_t count, len; @@ -845,42 +839,27 @@ uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size) if ((size & uc->target_page_align) != 0) return UC_ERR_MAP; - //check that user's entire requested block is mapped + // check that user's entire requested block is mapped if (!check_mem_area(uc, address, size)) return UC_ERR_NOMEM; - // Now we know entire region is mapped, so change permissions + // Now we know entire region is mapped, so do the unmap // We may need to split regions if this area spans adjacent regions addr = address; count = 0; while(count < size) { mr = memory_mapping(uc, addr); len = MIN(size - count, mr->end - addr); - if (!split_region(handle, mr, addr, len)) + if (!split_region(handle, mr, addr, len, true)) return UC_ERR_NOMEM; - count += len; - addr += len; - } - - // Now iterate all the regions to set permission - addr = address; - count = 0; - while(count < size) { + // if we can retieve the mapping, then no splitting took place + // so unmap here mr = memory_mapping(uc, addr); - len = MIN(size - count, mr->end - addr); - uc->memory_unmap(uc, mr); - for (i = 0; i < uc->mapped_block_count; i++) { - if (uc->mapped_blocks[i] == mr) { - uc->mapped_block_count--; - //shift remainder of array down over deleted pointer - memcpy(&uc->mapped_blocks[i], &uc->mapped_blocks[i + 1], sizeof(MemoryRegion*) * (uc->mapped_block_count - i)); - break; - } - } + if (mr != NULL) + uc->memory_unmap(uc, mr); count += len; addr += len; } - return UC_ERR_OK; }