Deep copy for arm cpu state
This commit is contained in:
parent
2a3cc7a1b3
commit
19d8876e23
@ -168,6 +168,16 @@ typedef void (*uc_add_inline_hook_t)(struct uc_struct *uc, struct hook *hk,
|
||||
// Delete a hook from helper_table
|
||||
typedef void (*uc_del_inline_hook_t)(struct uc_struct *uc, struct hook *hk);
|
||||
|
||||
// Return the size of a CPU context
|
||||
typedef size_t (*uc_context_size_t)(struct uc_struct *uc);
|
||||
|
||||
// Generate a CPU context
|
||||
typedef uc_err (*uc_context_save_t)(struct uc_struct *uc, uc_context *context);
|
||||
|
||||
// Restore a CPU context
|
||||
typedef uc_err (*uc_context_restore_t)(struct uc_struct *uc,
|
||||
uc_context *context);
|
||||
|
||||
// hook list offsets
|
||||
//
|
||||
// The lowest 6 bits are used for hook type index while the others
|
||||
@ -285,6 +295,10 @@ struct uc_struct {
|
||||
uc_add_inline_hook_t add_inline_hook;
|
||||
uc_del_inline_hook_t del_inline_hook;
|
||||
|
||||
uc_context_size_t context_size;
|
||||
uc_context_save_t context_save;
|
||||
uc_context_restore_t context_restore;
|
||||
|
||||
/* only 1 cpu in unicorn,
|
||||
do not need current_cpu to handle current running cpu. */
|
||||
CPUState *cpu;
|
||||
|
@ -621,6 +621,145 @@ static int arm_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t uc_arm_context_size(struct uc_struct *uc)
|
||||
{
|
||||
size_t ret = offsetof(CPUARMState, cpu_watchpoint);
|
||||
ARMCPU *cpu = (ARMCPU *)uc->cpu;
|
||||
CPUARMState *env = (CPUARMState *)&cpu->env;
|
||||
uint32_t nr;
|
||||
|
||||
#define ARM_ENV_CHECK(field) \
|
||||
if (field) { \
|
||||
ret += sizeof(uint32_t) * (nr + 1); \
|
||||
} else { \
|
||||
ret += sizeof(uint32_t); \
|
||||
}
|
||||
|
||||
// /* PMSAv7 MPU */
|
||||
// struct {
|
||||
// uint32_t *drbar;
|
||||
// uint32_t *drsr;
|
||||
// uint32_t *dracr;
|
||||
// uint32_t rnr[M_REG_NUM_BANKS];
|
||||
// } pmsav7;
|
||||
// /* PMSAv8 MPU */
|
||||
// struct {
|
||||
// /* The PMSAv8 implementation also shares some PMSAv7 config
|
||||
// * and state:
|
||||
// * pmsav7.rnr (region number register)
|
||||
// * pmsav7_dregion (number of configured regions)
|
||||
// */
|
||||
// uint32_t *rbar[M_REG_NUM_BANKS];
|
||||
// uint32_t *rlar[M_REG_NUM_BANKS];
|
||||
// uint32_t mair0[M_REG_NUM_BANKS];
|
||||
// uint32_t mair1[M_REG_NUM_BANKS];
|
||||
// } pmsav8;
|
||||
nr = cpu->pmsav7_dregion;
|
||||
ARM_ENV_CHECK(env->pmsav7.drbar)
|
||||
ARM_ENV_CHECK(env->pmsav7.drsr)
|
||||
ARM_ENV_CHECK(env->pmsav7.dracr)
|
||||
ARM_ENV_CHECK(env->pmsav8.rbar[M_REG_NS])
|
||||
ARM_ENV_CHECK(env->pmsav8.rbar[M_REG_S])
|
||||
ARM_ENV_CHECK(env->pmsav8.rlar[M_REG_NS])
|
||||
ARM_ENV_CHECK(env->pmsav8.rlar[M_REG_S])
|
||||
|
||||
// /* v8M SAU */
|
||||
// struct {
|
||||
// uint32_t *rbar;
|
||||
// uint32_t *rlar;
|
||||
// uint32_t rnr;
|
||||
// uint32_t ctrl;
|
||||
// } sau;
|
||||
nr = cpu->sau_sregion;
|
||||
ARM_ENV_CHECK(env->sau.rbar)
|
||||
ARM_ENV_CHECK(env->sau.rlar)
|
||||
#undef ARM_ENV_CHECK
|
||||
// These fields are never used:
|
||||
// void *nvic;
|
||||
// const struct arm_boot_info *boot_info;
|
||||
// void *gicv3state;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uc_err uc_arm_context_save(struct uc_struct *uc, uc_context *context)
|
||||
{
|
||||
char *p = NULL;
|
||||
ARMCPU *cpu = (ARMCPU *)uc->cpu;
|
||||
CPUARMState *env = (CPUARMState *)&cpu->env;
|
||||
uint32_t nr = 0;
|
||||
|
||||
#define ARM_ENV_SAVE(field) \
|
||||
if (!field) { \
|
||||
*(uint32_t *)p = 0; \
|
||||
p += sizeof(uint32_t); \
|
||||
} else { \
|
||||
*(uint32_t *)p = nr; \
|
||||
p += sizeof(uint32_t); \
|
||||
memcpy(p, (void *)field, sizeof(uint32_t) * nr); \
|
||||
p += sizeof(uint32_t) * nr; \
|
||||
}
|
||||
p = context->data;
|
||||
memcpy(p, uc->cpu->env_ptr, uc->cpu_context_size);
|
||||
p += uc->cpu_context_size;
|
||||
|
||||
nr = cpu->pmsav7_dregion;
|
||||
ARM_ENV_SAVE(env->pmsav7.drbar)
|
||||
ARM_ENV_SAVE(env->pmsav7.drsr)
|
||||
ARM_ENV_SAVE(env->pmsav7.dracr)
|
||||
ARM_ENV_SAVE(env->pmsav8.rbar[M_REG_NS])
|
||||
ARM_ENV_SAVE(env->pmsav8.rbar[M_REG_S])
|
||||
ARM_ENV_SAVE(env->pmsav8.rlar[M_REG_NS])
|
||||
ARM_ENV_SAVE(env->pmsav8.rlar[M_REG_S])
|
||||
|
||||
nr = cpu->sau_sregion;
|
||||
ARM_ENV_SAVE(env->sau.rbar)
|
||||
ARM_ENV_SAVE(env->sau.rlar)
|
||||
|
||||
#undef ARM_ENV_SAVE
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static uc_err uc_arm_context_restore(struct uc_struct *uc, uc_context *context)
|
||||
{
|
||||
char *p = NULL;
|
||||
ARMCPU *cpu = (ARMCPU *)uc->cpu;
|
||||
CPUARMState *env = (CPUARMState *)&cpu->env;
|
||||
uint32_t nr, ctx_nr;
|
||||
|
||||
#define ARM_ENV_RESTORE(field) \
|
||||
ctx_nr = *(uint32_t *)p; \
|
||||
if (ctx_nr != 0) { \
|
||||
p += sizeof(uint32_t); \
|
||||
if (field && ctx_nr == nr) { \
|
||||
memcpy(field, p, sizeof(uint32_t) * ctx_nr); \
|
||||
} \
|
||||
p += sizeof(uint32_t) * ctx_nr; \
|
||||
} else { \
|
||||
p += sizeof(uint32_t); \
|
||||
}
|
||||
|
||||
p = context->data;
|
||||
memcpy(uc->cpu->env_ptr, p, uc->cpu_context_size);
|
||||
p += uc->cpu_context_size;
|
||||
|
||||
nr = cpu->pmsav7_dregion;
|
||||
ARM_ENV_RESTORE(env->pmsav7.drbar)
|
||||
ARM_ENV_RESTORE(env->pmsav7.drsr)
|
||||
ARM_ENV_RESTORE(env->pmsav7.dracr)
|
||||
ARM_ENV_RESTORE(env->pmsav8.rbar[M_REG_NS])
|
||||
ARM_ENV_RESTORE(env->pmsav8.rbar[M_REG_S])
|
||||
ARM_ENV_RESTORE(env->pmsav8.rlar[M_REG_NS])
|
||||
ARM_ENV_RESTORE(env->pmsav8.rlar[M_REG_S])
|
||||
|
||||
nr = cpu->sau_sregion;
|
||||
ARM_ENV_RESTORE(env->sau.rbar)
|
||||
ARM_ENV_RESTORE(env->sau.rlar)
|
||||
|
||||
#undef ARM_ENV_RESTORE
|
||||
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
void arm_uc_init(struct uc_struct *uc)
|
||||
{
|
||||
uc->reg_read = arm_reg_read;
|
||||
@ -634,5 +773,8 @@ void arm_uc_init(struct uc_struct *uc)
|
||||
uc->cpus_init = arm_cpus_init;
|
||||
uc->opcode_hook_invalidate = arm_opcode_hook_invalidate;
|
||||
uc->cpu_context_size = offsetof(CPUARMState, cpu_watchpoint);
|
||||
uc->context_size = uc_arm_context_size;
|
||||
uc->context_save = uc_arm_context_save;
|
||||
uc->context_restore = uc_arm_context_restore;
|
||||
uc_common_init(uc);
|
||||
}
|
||||
|
@ -751,6 +751,30 @@ static void test_armeb_ldrb(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static void test_arm_context_save(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_engine *uc2;
|
||||
char code[] = "\x83\xb0"; // sub sp, #0xc
|
||||
uc_context *ctx;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1,
|
||||
UC_CPU_ARM_CORTEX_R5);
|
||||
|
||||
OK(uc_context_alloc(uc, &ctx));
|
||||
OK(uc_context_save(uc, ctx));
|
||||
OK(uc_context_restore(uc, ctx));
|
||||
|
||||
uc_common_setup(&uc2, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1,
|
||||
UC_CPU_ARM_CORTEX_A7); // Note the different CPU model
|
||||
|
||||
OK(uc_context_restore(uc2, ctx));
|
||||
|
||||
OK(uc_context_free(ctx));
|
||||
OK(uc_close(uc));
|
||||
OK(uc_close(uc2));
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_arm_nop", test_arm_nop},
|
||||
{"test_arm_thumb_sub", test_arm_thumb_sub},
|
||||
{"test_armeb_sub", test_armeb_sub},
|
||||
@ -773,4 +797,5 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop},
|
||||
{"test_arm_be_cpsr_sctlr", test_arm_be_cpsr_sctlr},
|
||||
{"test_arm_switch_endian", test_arm_switch_endian},
|
||||
{"test_armeb_ldrb", test_armeb_ldrb},
|
||||
{"test_arm_context_save", test_arm_context_save},
|
||||
{NULL, NULL}};
|
30
uc.c
30
uc.c
@ -2,6 +2,7 @@
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
#include "unicorn/unicorn.h"
|
||||
#if defined(UNICORN_HAS_OSXKERNEL)
|
||||
#include <libkern/libkern.h>
|
||||
#else
|
||||
@ -1861,7 +1862,7 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context)
|
||||
|
||||
*_context = g_malloc(size);
|
||||
if (*_context) {
|
||||
(*_context)->context_size = uc->cpu_context_size;
|
||||
(*_context)->context_size = size - sizeof(uc_context);
|
||||
(*_context)->arch = uc->arch;
|
||||
(*_context)->mode = uc->mode;
|
||||
return UC_ERR_OK;
|
||||
@ -1881,8 +1882,13 @@ UNICORN_EXPORT
|
||||
size_t uc_context_size(uc_engine *uc)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
// return the total size of struct uc_context
|
||||
return sizeof(uc_context) + uc->cpu_context_size;
|
||||
|
||||
if (!uc->context_size) {
|
||||
// return the total size of struct uc_context
|
||||
return sizeof(uc_context) + uc->cpu_context_size;
|
||||
} else {
|
||||
return sizeof(uc_context) + uc->context_size(uc);
|
||||
}
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
@ -1890,9 +1896,12 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
|
||||
memcpy(context->data, uc->cpu->env_ptr, context->context_size);
|
||||
|
||||
return UC_ERR_OK;
|
||||
if (!uc->context_save) {
|
||||
memcpy(context->data, uc->cpu->env_ptr, context->context_size);
|
||||
return UC_ERR_OK;
|
||||
} else {
|
||||
return uc->context_save(uc, context);
|
||||
}
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
@ -2064,9 +2073,12 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
|
||||
memcpy(uc->cpu->env_ptr, context->data, context->context_size);
|
||||
|
||||
return UC_ERR_OK;
|
||||
if (!uc->context_restore) {
|
||||
memcpy(uc->cpu->env_ptr, context->data, context->context_size);
|
||||
return UC_ERR_OK;
|
||||
} else {
|
||||
return uc->context_restore(uc, context);
|
||||
}
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
|
Loading…
x
Reference in New Issue
Block a user