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) void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
{ {
int i;
target_ulong addr; target_ulong addr;
//make sure all pages associated with the MemoryRegion are flushed //make sure all pages associated with the MemoryRegion are flushed
for (addr = mr->addr; addr < mr->end; addr += uc->target_page_size) { 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; mr->enabled = false;
memory_region_del_subregion(get_system_memory(uc), mr); 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); 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++); 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++); printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++);
return 6; return 6;
} else { } else {
@ -212,7 +212,7 @@ int main(int argc, char **argv, char **envp)
} }
// intercept memory write events // 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++); printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++);
return 7; return 7;
} else { } 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++); 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++); printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++);
return 5; return 5;
} else { } else {
@ -220,7 +220,7 @@ int main(int argc, char **argv, char **envp)
} }
// intercept memory write events // 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++); printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++);
return 6; return 6;
} else { } 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++); 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++); printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++);
return 5; return 5;
} else { } else {
@ -215,7 +215,7 @@ int main(int argc, char **argv, char **envp)
} }
// intercept memory write events // 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++); printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++);
return 6; return 6;
} else { } else {

57
uc.c
View file

@ -32,7 +32,7 @@
#include "qemu/include/hw/boards.h" #include "qemu/include/hw/boards.h"
static uint8_t *copy_region(uch uc, MemoryRegion *mr); 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 UNICORN_EXPORT
unsigned int uc_version(unsigned int *major, unsigned int *minor) 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 This is a static function and callers have already done some preliminary
parameter validation. 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 // TODO: investigate whether qemu region manipulation functions already offered
// this capability // this capability
static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, static bool split_region(uch handle, MemoryRegion *mr, uint64_t address,
size_t size) size_t size, bool do_delete)
{ {
uint8_t *backup; uint8_t *backup;
uint32_t perms; 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; size_t l_size, m_size, r_size;
chunk_end = address + size; chunk_end = address + size;
if (address <= mr->addr && chunk_end >= mr->end) { if (address <= mr->addr && chunk_end >= mr->end)
return true; return true;
}
if (size == 0) if (size == 0)
//trivial case //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) if (uc_mem_write(handle, begin, backup, l_size) != UC_ERR_OK)
goto error; goto error;
} }
if (m_size > 0) { if (m_size > 0 && !do_delete) {
if (uc_mem_map(handle, address, m_size, perms) != UC_ERR_OK) if (uc_mem_map(handle, address, m_size, perms) != UC_ERR_OK)
goto error; goto error;
if (uc_mem_write(handle, address, backup + l_size, m_size) != UC_ERR_OK) 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) if ((perms & ~UC_PROT_ALL) != 0)
return UC_ERR_INVAL; 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)) if (!check_mem_area(uc, address, size))
return UC_ERR_NOMEM; 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) { while(count < size) {
mr = memory_mapping(uc, addr); mr = memory_mapping(uc, addr);
len = MIN(size - count, mr->end - 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; 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); mr = memory_mapping(uc, addr);
len = MIN(size - count, mr->end - addr);
mr->perms = perms; mr->perms = perms;
uc->readonly_mem(mr, (perms & UC_PROT_WRITE) == 0); uc->readonly_mem(mr, (perms & UC_PROT_WRITE) == 0);
count += len; count += len;
addr += len; addr += len;
} }
return UC_ERR_OK; return UC_ERR_OK;
} }
@ -824,7 +819,6 @@ UNICORN_EXPORT
uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size) uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size)
{ {
MemoryRegion *mr; MemoryRegion *mr;
unsigned int i;
struct uc_struct* uc = (struct uc_struct *)handle; struct uc_struct* uc = (struct uc_struct *)handle;
uint64_t addr; uint64_t addr;
size_t count, len; 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) if ((size & uc->target_page_align) != 0)
return UC_ERR_MAP; 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)) if (!check_mem_area(uc, address, size))
return UC_ERR_NOMEM; 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 // We may need to split regions if this area spans adjacent regions
addr = address; addr = address;
count = 0; count = 0;
while(count < size) { while(count < size) {
mr = memory_mapping(uc, addr); mr = memory_mapping(uc, addr);
len = MIN(size - count, mr->end - 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; return UC_ERR_NOMEM;
count += len; // if we can retieve the mapping, then no splitting took place
addr += len; // so unmap here
}
// Now iterate all the regions to set permission
addr = address;
count = 0;
while(count < size) {
mr = memory_mapping(uc, addr); mr = memory_mapping(uc, addr);
len = MIN(size - count, mr->end - addr); if (mr != NULL)
uc->memory_unmap(uc, mr); 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; count += len;
addr += len; addr += len;
} }
return UC_ERR_OK; return UC_ERR_OK;
} }