Deep copy for arm cpu state

This commit is contained in:
mio 2022-10-01 00:13:36 +02:00
parent 2a3cc7a1b3
commit 19d8876e23
No known key found for this signature in database
GPG Key ID: DFF27E34A47CB873
4 changed files with 202 additions and 9 deletions

View File

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

View File

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

View File

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

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