smooth out split_region related code

This commit is contained in:
Chris Eagle 2015-09-03 12:26:36 -07:00
parent 6ca85a72ed
commit 2da46caef7
5 changed files with 35 additions and 45 deletions

View File

@ -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);
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

55
uc.c
View File

@ -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);
if (mr != NULL)
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;
}
}
count += len;
addr += len;
}
return UC_ERR_OK;
}