This commit is contained in:
Nguyen Anh Quynh 2015-09-11 15:58:58 +08:00
commit ab337ef65a
15 changed files with 238 additions and 131 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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).

View File

@ -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);
}

View File

@ -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

View File

@ -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
View 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))

View File

@ -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)

View File

@ -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'

View File

@ -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
View File

@ -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)