Detect all occurences of write to read only page. Add callback capability on write to read only. Add new error type UC_ERR_MEM_WRITE_RO and new access type UC_MEM_WRITE_RO for use in callback

This commit is contained in:
Chris Eagle
2015-08-27 18:03:17 -07:00
parent f357f4de21
commit 686acb7e6e
9 changed files with 136 additions and 48 deletions

View File

@ -170,6 +170,7 @@ struct MemoryRegion {
MemoryRegionIoeventfd *ioeventfds;
NotifierList iommu_notify;
struct uc_struct *uc;
uint32_t perms; //all perms, partially redundant with readonly
};
/**

View File

@ -1160,6 +1160,7 @@ void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
if (!(perms & UC_PROT_WRITE)) {
mr->readonly = true;
}
mr->perms = perms;
mr->terminates = true;
mr->destructor = memory_region_destructor_ram;
mr->ram_addr = qemu_ram_alloc(size, mr, errp);

View File

@ -460,31 +460,53 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
uintptr_t haddr;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// Unicorn: callback on memory write
if (env->uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_WRITE, addr);
if (uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)uc, UC_MEM_WRITE, addr);
if (trace) {
((uc_cb_hookmem_t)trace->callback)((uch)env->uc, UC_MEM_WRITE,
((uc_cb_hookmem_t)trace->callback)((uch)uc, UC_MEM_WRITE,
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
}
}
// Unicorn: callback on invalid memory
if (env->uc->hook_mem_idx && !memory_mapping(env->uc, addr)) {
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
(uch)env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
if (uc->hook_mem_idx && mr == NULL) {
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
(uch)uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
// save error & quit
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE;
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
cpu_exit(env->uc->current_cpu);
cpu_exit(uc->current_cpu);
return;
} else {
env->invalid_error = UC_ERR_OK;
}
}
// Unicorn: callback on read only memory
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //read only memory
bool result = false;
if (uc->hook_mem_idx) {
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
(uch)uc, UC_MEM_WRITE_RO, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data);
}
if (result) {
env->invalid_error = UC_ERR_OK;
}
else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE_RO;
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return;
}
}
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@ -546,6 +568,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
mmu_idx, retaddr + GETPC_ADJ);
if (env->invalid_error != UC_ERR_OK)
break;
}
return;
}
@ -574,31 +598,54 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
uintptr_t haddr;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// Unicorn: callback on memory write
if (env->uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_WRITE, addr);
if (uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)uc, UC_MEM_WRITE, addr);
if (trace) {
((uc_cb_hookmem_t)trace->callback)((uch)env->uc, UC_MEM_WRITE,
((uc_cb_hookmem_t)trace->callback)((uch)uc, UC_MEM_WRITE,
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
}
}
// Unicorn: callback on invalid memory
if (env->uc->hook_mem_idx && !memory_mapping(env->uc, addr)) {
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
(uch)env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
if (uc->hook_mem_idx && mr == NULL) {
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
(uch)uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
// save error & quit
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE;
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
cpu_exit(env->uc->current_cpu);
cpu_exit(uc->current_cpu);
return;
} else {
env->invalid_error = UC_ERR_OK;
}
}
// Unicorn: callback on read only memory
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //read only memory
bool result = false;
if (uc->hook_mem_idx) {
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
(uch)uc, UC_MEM_WRITE_RO, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data);
}
if (result) {
env->invalid_error = UC_ERR_OK;
}
else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE_RO;
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return;
}
}
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@ -659,6 +706,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
mmu_idx, retaddr + GETPC_ADJ);
if (env->invalid_error != UC_ERR_OK)
break;
}
return;
}