Merge branch 'mem_map_ex' of https://github.com/cseagle/unicorn into cseagle-mem_map_ex
This commit is contained in:
6
qemu/include/exec/memory.h
Normal file → Executable file
6
qemu/include/exec/memory.h
Normal file → Executable file
@@ -170,6 +170,8 @@ struct MemoryRegion {
|
||||
MemoryRegionIoeventfd *ioeventfds;
|
||||
NotifierList iommu_notify;
|
||||
struct uc_struct *uc;
|
||||
uint32_t perms; //all perms, partially redundant with readonly
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -315,12 +317,14 @@ void memory_region_init_io(struct uc_struct *uc, MemoryRegion *mr,
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @size: size of the region.
|
||||
* @perms: permissions on the region (UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC).
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*/
|
||||
void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
uint32_t perms,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
@@ -934,7 +938,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
||||
|
||||
void memory_register_types(struct uc_struct *uc);
|
||||
|
||||
int memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size);
|
||||
MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms);
|
||||
int memory_free(struct uc_struct *uc);
|
||||
|
||||
#endif
|
||||
|
||||
27
qemu/memory.c
Normal file → Executable file
27
qemu/memory.c
Normal file → Executable file
@@ -31,27 +31,28 @@
|
||||
|
||||
|
||||
// Unicorn engine
|
||||
int memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size)
|
||||
MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms)
|
||||
{
|
||||
uc->ram = g_new(MemoryRegion, 1);
|
||||
|
||||
memory_region_init_ram(uc, uc->ram, NULL, "pc.ram", size, &error_abort);
|
||||
memory_region_init_ram(uc, uc->ram, NULL, "pc.ram", size, perms, &error_abort);
|
||||
|
||||
memory_region_add_subregion(get_system_memory(uc), begin, uc->ram);
|
||||
|
||||
if (uc->current_cpu)
|
||||
tlb_flush(uc->current_cpu, 1);
|
||||
|
||||
return 0;
|
||||
return uc->ram;
|
||||
}
|
||||
|
||||
int memory_free(struct uc_struct *uc)
|
||||
{
|
||||
int i;
|
||||
get_system_memory(uc)->enabled = false;
|
||||
if (uc->ram) {
|
||||
uc->ram->enabled = false;
|
||||
memory_region_del_subregion(get_system_memory(uc), uc->ram);
|
||||
g_free(uc->ram);
|
||||
for (i = 0; i < uc->mapped_block_count; i++) {
|
||||
uc->mapped_blocks[i]->enabled = false;
|
||||
memory_region_del_subregion(get_system_memory(uc), uc->mapped_blocks[i]);
|
||||
g_free(uc->mapped_blocks[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1151,10 +1152,15 @@ void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
uint32_t perms,
|
||||
Error **errp)
|
||||
{
|
||||
memory_region_init(uc, mr, owner, name, size);
|
||||
mr->ram = true;
|
||||
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);
|
||||
@@ -1309,6 +1315,12 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
|
||||
if (mr->readonly != readonly) {
|
||||
memory_region_transaction_begin(mr->uc);
|
||||
mr->readonly = readonly;
|
||||
if (readonly) {
|
||||
mr->perms &= ~UC_PROT_WRITE;
|
||||
}
|
||||
else {
|
||||
mr->perms |= UC_PROT_WRITE;
|
||||
}
|
||||
mr->uc->memory_region_update_pending |= mr->enabled;
|
||||
memory_region_transaction_commit(mr->uc);
|
||||
}
|
||||
@@ -1528,6 +1540,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
|
||||
assert(!subregion->container);
|
||||
subregion->container = mr;
|
||||
subregion->addr = offset;
|
||||
subregion->end = offset + int128_get64(subregion->size);
|
||||
memory_region_update_container_subregions(subregion);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
1
qemu/unicorn_common.h
Normal file → Executable file
1
qemu/unicorn_common.h
Normal file → Executable file
@@ -73,6 +73,7 @@ static inline void uc_common_init(struct uc_struct* uc)
|
||||
uc->pause_all_vcpus = pause_all_vcpus;
|
||||
uc->vm_start = vm_start;
|
||||
uc->memory_map = memory_map;
|
||||
uc->readonly_mem = memory_region_set_readonly;
|
||||
|
||||
if (!uc->release)
|
||||
uc->release = release_common;
|
||||
|
||||
Reference in New Issue
Block a user