This commit continues the PR #111

- Allow to register handler separately for invalid memory access
- Add new memory events for hooking:
   - UC_MEM_READ_INVALID, UC_MEM_WRITE_INVALID, UC_MEM_FETCH_INVALID
   - UC_HOOK_MEM_READ_PROT, UC_HOOK_MEM_WRITE_PROT, UC_HOOK_MEM_FETCH_PROT
- Rename UC_ERR_EXEC_PROT to UC_ERR_FETCH_PROT
- Change API uc_hook_add() so event type @type can be combined from hooking types
This commit is contained in:
Nguyen Anh Quynh
2015-09-24 14:18:02 +08:00
parent e479f72403
commit 90eb8f2e72
21 changed files with 223 additions and 128 deletions

View File

@@ -300,7 +300,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
(addr & TARGET_PAGE_MASK))) {
cpu_ldub_code(env1, addr);
//check for NX related error from softmmu
if (env1->invalid_error == UC_ERR_EXEC_PROT) {
if (env1->invalid_error == UC_ERR_FETCH_PROT) {
env1->invalid_error = UC_ERR_CODE_INVALID;
return -1;
}

View File

@@ -177,7 +177,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
uintptr_t haddr;
DATA_TYPE res;
int mem_access, error_code;
int error_code;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
@@ -185,15 +185,16 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
// memory can be unmapped while reading or fetching
if (mr == NULL) {
#if defined(SOFTMMU_CODE_ACCESS)
mem_access = UC_MEM_FETCH;
error_code = UC_ERR_FETCH_INVALID;
if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)(
uc, UC_MEM_FETCH_INVALID, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) {
#else
mem_access = UC_MEM_READ;
error_code = UC_ERR_READ_INVALID;
if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)(
uc, UC_MEM_READ_INVALID, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) {
#endif
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
uc, mem_access, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
} else {
@@ -208,13 +209,13 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
#if defined(SOFTMMU_CODE_ACCESS)
// Unicorn: callback on fetch from NX
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
if (uc->hook_mem_fetch_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].callback)(
uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
} else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_EXEC_PROT;
env->invalid_error = UC_ERR_FETCH_PROT;
// printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return 0;
@@ -233,9 +234,9 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
// Unicorn: callback on non-readable memory
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
if (uc->hook_mem_read_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_prot_idx].callback)(
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
uc->hook_callbacks[uc->hook_mem_read_prot_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
}
else {
@@ -367,7 +368,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
uintptr_t haddr;
DATA_TYPE res;
int mem_access, error_code;
int error_code;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
@@ -375,15 +376,16 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
// memory can be unmapped while reading or fetching
if (mr == NULL) {
#if defined(SOFTMMU_CODE_ACCESS)
mem_access = UC_MEM_FETCH;
error_code = UC_ERR_FETCH_INVALID;
if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)(
uc, UC_MEM_FETCH_INVALID, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) {
#else
mem_access = UC_MEM_READ;
error_code = UC_ERR_READ_INVALID;
if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)(
uc, UC_MEM_READ_INVALID, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) {
#endif
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
uc, mem_access, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
} else {
@@ -398,13 +400,13 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
#if defined(SOFTMMU_CODE_ACCESS)
// Unicorn: callback on fetch from NX
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
if (uc->hook_mem_fetch_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].callback)(
uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
} else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_EXEC_PROT;
env->invalid_error = UC_ERR_FETCH_PROT;
// printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return 0;
@@ -423,9 +425,9 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
// Unicorn: callback on non-readable memory
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
if (uc->hook_mem_read_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_prot_idx].callback)(
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
uc->hook_callbacks[uc->hook_mem_read_prot_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
} else {
env->invalid_addr = addr;
@@ -608,10 +610,10 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
}
// Unicorn: callback on invalid memory
if (uc->hook_mem_idx && mr == NULL) {
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
if (uc->hook_mem_write_idx && mr == NULL) {
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)(
uc, UC_MEM_WRITE_INVALID, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) {
// save error & quit
env->invalid_addr = addr;
env->invalid_error = UC_ERR_WRITE_INVALID;
@@ -620,14 +622,15 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
return;
} else {
env->invalid_error = UC_ERR_OK;
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
}
}
// Unicorn: callback on non-writable memory
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
if (uc->hook_mem_write_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_prot_idx].callback)(
uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
uc->hook_callbacks[uc->hook_mem_write_prot_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
}
else {
@@ -754,10 +757,10 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
}
// Unicorn: callback on invalid memory
if (uc->hook_mem_idx && mr == NULL) {
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
if (uc->hook_mem_write_idx && mr == NULL) {
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)(
uc, UC_MEM_WRITE_INVALID, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) {
// save error & quit
env->invalid_addr = addr;
env->invalid_error = UC_ERR_WRITE_INVALID;
@@ -766,14 +769,15 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
return;
} else {
env->invalid_error = UC_ERR_OK;
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
}
}
// Unicorn: callback on non-writable memory
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
if (uc->hook_mem_write_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_prot_idx].callback)(
uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val,
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
uc->hook_callbacks[uc->hook_mem_write_prot_idx].user_data)) {
env->invalid_error = UC_ERR_OK;
}
else {