diff --git a/include/uc_priv.h b/include/uc_priv.h index d038c51b..9d88c233 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -267,7 +267,8 @@ struct uc_struct { unsigned int alloc_hint; /* qemu/exec-vary.c */ TargetPageBits *init_target_page; - int target_bits; // User defined page bits by uc_ctl + int target_bits; // User defined page bits by uc_ctl + int cpu_model; BounceBuffer bounce; // qemu/cpu-exec.c volatile sig_atomic_t exit_request; // qemu/cpu-exec.c /* qemu/accel/tcg/cpu-exec-common.c */ diff --git a/include/unicorn/arm.h b/include/unicorn/arm.h index d9cf4949..6f5b3ecc 100644 --- a/include/unicorn/arm.h +++ b/include/unicorn/arm.h @@ -30,9 +30,9 @@ typedef enum uc_cpu_arm { UC_CPU_ARM_CORTEX_M33, UC_CPU_ARM_CORTEX_R5, UC_CPU_ARM_CORTEX_R5F, + UC_CPU_ARM_CORTEX_A7, UC_CPU_ARM_CORTEX_A8, UC_CPU_ARM_CORTEX_A9, - UC_CPU_ARM_CORTEX_A7, UC_CPU_ARM_CORTEX_A15, UC_CPU_ARM_TI925T, UC_CPU_ARM_SA1100, diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 37dea8ae..2ed44833 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -513,7 +513,7 @@ typedef enum uc_control_type { // Note this option can only be set before any Unicorn // API is called except for uc_open. // Write: @args = (int) - // Read: @args = (int) + // Read: @args = (int*) UC_CTL_CPU_MODEL, // Request a tb cache at a specific address // Read: @args = (uint64_t, uc_tb*) diff --git a/qemu/target/arm/cpu.c b/qemu/target/arm/cpu.c index d391ad21..207e1ec9 100644 --- a/qemu/target/arm/cpu.c +++ b/qemu/target/arm/cpu.c @@ -2017,33 +2017,32 @@ static void arm_cpu_instance_init(CPUState *obj) ARMCPU *cpu_arm_init(struct uc_struct *uc) { -#if !defined(TARGET_AARCH64) - int i; - char *cpu_model; -#endif ARMCPU *cpu; CPUState *cs; CPUClass *cc; -#if !defined(TARGET_AARCH64) - if (uc->mode & UC_MODE_MCLASS) { - cpu_model = "cortex-m33"; - } else if (uc->mode & UC_MODE_ARM926) { - cpu_model = "arm926"; - } else if (uc->mode & UC_MODE_ARM946) { - cpu_model = "arm946"; - } else if (uc->mode & UC_MODE_ARM1176) { - cpu_model = "arm1176"; - } else { - cpu_model = "cortex-a15"; - } -#endif - cpu = calloc(1, sizeof(*cpu)); if (cpu == NULL) { return NULL; } +#if !defined(TARGET_AARCH64) + if (uc->mode & UC_MODE_MCLASS) { + uc->cpu_model = 11; + } else if (uc->mode & UC_MODE_ARM926) { + uc->cpu_model = 0; + } else if (uc->mode & UC_MODE_ARM946) { + uc->cpu_model = 1; + } else if (uc->mode & UC_MODE_ARM1176) { + uc->cpu_model = 5; + } else if (uc->cpu_model == INT_MAX) { + uc->cpu_model = 17; // cortex-a15 + } else if (uc->cpu_model >= ARR_SIZE(arm_cpus)) { + free(cpu); + return NULL; + } +#endif + cs = (CPUState *)cpu; cc = (CPUClass *)&cpu->cc; cs->cc = cc; @@ -2064,20 +2063,11 @@ ARMCPU *cpu_arm_init(struct uc_struct *uc) #if !defined(TARGET_AARCH64) /* init ARM types */ - for (i = 0; i < ARRAY_SIZE(arm_cpus); i++) { - if (strcmp(cpu_model, arm_cpus[i].name) == 0) { - if (arm_cpus[i].class_init) { - arm_cpus[i].class_init(uc, cc, uc); - } - if (arm_cpus[i].initfn) { - arm_cpus[i].initfn(uc, cs); - } - break; - } + if (arm_cpus[uc->cpu_model].class_init) { + arm_cpus[uc->cpu_model].class_init(uc, cc, uc); } - if (i == ARRAY_SIZE(arm_cpus)) { - free(cpu); - return NULL; + if (arm_cpus[uc->cpu_model].initfn) { + arm_cpus[uc->cpu_model].initfn(uc, cs); } #endif diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index c5f464a4..8138de8e 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -160,7 +160,6 @@ static void test_uc_ctl_change_page_size() { uc_engine *uc; uc_engine *uc2; - int r_pc; OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc)); OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc2)); @@ -174,6 +173,40 @@ static void test_uc_ctl_change_page_size() OK(uc_close(uc2)); } +// Copy from test_arm.c but with new API. +static void test_uc_ctl_arm_cpu() { + uc_engine *uc; + int r_control, r_msp, r_psp; + + OK(uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc)); + + OK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_M7)); + + r_control = 0; // Make sure we are using MSP. + OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control)); + + r_msp = 0x1000; + OK(uc_reg_write(uc, UC_ARM_REG_R13, &r_msp)); + + r_control = 0b10; // Make the switch. + OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control)); + + OK(uc_reg_read(uc, UC_ARM_REG_R13, &r_psp)); + TEST_CHECK(r_psp != r_msp); + + r_psp = 0x2000; + OK(uc_reg_write(uc, UC_ARM_REG_R13, &r_psp)); + + r_control = 0; // Switch again + OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control)); + + OK(uc_reg_read(uc, UC_ARM_REG_R13, &r_msp)); + TEST_CHECK(r_psp != r_msp); + TEST_CHECK(r_msp == 0x1000); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_page_size", test_uc_ctl_page_size}, {"test_uc_ctl_arch", test_uc_ctl_arch}, @@ -181,4 +214,5 @@ TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_exits", test_uc_ctl_exits}, {"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache}, {"test_uc_ctl_change_page_size", test_uc_ctl_change_page_size}, + {"test_uc_ctl_arm_cpu", test_uc_ctl_arm_cpu}, {NULL, NULL}}; \ No newline at end of file diff --git a/uc.c b/uc.c index 19047a38..f3fa394f 100644 --- a/uc.c +++ b/uc.c @@ -348,6 +348,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) } uc->init_done = false; + uc->cpu_model = INT_MAX; // INT_MAX means the default cpu model. *result = uc; @@ -1975,6 +1976,11 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) uint32_t page_size = va_arg(args, uint32_t); int bits = 0; + if (uc->init_done) { + err = UC_ERR_ARG; + break; + } + if (uc->arch != UC_ARCH_ARM) { err = UC_ERR_ARG; break; @@ -1996,6 +2002,7 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) } break; } + case UC_CTL_UC_USE_EXITS: { if (rw == UC_CTL_IO_WRITE) { int use_exits = va_arg(args, int); @@ -2054,10 +2061,24 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) break; } - case UC_CTL_CPU_MODEL: - // Not implemented. - err = UC_ERR_ARG; + case UC_CTL_CPU_MODEL: { + if (rw == UC_CTL_IO_READ) { + int *model = va_arg(args, int *); + *model = uc->cpu_model; + } else { + int model = va_arg(args, int); + + if (uc->init_done) { + err = UC_ERR_ARG; + break; + } + + uc->cpu_model = model; + + err = UC_ERR_OK; + } break; + } case UC_CTL_TB_REQUEST_CACHE: {