diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index f2c028b1..20c42bc9 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -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 diff --git a/bindings/go/unicorn/x86_test.go b/bindings/go/unicorn/x86_test.go index 302a105d..fe72f2e3 100644 --- a/bindings/go/unicorn/x86_test.go +++ b/bindings/go/unicorn/x86_test.go @@ -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) diff --git a/bindings/java/samples/Sample_sparc.java b/bindings/java/samples/Sample_sparc.java index 60735d96..60298979 100644 --- a/bindings/java/samples/Sample_sparc.java +++ b/bindings/java/samples/Sample_sparc.java @@ -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); diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 92122129..ba85074b 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -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; diff --git a/bindings/python/sample_sparc.py b/bindings/python/sample_sparc.py index c1a4a4d9..307ba936 100755 --- a/bindings/python/sample_sparc.py +++ b/bindings/python/sample_sparc.py @@ -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) diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 68589235..7999afc1 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -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 diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 9c1e37e0..08e01028 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -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). diff --git a/qemu/hw/mips/mips_r4k.c b/qemu/hw/mips/mips_r4k.c index 13a22e55..739d8029 100644 --- a/qemu/hw/mips/mips_r4k.c +++ b/qemu/hw/mips/mips_r4k.c @@ -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); } diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index 7e366bf3..9e8afd46 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -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 diff --git a/qemu/target-mips/cpu.c b/qemu/target-mips/cpu.c index 36bc042e..2cb6e14a 100644 --- a/qemu/target-mips/cpu.c +++ b/qemu/target-mips/cpu.c @@ -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); } diff --git a/regress/mips_branch_delay.py b/regress/mips_branch_delay.py new file mode 100755 index 00000000..50a71a6f --- /dev/null +++ b/regress/mips_branch_delay.py @@ -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)) diff --git a/regress/mips_except.py b/regress/mips_except.py index f24b5b85..28c8001e 100755 --- a/regress/mips_except.py +++ b/regress/mips_except.py @@ -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) diff --git a/regress/sparc_reg.py b/regress/sparc_reg.py index 0857d671..73858360 100755 --- a/regress/sparc_reg.py +++ b/regress/sparc_reg.py @@ -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' diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index 2cdc4915..3f253ff1 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -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)); diff --git a/uc.c b/uc.c index 0ea5cf03..76a3f5f7 100644 --- a/uc.c +++ b/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)