Merge branch 'master' of https://github.com/unicorn-engine/unicorn
This commit is contained in:
commit
ab337ef65a
@ -39,9 +39,9 @@ const (
|
||||
ERR_HANDLE = 3
|
||||
ERR_MODE = 4
|
||||
ERR_VERSION = 5
|
||||
ERR_MEM_READ = 6
|
||||
ERR_MEM_WRITE = 7
|
||||
ERR_MEM_FETCH = 8
|
||||
ERR_READ_INVALID = 6
|
||||
ERR_WRITE_INVALID = 7
|
||||
ERR_FETCH_INVALID = 8
|
||||
ERR_CODE_INVALID = 9
|
||||
ERR_HOOK = 10
|
||||
ERR_INSN_INVALID = 11
|
||||
@ -49,7 +49,10 @@ const (
|
||||
ERR_WRITE_PROT = 13
|
||||
ERR_READ_PROT = 14
|
||||
ERR_EXEC_PROT = 15
|
||||
ERR_INVAL = 16
|
||||
ERR_ARG = 16
|
||||
ERR_READ_UNALIGNED = 17
|
||||
ERR_WRITE_UNALIGNED = 18
|
||||
ERR_FETCH_UNALIGNED = 19
|
||||
MEM_READ = 16
|
||||
MEM_WRITE = 17
|
||||
MEM_READ_WRITE = 18
|
||||
|
@ -49,8 +49,8 @@ func TestX86InvalidRead(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = mu.Start(ADDRESS, ADDRESS+uint64(len(code)))
|
||||
if err.(UcError) != ERR_MEM_READ {
|
||||
t.Fatal("Expected ERR_MEM_READ")
|
||||
if err.(UcError) != ERR_READ_INVALID {
|
||||
t.Fatal("Expected ERR_READ_INVALID")
|
||||
}
|
||||
ecx, _ := mu.RegRead(X86_REG_ECX)
|
||||
edx, _ := mu.RegRead(X86_REG_EDX)
|
||||
@ -66,8 +66,8 @@ func TestX86InvalidWrite(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = mu.Start(ADDRESS, ADDRESS+uint64(len(code)))
|
||||
if err.(UcError) != ERR_MEM_WRITE {
|
||||
t.Fatal("Expected ERR_MEM_WRITE")
|
||||
if err.(UcError) != ERR_WRITE_INVALID {
|
||||
t.Fatal("Expected ERR_WRITE_INVALID")
|
||||
}
|
||||
ecx, _ := mu.RegRead(X86_REG_ECX)
|
||||
edx, _ := mu.RegRead(X86_REG_EDX)
|
||||
|
@ -76,7 +76,7 @@ public class Sample_sparc {
|
||||
System.out.print("Emulate SPARC code\n");
|
||||
|
||||
// Initialize emulator in Sparc mode
|
||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_BIG_ENDIAN);
|
||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_32);
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
|
||||
|
@ -41,9 +41,9 @@ public interface UnicornConst {
|
||||
public static final int UC_ERR_HANDLE = 3;
|
||||
public static final int UC_ERR_MODE = 4;
|
||||
public static final int UC_ERR_VERSION = 5;
|
||||
public static final int UC_ERR_MEM_READ = 6;
|
||||
public static final int UC_ERR_MEM_WRITE = 7;
|
||||
public static final int UC_ERR_MEM_FETCH = 8;
|
||||
public static final int UC_ERR_READ_INVALID = 6;
|
||||
public static final int UC_ERR_WRITE_INVALID = 7;
|
||||
public static final int UC_ERR_FETCH_INVALID = 8;
|
||||
public static final int UC_ERR_CODE_INVALID = 9;
|
||||
public static final int UC_ERR_HOOK = 10;
|
||||
public static final int UC_ERR_INSN_INVALID = 11;
|
||||
@ -51,7 +51,7 @@ public interface UnicornConst {
|
||||
public static final int UC_ERR_WRITE_PROT = 13;
|
||||
public static final int UC_ERR_READ_PROT = 14;
|
||||
public static final int UC_ERR_EXEC_PROT = 15;
|
||||
public static final int UC_ERR_INVAL = 16;
|
||||
public static final int UC_ERR_ARG = 16;
|
||||
public static final int UC_MEM_READ = 16;
|
||||
public static final int UC_MEM_WRITE = 17;
|
||||
public static final int UC_MEM_READ_WRITE = 18;
|
||||
|
@ -28,7 +28,7 @@ def test_sparc():
|
||||
print("Emulate SPARC code")
|
||||
try:
|
||||
# Initialize emulator in SPARC EB mode
|
||||
mu = Uc(UC_ARCH_SPARC, UC_MODE_BIG_ENDIAN)
|
||||
mu = Uc(UC_ARCH_SPARC, UC_MODE_32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
@ -37,9 +37,9 @@ UC_ERR_ARCH = 2
|
||||
UC_ERR_HANDLE = 3
|
||||
UC_ERR_MODE = 4
|
||||
UC_ERR_VERSION = 5
|
||||
UC_ERR_MEM_READ = 6
|
||||
UC_ERR_MEM_WRITE = 7
|
||||
UC_ERR_MEM_FETCH = 8
|
||||
UC_ERR_READ_INVALID = 6
|
||||
UC_ERR_WRITE_INVALID = 7
|
||||
UC_ERR_FETCH_INVALID = 8
|
||||
UC_ERR_CODE_INVALID = 9
|
||||
UC_ERR_HOOK = 10
|
||||
UC_ERR_INSN_INVALID = 11
|
||||
@ -47,7 +47,10 @@ UC_ERR_MAP = 12
|
||||
UC_ERR_WRITE_PROT = 13
|
||||
UC_ERR_READ_PROT = 14
|
||||
UC_ERR_EXEC_PROT = 15
|
||||
UC_ERR_INVAL = 16
|
||||
UC_ERR_ARG = 16
|
||||
UC_ERR_READ_UNALIGNED = 17
|
||||
UC_ERR_WRITE_UNALIGNED = 18
|
||||
UC_ERR_FETCH_UNALIGNED = 19
|
||||
UC_MEM_READ = 16
|
||||
UC_MEM_WRITE = 17
|
||||
UC_MEM_READ_WRITE = 18
|
||||
|
@ -111,17 +111,20 @@ typedef enum uc_err {
|
||||
UC_ERR_HANDLE, // Invalid handle
|
||||
UC_ERR_MODE, // Invalid/unsupported mode: uc_open()
|
||||
UC_ERR_VERSION, // Unsupported version (bindings)
|
||||
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_FETCH, // Quit emulation due to invalid memory FETCH: uc_emu_start()
|
||||
UC_ERR_READ_INVALID, // Quit emulation due to invalid memory READ: uc_emu_start()
|
||||
UC_ERR_WRITE_INVALID, // Quit emulation due to invalid memory WRITE: uc_emu_start()
|
||||
UC_ERR_FETCH_INVALID, // 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_HOOK, // Invalid hook type: uc_hook_add()
|
||||
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start()
|
||||
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
|
||||
UC_ERR_WRITE_PROT, // Quit emulation due to UC_PROT_WRITE violation: uc_emu_start()
|
||||
UC_ERR_READ_PROT, // Quit emulation due to UC_PROT_READ violation: uc_emu_start()
|
||||
UC_ERR_EXEC_PROT, // Quit emulation due to UC_PROT_EXEC violation: uc_emu_start()
|
||||
UC_ERR_INVAL, // Inavalid argument provided to uc_xxx function (See specific function API)
|
||||
UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start()
|
||||
UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start()
|
||||
UC_ERR_EXEC_PROT, // Quit emulation due to UC_MEM_EXEC_PROT violation: uc_emu_start()
|
||||
UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific function API)
|
||||
UC_ERR_READ_UNALIGNED, // Unaligned read
|
||||
UC_ERR_WRITE_UNALIGNED, // Unaligned write
|
||||
UC_ERR_FETCH_UNALIGNED, // Unaligned fetch
|
||||
} uc_err;
|
||||
|
||||
|
||||
@ -408,12 +411,12 @@ typedef enum uc_prot {
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@address: starting address of the new memory region to be mapped in.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_INVAL error.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the new memory region to be mapped in.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_INVAL error.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
@perms: Permissions for the newly mapped region.
|
||||
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
||||
or this will return with UC_ERR_INVAL error.
|
||||
or this will return with UC_ERR_ARG error.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@ -427,9 +430,9 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms);
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@address: starting address of the memory region to be unmapped.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_INVAL error.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the memory region to be modified.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_INVAL error.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@ -443,12 +446,12 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size);
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@address: starting address of the memory region to be modified.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_INVAL error.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
|
||||
@size: size of the memory region to be modified.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_INVAL error.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
|
||||
@perms: New permissions for the mapped region.
|
||||
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
||||
or this will return with UC_ERR_INVAL error.
|
||||
or this will return with UC_ERR_ARG error.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
|
@ -51,7 +51,5 @@ void mips_machine_init(struct uc_struct *uc)
|
||||
.arch = UC_ARCH_MIPS,
|
||||
};
|
||||
|
||||
printf(">>> mips_machine_init\n");
|
||||
|
||||
qemu_register_machine(uc, &mips_machine, TYPE_MACHINE, NULL);
|
||||
}
|
||||
|
@ -177,27 +177,35 @@ 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;
|
||||
|
||||
struct uc_struct *uc = env->uc;
|
||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||
|
||||
// memory can be unmapped while reading or fetching
|
||||
if (mr == NULL) {
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
// Unicorn: callback on fetch from unmapped memory
|
||||
if (mr == NULL) { // memory is not mapped
|
||||
mem_access = UC_MEM_FETCH;
|
||||
error_code = UC_ERR_FETCH_INVALID;
|
||||
#else
|
||||
mem_access = UC_MEM_READ;
|
||||
error_code = UC_ERR_READ_INVALID;
|
||||
#endif
|
||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
uc, UC_MEM_FETCH, addr, DATA_SIZE, 0,
|
||||
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 {
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_FETCH;
|
||||
env->invalid_error = error_code;
|
||||
// printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#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)(
|
||||
@ -223,22 +231,6 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
}
|
||||
}
|
||||
|
||||
// Unicorn: callback on invalid memory
|
||||
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)(
|
||||
env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_READ;
|
||||
// printf("***** Invalid memory read at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(env->uc->current_cpu);
|
||||
return 0;
|
||||
} else {
|
||||
env->invalid_error = UC_ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)(
|
||||
@ -263,8 +255,16 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
//cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
// mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
env->invalid_error = UC_ERR_FETCH_UNALIGNED;
|
||||
#else
|
||||
env->invalid_error = UC_ERR_READ_UNALIGNED;
|
||||
#endif
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (!VICTIM_TLB_HIT(ADDR_READ)) {
|
||||
@ -283,7 +283,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
ioaddr = env->iotlb[mmu_idx][index];
|
||||
if (ioaddr == 0) {
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_READ;
|
||||
env->invalid_error = UC_ERR_READ_INVALID;
|
||||
// printf("Invalid memory read at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(env->uc->current_cpu);
|
||||
return 0;
|
||||
@ -307,8 +307,16 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
unsigned shift;
|
||||
do_unaligned_access:
|
||||
#ifdef ALIGNED_ONLY
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
//cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
// mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
env->invalid_error = UC_ERR_FETCH_UNALIGNED;
|
||||
#else
|
||||
env->invalid_error = UC_ERR_READ_UNALIGNED;
|
||||
#endif
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
#endif
|
||||
addr1 = addr & ~(DATA_SIZE - 1);
|
||||
addr2 = addr1 + DATA_SIZE;
|
||||
@ -326,8 +334,16 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
/* Handle aligned access or unaligned access in the same page. */
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
//cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
// mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
env->invalid_error = UC_ERR_FETCH_UNALIGNED;
|
||||
#else
|
||||
env->invalid_error = UC_ERR_READ_UNALIGNED;
|
||||
#endif
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -351,27 +367,35 @@ 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;
|
||||
|
||||
struct uc_struct *uc = env->uc;
|
||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||
|
||||
// memory can be unmapped while reading or fetching
|
||||
if (mr == NULL) {
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
// Unicorn: callback on fetch from unmapped memory
|
||||
if (mr == NULL) { // memory is not mapped
|
||||
mem_access = UC_MEM_FETCH;
|
||||
error_code = UC_ERR_FETCH_INVALID;
|
||||
#else
|
||||
mem_access = UC_MEM_READ;
|
||||
error_code = UC_ERR_READ_INVALID;
|
||||
#endif
|
||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
uc, UC_MEM_FETCH, addr, DATA_SIZE, 0,
|
||||
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 {
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_FETCH;
|
||||
env->invalid_error = error_code;
|
||||
// printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#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)(
|
||||
@ -397,22 +421,6 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
}
|
||||
}
|
||||
|
||||
// Unicorn: callback on invalid memory
|
||||
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)(
|
||||
env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_READ;
|
||||
// printf("***** Invalid memory read at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(env->uc->current_cpu);
|
||||
return 0;
|
||||
} else {
|
||||
env->invalid_error = UC_ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)(
|
||||
@ -436,8 +444,16 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
//cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
// mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
env->invalid_error = UC_ERR_FETCH_UNALIGNED;
|
||||
#else
|
||||
env->invalid_error = UC_ERR_READ_UNALIGNED;
|
||||
#endif
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (!VICTIM_TLB_HIT(ADDR_READ)) {
|
||||
@ -457,7 +473,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
|
||||
if (ioaddr == 0) {
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_READ;
|
||||
env->invalid_error = UC_ERR_READ_INVALID;
|
||||
// printf("Invalid memory read at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(env->uc->current_cpu);
|
||||
return 0;
|
||||
@ -479,8 +495,16 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
unsigned shift;
|
||||
do_unaligned_access:
|
||||
#ifdef ALIGNED_ONLY
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
//cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
// mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
env->invalid_error = UC_ERR_FETCH_UNALIGNED;
|
||||
#else
|
||||
env->invalid_error = UC_ERR_READ_UNALIGNED;
|
||||
#endif
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
#endif
|
||||
addr1 = addr & ~(DATA_SIZE - 1);
|
||||
addr2 = addr1 + DATA_SIZE;
|
||||
@ -498,8 +522,16 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
||||
/* Handle aligned access or unaligned access in the same page. */
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
//cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
// mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
#if defined(SOFTMMU_CODE_ACCESS)
|
||||
env->invalid_error = UC_ERR_FETCH_UNALIGNED;
|
||||
#else
|
||||
env->invalid_error = UC_ERR_READ_UNALIGNED;
|
||||
#endif
|
||||
cpu_exit(uc->current_cpu);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -582,7 +614,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_WRITE;
|
||||
env->invalid_error = UC_ERR_WRITE_INVALID;
|
||||
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
@ -615,8 +647,12 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
//cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
// mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_WRITE_UNALIGNED;
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!VICTIM_TLB_HIT(addr_write)) {
|
||||
@ -634,7 +670,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
ioaddr = env->iotlb[mmu_idx][index];
|
||||
if (ioaddr == 0) {
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_WRITE;
|
||||
env->invalid_error = UC_ERR_WRITE_INVALID;
|
||||
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(env->uc->current_cpu);
|
||||
return;
|
||||
@ -656,6 +692,10 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
#ifdef ALIGNED_ONLY
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_WRITE_UNALIGNED;
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
#endif
|
||||
/* XXX: not efficient, but simple */
|
||||
/* Note: relies on the fact that tlb_fill() does not remove the
|
||||
@ -678,6 +718,10 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_WRITE_UNALIGNED;
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -716,7 +760,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_WRITE;
|
||||
env->invalid_error = UC_ERR_WRITE_INVALID;
|
||||
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
@ -751,6 +795,10 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_WRITE_UNALIGNED;
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!VICTIM_TLB_HIT(addr_write)) {
|
||||
@ -768,7 +816,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
ioaddr = env->iotlb[mmu_idx][index];
|
||||
if (ioaddr == 0) {
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_MEM_WRITE;
|
||||
env->invalid_error = UC_ERR_WRITE_INVALID;
|
||||
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
||||
cpu_exit(env->uc->current_cpu);
|
||||
return;
|
||||
@ -790,6 +838,10 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
#ifdef ALIGNED_ONLY
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_WRITE_UNALIGNED;
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
#endif
|
||||
/* XXX: not efficient, but simple */
|
||||
/* Note: relies on the fact that tlb_fill() does not remove the
|
||||
@ -812,6 +864,10 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
env->invalid_addr = addr;
|
||||
env->invalid_error = UC_ERR_WRITE_UNALIGNED;
|
||||
cpu_exit(uc->current_cpu);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -156,6 +156,5 @@ void mips_cpu_register_types(void *opaque)
|
||||
.class_init = mips_cpu_class_init,
|
||||
};
|
||||
|
||||
printf(">>> mips_cpu_register_types\n");
|
||||
type_register_static(opaque, &mips_cpu_type_info);
|
||||
}
|
||||
|
29
regress/mips_branch_delay.py
Executable file
29
regress/mips_branch_delay.py
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/python
|
||||
from capstone import *
|
||||
from unicorn import *
|
||||
from unicorn.mips_const import *
|
||||
|
||||
md = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_LITTLE_ENDIAN)
|
||||
|
||||
def disas(code, addr):
|
||||
for i in md.disasm(code, addr):
|
||||
print '0x%x: %s %s' % (i.address, str(i.bytes).encode('hex'), i.op_str)
|
||||
|
||||
def hook_code(uc, addr, size, _):
|
||||
mem = str(uc.mem_read(addr, size))
|
||||
disas(mem, addr)
|
||||
|
||||
CODE = 0x400000
|
||||
asm = '0000a4126a00822800000000'.decode('hex')
|
||||
|
||||
print 'Input instructions:'
|
||||
disas(asm, CODE)
|
||||
print
|
||||
|
||||
print 'Hooked instructions:'
|
||||
|
||||
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN)
|
||||
uc.hook_add(UC_HOOK_CODE, hook_code)
|
||||
uc.mem_map(CODE, 0x1000)
|
||||
uc.mem_write(CODE, asm)
|
||||
uc.emu_start(CODE, CODE + len(asm))
|
@ -6,24 +6,33 @@ def hook_intr(uc, intno, _):
|
||||
print 'interrupt', intno
|
||||
|
||||
CODE = 0x400000
|
||||
asm = '0000a48f'.decode('hex')
|
||||
asm = '0000a48f'.decode('hex') # lw $a0, ($sp)
|
||||
|
||||
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN)
|
||||
uc.hook_add(UC_HOOK_INTR, hook_intr)
|
||||
uc.mem_map(CODE, 0x1000)
|
||||
uc.mem_write(CODE, asm)
|
||||
|
||||
print 'unaligned access (exc 12)'
|
||||
uc.reg_write(UC_MIPS_REG_SP, 0x01)
|
||||
uc.emu_start(CODE, CODE + len(asm), 300)
|
||||
print
|
||||
try:
|
||||
print 'unaligned access (exc 12)'
|
||||
uc.reg_write(UC_MIPS_REG_SP, 0x400001)
|
||||
uc.emu_start(CODE, CODE + len(asm), 300)
|
||||
print
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
print 'dunno (exc 26)'
|
||||
uc.reg_write(UC_MIPS_REG_SP, 0xFFFFFFF0)
|
||||
uc.emu_start(CODE, CODE + len(asm), 200)
|
||||
print
|
||||
try:
|
||||
print 'dunno (exc 26)'
|
||||
uc.reg_write(UC_MIPS_REG_SP, 0xFFFFFFF0)
|
||||
uc.emu_start(CODE, CODE + len(asm), 200)
|
||||
print
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
print 'unassigned access (exc 28)'
|
||||
uc.reg_write(UC_MIPS_REG_SP, 0x80000000)
|
||||
uc.emu_start(CODE, CODE + len(asm), 100)
|
||||
print
|
||||
try:
|
||||
print 'unassigned access (exc 28)'
|
||||
uc.reg_write(UC_MIPS_REG_SP, 0x80000000)
|
||||
uc.emu_start(CODE, CODE + len(asm), 100)
|
||||
print
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
@ -3,7 +3,7 @@
|
||||
from unicorn import *
|
||||
from unicorn.sparc_const import *
|
||||
|
||||
uc = Uc(UC_ARCH_SPARC, UC_MODE_BIG_ENDIAN)
|
||||
uc = Uc(UC_ARCH_SPARC, UC_MODE_32)
|
||||
uc.reg_write(UC_SPARC_REG_SP, 100)
|
||||
uc.reg_write(UC_SPARC_REG_FP, 100)
|
||||
print 'writing sp = 100, fp = 100'
|
||||
|
@ -38,7 +38,7 @@ static void test_sparc(void)
|
||||
printf("Emulate SPARC code\n");
|
||||
|
||||
// Initialize emulator in Sparc mode
|
||||
err = uc_open(UC_ARCH_SPARC, UC_MODE_BIG_ENDIAN, &uc);
|
||||
err = uc_open(UC_ARCH_SPARC, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
47
uc.c
47
uc.c
@ -69,12 +69,12 @@ const char *uc_strerror(uc_err code)
|
||||
return "Invalid mode (UC_ERR_MODE)";
|
||||
case UC_ERR_VERSION:
|
||||
return "Different API version between core & binding (UC_ERR_VERSION)";
|
||||
case UC_ERR_MEM_READ:
|
||||
return "Invalid memory read (UC_ERR_MEM_READ)";
|
||||
case 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_READ_INVALID:
|
||||
return "Invalid memory read (UC_ERR_READ_INVALID)";
|
||||
case UC_ERR_WRITE_INVALID:
|
||||
return "Invalid memory write (UC_ERR_WRITE_INVALID)";
|
||||
case UC_ERR_FETCH_INVALID:
|
||||
return "Invalid memory fetch (UC_ERR_FETCH_INVALID)";
|
||||
case UC_ERR_CODE_INVALID:
|
||||
return "Invalid code address (UC_ERR_CODE_INVALID)";
|
||||
case UC_ERR_HOOK:
|
||||
@ -89,8 +89,15 @@ const char *uc_strerror(uc_err code)
|
||||
return "Read from non-readable memory (UC_ERR_READ_PROT)";
|
||||
case UC_ERR_EXEC_PROT:
|
||||
return "Fetch from non-executable memory (UC_ERR_EXEC_PROT)";
|
||||
case UC_ERR_INVAL:
|
||||
return "Invalid argumet (UC_ERR_INVAL)";
|
||||
case UC_ERR_ARG:
|
||||
return "Invalid argumet (UC_ERR_ARG)";
|
||||
|
||||
case UC_ERR_READ_UNALIGNED:
|
||||
return "Read from unaligned memory (UC_ERR_READ_UNALIGNED)";
|
||||
case UC_ERR_WRITE_UNALIGNED:
|
||||
return "Write to unaligned memory (UC_ERR_WRITE_UNALIGNED)";
|
||||
case UC_ERR_FETCH_UNALIGNED:
|
||||
return "Fetch from unaligned memory (UC_ERR_FETCH_UNALIGNED)";
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,7 +343,7 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size)
|
||||
uint8_t *bytes = _bytes;
|
||||
|
||||
if (!check_mem_area(uc, address, size))
|
||||
return UC_ERR_MEM_READ;
|
||||
return UC_ERR_READ_INVALID;
|
||||
|
||||
size_t count = 0, len;
|
||||
|
||||
@ -357,7 +364,7 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size)
|
||||
if (count == size)
|
||||
return UC_ERR_OK;
|
||||
else
|
||||
return UC_ERR_MEM_READ;
|
||||
return UC_ERR_READ_INVALID;
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
@ -366,7 +373,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t
|
||||
const uint8_t *bytes = _bytes;
|
||||
|
||||
if (!check_mem_area(uc, address, size))
|
||||
return UC_ERR_MEM_WRITE;
|
||||
return UC_ERR_WRITE_INVALID;
|
||||
|
||||
size_t count = 0, len;
|
||||
|
||||
@ -397,7 +404,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t
|
||||
if (count == size)
|
||||
return UC_ERR_OK;
|
||||
else
|
||||
return UC_ERR_MEM_WRITE;
|
||||
return UC_ERR_WRITE_INVALID;
|
||||
}
|
||||
|
||||
#define TIMEOUT_STEP 2 // microseconds
|
||||
@ -563,19 +570,19 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms)
|
||||
|
||||
if (size == 0)
|
||||
// invalid memory mapping
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
// address must be aligned to uc->target_page_size
|
||||
if ((address & uc->target_page_align) != 0)
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
// size must be multiple of uc->target_page_size
|
||||
if ((size & uc->target_page_align) != 0)
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
// check for only valid permissions
|
||||
if ((perms & ~UC_PROT_ALL) != 0)
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow
|
||||
regions = (MemoryRegion**)realloc(uc->mapped_blocks,
|
||||
@ -721,15 +728,15 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3
|
||||
|
||||
// address must be aligned to uc->target_page_size
|
||||
if ((address & uc->target_page_align) != 0)
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
// size must be multiple of uc->target_page_size
|
||||
if ((size & uc->target_page_align) != 0)
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
// check for only valid permissions
|
||||
if ((perms & ~UC_PROT_ALL) != 0)
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
// check that user's entire requested block is mapped
|
||||
if (!check_mem_area(uc, address, size))
|
||||
@ -768,7 +775,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||
|
||||
// address must be aligned to uc->target_page_size
|
||||
if ((address & uc->target_page_align) != 0)
|
||||
return UC_ERR_INVAL;
|
||||
return UC_ERR_ARG;
|
||||
|
||||
// size must be multiple of uc->target_page_size
|
||||
if ((size & uc->target_page_align) != 0)
|
||||
|
Loading…
Reference in New Issue
Block a user