handle memory fetch as invalid memory access. now we can also report error if exec memory is unmapped (UC_ERR_MEM_FETCH)
This commit is contained in:
parent
84e3b5c897
commit
022f8d82d1
|
@ -41,20 +41,22 @@ const (
|
||||||
UC_ERR_VERSION = 5
|
UC_ERR_VERSION = 5
|
||||||
UC_ERR_MEM_READ = 6
|
UC_ERR_MEM_READ = 6
|
||||||
UC_ERR_MEM_WRITE = 7
|
UC_ERR_MEM_WRITE = 7
|
||||||
UC_ERR_CODE_INVALID = 8
|
UC_ERR_MEM_FETCH = 8
|
||||||
UC_ERR_HOOK = 9
|
UC_ERR_CODE_INVALID = 9
|
||||||
UC_ERR_INSN_INVALID = 10
|
UC_ERR_HOOK = 10
|
||||||
UC_ERR_MAP = 11
|
UC_ERR_INSN_INVALID = 11
|
||||||
UC_ERR_WRITE_PROT = 12
|
UC_ERR_MAP = 12
|
||||||
UC_ERR_READ_PROT = 13
|
UC_ERR_WRITE_PROT = 13
|
||||||
UC_ERR_EXEC_PROT = 14
|
UC_ERR_READ_PROT = 14
|
||||||
UC_ERR_INVAL = 15
|
UC_ERR_EXEC_PROT = 15
|
||||||
|
UC_ERR_INVAL = 16
|
||||||
UC_MEM_READ = 16
|
UC_MEM_READ = 16
|
||||||
UC_MEM_WRITE = 17
|
UC_MEM_WRITE = 17
|
||||||
UC_MEM_READ_WRITE = 18
|
UC_MEM_READ_WRITE = 18
|
||||||
UC_MEM_WRITE_PROT = 19
|
UC_MEM_EXEC = 19
|
||||||
UC_MEM_READ_PROT = 20
|
UC_MEM_WRITE_PROT = 20
|
||||||
UC_MEM_EXEC_PROT = 21
|
UC_MEM_READ_PROT = 21
|
||||||
|
UC_MEM_EXEC_PROT = 22
|
||||||
UC_HOOK_INTR = 32
|
UC_HOOK_INTR = 32
|
||||||
UC_HOOK_INSN = 33
|
UC_HOOK_INSN = 33
|
||||||
UC_HOOK_CODE = 34
|
UC_HOOK_CODE = 34
|
||||||
|
|
|
@ -39,20 +39,22 @@ UC_ERR_MODE = 4
|
||||||
UC_ERR_VERSION = 5
|
UC_ERR_VERSION = 5
|
||||||
UC_ERR_MEM_READ = 6
|
UC_ERR_MEM_READ = 6
|
||||||
UC_ERR_MEM_WRITE = 7
|
UC_ERR_MEM_WRITE = 7
|
||||||
UC_ERR_CODE_INVALID = 8
|
UC_ERR_MEM_FETCH = 8
|
||||||
UC_ERR_HOOK = 9
|
UC_ERR_CODE_INVALID = 9
|
||||||
UC_ERR_INSN_INVALID = 10
|
UC_ERR_HOOK = 10
|
||||||
UC_ERR_MAP = 11
|
UC_ERR_INSN_INVALID = 11
|
||||||
UC_ERR_WRITE_PROT = 12
|
UC_ERR_MAP = 12
|
||||||
UC_ERR_READ_PROT = 13
|
UC_ERR_WRITE_PROT = 13
|
||||||
UC_ERR_EXEC_PROT = 14
|
UC_ERR_READ_PROT = 14
|
||||||
UC_ERR_INVAL = 15
|
UC_ERR_EXEC_PROT = 15
|
||||||
|
UC_ERR_INVAL = 16
|
||||||
UC_MEM_READ = 16
|
UC_MEM_READ = 16
|
||||||
UC_MEM_WRITE = 17
|
UC_MEM_WRITE = 17
|
||||||
UC_MEM_READ_WRITE = 18
|
UC_MEM_READ_WRITE = 18
|
||||||
UC_MEM_WRITE_PROT = 19
|
UC_MEM_EXEC = 19
|
||||||
UC_MEM_READ_PROT = 20
|
UC_MEM_WRITE_PROT = 20
|
||||||
UC_MEM_EXEC_PROT = 21
|
UC_MEM_READ_PROT = 21
|
||||||
|
UC_MEM_EXEC_PROT = 22
|
||||||
UC_HOOK_INTR = 32
|
UC_HOOK_INTR = 32
|
||||||
UC_HOOK_INSN = 33
|
UC_HOOK_INSN = 33
|
||||||
UC_HOOK_CODE = 34
|
UC_HOOK_CODE = 34
|
||||||
|
|
|
@ -113,6 +113,7 @@ typedef enum uc_err {
|
||||||
UC_ERR_VERSION, // Unsupported version (bindings)
|
UC_ERR_VERSION, // Unsupported version (bindings)
|
||||||
UC_ERR_MEM_READ, // Quit emulation due to invalid memory READ: uc_emu_start()
|
UC_ERR_MEM_READ, // Quit emulation due to invalid memory READ: uc_emu_start()
|
||||||
UC_ERR_MEM_WRITE, // Quit emulation due to invalid memory WRITE: uc_emu_start()
|
UC_ERR_MEM_WRITE, // Quit emulation due to invalid memory WRITE: uc_emu_start()
|
||||||
|
UC_ERR_MEM_FETCH, // Quit emulation due to invalid memory FETCH: uc_emu_start()
|
||||||
UC_ERR_CODE_INVALID, // Quit emulation due to invalid code address: uc_emu_start()
|
UC_ERR_CODE_INVALID, // Quit emulation due to invalid code address: uc_emu_start()
|
||||||
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()
|
||||||
|
@ -152,6 +153,7 @@ 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_EXEC, // Unmapped memory is fetched, but unmapped (invalid memory access)
|
||||||
UC_MEM_WRITE_PROT, // write to write protected memory
|
UC_MEM_WRITE_PROT, // write to write protected memory
|
||||||
UC_MEM_READ_PROT, // read from read protected memory
|
UC_MEM_READ_PROT, // read from read protected memory
|
||||||
UC_MEM_EXEC_PROT, // fetch from non-executable memory
|
UC_MEM_EXEC_PROT, // fetch from non-executable memory
|
||||||
|
|
|
@ -182,8 +182,24 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
#if defined(SOFTMMU_CODE_ACCESS)
|
#if defined(SOFTMMU_CODE_ACCESS)
|
||||||
|
// Unicorn: callback on fetch from unmapped memory
|
||||||
|
if (mr == NULL) { // memory is not mapped
|
||||||
|
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||||
|
uc, UC_MEM_EXEC, 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 {
|
||||||
|
env->invalid_addr = addr;
|
||||||
|
env->invalid_error = UC_ERR_MEM_FETCH;
|
||||||
|
// printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr);
|
||||||
|
cpu_exit(uc->current_cpu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unicorn: callback on fetch from NX
|
// Unicorn: callback on fetch from NX
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { //non-executable
|
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)(
|
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, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||||
|
@ -199,7 +215,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Unicorn: callback on memory read
|
// Unicorn: callback on memory read
|
||||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && env->uc->hook_mem_read) {
|
||||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr);
|
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ,
|
((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ,
|
||||||
|
@ -208,7 +224,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 && mr == NULL) {
|
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && 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)(
|
||||||
env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
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)) {
|
||||||
|
@ -224,7 +240,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on non-readable memory
|
// Unicorn: callback on non-readable memory
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
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_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||||
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||||
|
@ -340,8 +356,24 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
#if defined(SOFTMMU_CODE_ACCESS)
|
#if defined(SOFTMMU_CODE_ACCESS)
|
||||||
|
// Unicorn: callback on fetch from unmapped memory
|
||||||
|
if (mr == NULL) { // memory is not mapped
|
||||||
|
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||||
|
uc, UC_MEM_EXEC, 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 {
|
||||||
|
env->invalid_addr = addr;
|
||||||
|
env->invalid_error = UC_ERR_MEM_FETCH;
|
||||||
|
// printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr);
|
||||||
|
cpu_exit(uc->current_cpu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unicorn: callback on fetch from NX
|
// Unicorn: callback on fetch from NX
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { //non-executable
|
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)(
|
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, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||||
|
@ -357,7 +389,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Unicorn: callback on memory read
|
// Unicorn: callback on memory read
|
||||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && env->uc->hook_mem_read) {
|
||||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr);
|
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ,
|
((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ,
|
||||||
|
@ -366,7 +398,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 && mr == NULL) {
|
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && 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)(
|
||||||
env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
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)) {
|
||||||
|
@ -382,7 +414,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on non-readable memory
|
// Unicorn: callback on non-readable memory
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
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_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||||
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import unicorn
|
||||||
ADDR = 0xffaabbcc
|
ADDR = 0xffaabbcc
|
||||||
|
|
||||||
def hook_mem_invalid(mu, access, address, size, value, user_data):
|
def hook_mem_invalid(mu, access, address, size, value, user_data):
|
||||||
print ">>> Expected value: 0x%x, actual value: 0x%x" % (ADDR, address)
|
print ">>> Access type: %u, Expected value: 0x%x, actual value: 0x%x" % (access, ADDR, address)
|
||||||
assert(address == ADDR)
|
assert(address == ADDR)
|
||||||
mu.mem_map(address & 0xfffff000, 4 * 1024)
|
mu.mem_map(address & 0xfffff000, 4 * 1024)
|
||||||
mu.mem_write(address, b'\xcc')
|
mu.mem_write(address, b'\xcc')
|
||||||
|
|
6
uc.c
6
uc.c
|
@ -73,12 +73,14 @@ const char *uc_strerror(uc_err code)
|
||||||
return "Invalid memory read (UC_ERR_MEM_READ)";
|
return "Invalid memory read (UC_ERR_MEM_READ)";
|
||||||
case UC_ERR_MEM_WRITE:
|
case UC_ERR_MEM_WRITE:
|
||||||
return "Invalid memory write (UC_ERR_MEM_WRITE)";
|
return "Invalid memory write (UC_ERR_MEM_WRITE)";
|
||||||
|
case UC_ERR_MEM_FETCH:
|
||||||
|
return "Invalid memory fetch (UC_ERR_MEM_FETCH)";
|
||||||
case UC_ERR_CODE_INVALID:
|
case UC_ERR_CODE_INVALID:
|
||||||
return "Invalid code address (UC_ERR_CODE_INVALID)";
|
return "Invalid code address (UC_ERR_CODE_INVALID)";
|
||||||
case UC_ERR_INSN_INVALID:
|
|
||||||
return "Invalid instruction (UC_ERR_INSN_INVALID)";
|
|
||||||
case UC_ERR_HOOK:
|
case UC_ERR_HOOK:
|
||||||
return "Invalid hook type (UC_ERR_HOOK)";
|
return "Invalid hook type (UC_ERR_HOOK)";
|
||||||
|
case UC_ERR_INSN_INVALID:
|
||||||
|
return "Invalid instruction (UC_ERR_INSN_INVALID)";
|
||||||
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_WRITE_PROT:
|
case UC_ERR_WRITE_PROT:
|
||||||
|
|
Loading…
Reference in New Issue