diff --git a/include/uc_priv.h b/include/uc_priv.h index 589a655..c4e0e17 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -32,6 +32,8 @@ typedef struct ModuleEntry { typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList; +typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result); + // return 0 on success, -1 on failure typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int regid, void *value); typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int regid, const void *value); @@ -93,6 +95,7 @@ struct uc_struct { struct CPUTailQ cpus; // qemu/cpu-exec.c uc_err errnum; // qemu/cpu-exec.c AddressSpace as; + query_t query; reg_read_t reg_read; reg_write_t reg_write; reg_reset_t reg_reset; diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index a6bedfa..d5cd142 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -255,6 +255,12 @@ typedef struct uc_mem_region { uint32_t perms; // memory permissions of the region } uc_mem_region; +// All type of queries for uc_query() API. +typedef enum uc_query_type { + // Query current hardware mode for ARM. Return 1 for Thumb, 0 for ARM + UC_QUERY_ARM_MODE = 1, +} uc_query_type; + /* Return combined API version & major and minor version numbers. @@ -315,6 +321,18 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **uc); UNICORN_EXPORT uc_err uc_close(uc_engine *uc); +/* + Query internal status of engine. + + @uc: handle returned by uc_open() + @type: query type + @result: status retrieved + + @return: error code of uc_err enum type (UC_ERR_*, see above) +*/ +UNICORN_EXPORT +uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result); + /* Report the last error number when some API function fail. Like glibc's errno, uc_errno might not retain its old value once accessed. diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 5065c0f..0a64d15 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -108,6 +108,19 @@ static bool arm_stop_interrupt(int intno) } } +static uc_err arm_query(struct uc_struct *uc, uc_query_type type, size_t *result) +{ + CPUState *mycpu = first_cpu; + + switch(type) { + case UC_QUERY_ARM_MODE: + *result = (ARM_CPU(uc, mycpu)->env.thumb != 0); + return UC_ERR_OK; + default: + return UC_ERR_ARG; + } +} + void arm_uc_init(struct uc_struct* uc) { register_accel_types(uc); @@ -118,5 +131,6 @@ void arm_uc_init(struct uc_struct* uc) uc->reg_reset = arm_reg_reset; uc->set_pc = arm_set_pc; uc->stop_interrupt = arm_stop_interrupt; + uc->query = arm_query; uc_common_init(uc); } diff --git a/uc.c b/uc.c index 95a9c48..d93fa4e 100644 --- a/uc.c +++ b/uc.c @@ -1190,3 +1190,15 @@ uint32_t uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count) return UC_ERR_OK; } +UNICORN_EXPORT +uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) +{ + switch(uc->arch) { + case UC_ARCH_ARM: + return uc->query(uc, type, result); + default: + return UC_ERR_ARG; + } + + return UC_ERR_OK; +}