Merge branch 'mem_map_ex' of https://github.com/cseagle/unicorn into cseagle-mem_map_ex
This commit is contained in:
@ -116,7 +116,8 @@ typedef enum uc_err {
|
|||||||
UC_ERR_HOOK, // Invalid hook type: uc_hook_add()
|
UC_ERR_HOOK, // Invalid hook type: uc_hook_add()
|
||||||
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start()
|
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start()
|
||||||
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
|
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
|
||||||
UC_ERR_MEM_WRITE_RO, // Quit emulation due to invalid memory WRITE: uc_emu_start()
|
UC_ERR_MEM_WRITE_NW, // Quit emulation due to write to non-writable: uc_emu_start()
|
||||||
|
UC_ERR_MEM_READ_NR, // Quit emulation due to read from non-readable: uc_emu_start()
|
||||||
} uc_err;
|
} uc_err;
|
||||||
|
|
||||||
|
|
||||||
@ -148,7 +149,8 @@ typedef enum uc_mem_type {
|
|||||||
UC_MEM_READ = 16, // Memory is read from
|
UC_MEM_READ = 16, // Memory is read from
|
||||||
UC_MEM_WRITE, // Memory is written to
|
UC_MEM_WRITE, // Memory is written to
|
||||||
UC_MEM_READ_WRITE, // Memory is accessed (either READ or WRITE)
|
UC_MEM_READ_WRITE, // Memory is accessed (either READ or WRITE)
|
||||||
UC_MEM_WRITE_RO, // Read only memory is written to
|
UC_MEM_WRITE_NW, // write to non-writable
|
||||||
|
UC_MEM_READ_NR, // read from non-readable
|
||||||
} uc_mem_type;
|
} uc_mem_type;
|
||||||
|
|
||||||
// All type of hooks for uc_hook_add() API.
|
// All type of hooks for uc_hook_add() API.
|
||||||
|
@ -178,6 +178,9 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
DATA_TYPE res;
|
DATA_TYPE res;
|
||||||
|
|
||||||
|
struct uc_struct *uc = env->uc;
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
// Unicorn: callback on memory read
|
// Unicorn: callback on memory read
|
||||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
||||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_READ, addr);
|
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_READ, addr);
|
||||||
@ -188,7 +191,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on invalid memory
|
// Unicorn: callback on invalid memory
|
||||||
if (env->uc->hook_mem_idx && !memory_mapping(env->uc, addr)) {
|
if (env->uc->hook_mem_idx && mr == NULL) {
|
||||||
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
||||||
(uch)env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
(uch)env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
||||||
@ -203,6 +206,26 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unicorn: callback on read only memory
|
||||||
|
if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
||||||
|
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_READ_NR, addr, DATA_SIZE, 0,
|
||||||
|
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_READ_NR;
|
||||||
|
// printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr);
|
||||||
|
cpu_exit(uc->current_cpu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Adjust the given return address. */
|
/* Adjust the given return address. */
|
||||||
retaddr -= GETPC_ADJ;
|
retaddr -= GETPC_ADJ;
|
||||||
|
|
||||||
@ -300,6 +323,9 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
DATA_TYPE res;
|
DATA_TYPE res;
|
||||||
|
|
||||||
|
struct uc_struct *uc = env->uc;
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
// Unicorn: callback on memory read
|
// Unicorn: callback on memory read
|
||||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
||||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_READ, addr);
|
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_READ, addr);
|
||||||
@ -310,7 +336,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on invalid memory
|
// Unicorn: callback on invalid memory
|
||||||
if (env->uc->hook_mem_idx && !memory_mapping(env->uc, addr)) {
|
if (env->uc->hook_mem_idx && mr == NULL) {
|
||||||
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
||||||
(uch)env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
(uch)env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
||||||
@ -325,6 +351,26 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unicorn: callback on read only memory
|
||||||
|
if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
||||||
|
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_READ_NR, addr, DATA_SIZE, 0,
|
||||||
|
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_READ_NR;
|
||||||
|
// printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr);
|
||||||
|
cpu_exit(uc->current_cpu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Adjust the given return address. */
|
/* Adjust the given return address. */
|
||||||
retaddr -= GETPC_ADJ;
|
retaddr -= GETPC_ADJ;
|
||||||
|
|
||||||
@ -493,7 +539,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
if (uc->hook_mem_idx) {
|
if (uc->hook_mem_idx) {
|
||||||
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
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,
|
(uch)uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
||||||
}
|
}
|
||||||
if (result) {
|
if (result) {
|
||||||
@ -501,7 +547,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_MEM_WRITE_RO;
|
env->invalid_error = UC_ERR_MEM_WRITE_NW;
|
||||||
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
|
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
|
||||||
cpu_exit(uc->current_cpu);
|
cpu_exit(uc->current_cpu);
|
||||||
return;
|
return;
|
||||||
@ -631,7 +677,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
if (uc->hook_mem_idx) {
|
if (uc->hook_mem_idx) {
|
||||||
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
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,
|
(uch)uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
||||||
}
|
}
|
||||||
if (result) {
|
if (result) {
|
||||||
@ -639,7 +685,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_MEM_WRITE_RO;
|
env->invalid_error = UC_ERR_MEM_WRITE_NW;
|
||||||
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
|
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
|
||||||
cpu_exit(uc->current_cpu);
|
cpu_exit(uc->current_cpu);
|
||||||
return;
|
return;
|
||||||
|
@ -4,7 +4,7 @@ LDFLAGS = -L.. -lunicorn
|
|||||||
TESTS = map_crash map_write
|
TESTS = map_crash map_write
|
||||||
TESTS += sigill sigill2
|
TESTS += sigill sigill2
|
||||||
TESTS += block_test
|
TESTS += block_test
|
||||||
TESTS += ro_mem_test
|
TESTS += ro_mem_test nr_mem_test
|
||||||
|
|
||||||
all: $(TESTS)
|
all: $(TESTS)
|
||||||
|
|
||||||
|
@ -1,3 +1,24 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
non-writable memory test case
|
||||||
|
|
||||||
|
Copyright(c) 2015 Chris Eagle
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
version 2 as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -61,7 +82,7 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
|||||||
printf(">>> Missing memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
printf(">>> Missing memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
||||||
address, size, value);
|
address, size, value);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_WRITE_RO:
|
case UC_MEM_WRITE_NR:
|
||||||
printf(">>> RO memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
printf(">>> RO memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
||||||
address, size, value);
|
address, size, value);
|
||||||
return false;
|
return false;
|
||||||
|
6
uc.c
6
uc.c
@ -89,8 +89,10 @@ const char *uc_strerror(uc_err code)
|
|||||||
return "Invalid hook type (UC_ERR_HOOK)";
|
return "Invalid hook type (UC_ERR_HOOK)";
|
||||||
case UC_ERR_MAP:
|
case UC_ERR_MAP:
|
||||||
return "Invalid memory mapping (UC_ERR_MAP)";
|
return "Invalid memory mapping (UC_ERR_MAP)";
|
||||||
case UC_ERR_MEM_WRITE_RO:
|
case UC_ERR_MEM_WRITE_NW:
|
||||||
return "Invalid memory write (UC_ERR_MEM_WRITE_RO)";
|
return "Write to non-writable (UC_ERR_MEM_WRITE_NW)";
|
||||||
|
case UC_ERR_MEM_READ_NR:
|
||||||
|
return "Read from non-readable (UC_ERR_MEM_READ_NR)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user