Tweak some names in a few places, encapsulate the uc_context struct to hide it from users for some reason

This commit is contained in:
Andrew Dutcher 2016-10-10 14:04:51 -07:00
parent 1ab2154fe5
commit ea54204952
4 changed files with 35 additions and 28 deletions

View File

@ -245,6 +245,15 @@ struct uc_struct {
uint64_t next_pc; // save next PC for some special cases uint64_t next_pc; // save next PC for some special cases
}; };
// Metadata stub for the variable-size cpu context used with uc_context_*()
struct uc_context {
uc_arch arch;
uc_mode mode;
size_t size;
bool used;
char data[0];
};
// check if this address is mapped in (via uc_mem_map()) // check if this address is mapped in (via uc_mem_map())
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address); MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address);

View File

@ -273,14 +273,9 @@ typedef enum uc_query_type {
UC_QUERY_PAGE_SIZE, UC_QUERY_PAGE_SIZE,
} uc_query_type; } uc_query_type;
// Metadata stub for the variable-size cpu context used with uc_context_*() // Opaque storage for CPU context, used with uc_context_*()
typedef struct uc_context { struct uc_context;
uc_arch arch; typedef struct uc_context uc_context;
uc_mode mode;
size_t size;
bool used;
char data[0];
} uc_context;
/* /*
Return combined API version & major and minor version numbers. Return combined API version & major and minor version numbers.

View File

@ -742,7 +742,7 @@ static void test_x86_16(void **state)
static void test_i386_reg_save(void **state) static void test_i386_reg_save(void **state)
{ {
uc_engine *uc; uc_engine *uc;
uc_context *saved_regs; uc_context *saved_context;
static const uint64_t address = 0; static const uint64_t address = 0;
static const uint8_t code[] = { static const uint8_t code[] = {
@ -766,10 +766,10 @@ static void test_i386_reg_save(void **state)
uc_assert_success(uc_emu_start(uc, address, address+1, 0, 0)); uc_assert_success(uc_emu_start(uc, address, address+1, 0, 0));
// grab a buffer to use for state saving // grab a buffer to use for state saving
uc_assert_success(uc_context_alloc(uc, &saved_regs)); uc_assert_success(uc_context_alloc(uc, &saved_context));
// save the state // save the state
uc_assert_success(uc_context_save(uc, saved_regs)); uc_assert_success(uc_context_save(uc, saved_context));
// step one instruction // step one instruction
uc_assert_success(uc_emu_start(uc, address, address+1, 0, 0)); uc_assert_success(uc_emu_start(uc, address, address+1, 0, 0));
@ -779,7 +779,7 @@ static void test_i386_reg_save(void **state)
assert_int_equal(eax, 3); assert_int_equal(eax, 3);
// restore the state // restore the state
uc_context_restore(uc, saved_regs); uc_context_restore(uc, saved_context);
// check that eax == 2 // check that eax == 2
uc_assert_success(uc_reg_read(uc, UC_X86_REG_EAX, &eax)); uc_assert_success(uc_reg_read(uc, UC_X86_REG_EAX, &eax));
@ -793,14 +793,14 @@ static void test_i386_reg_save(void **state)
assert_int_equal(eax, 3); assert_int_equal(eax, 3);
// restore the state // restore the state
uc_context_restore(uc, saved_regs); uc_context_restore(uc, saved_context);
// check that eax == 2 // check that eax == 2
uc_assert_success(uc_reg_read(uc, UC_X86_REG_EAX, &eax)); uc_assert_success(uc_reg_read(uc, UC_X86_REG_EAX, &eax));
assert_int_equal(eax, 2); assert_int_equal(eax, 2);
// clean up; // clean up;
uc_context_free(saved_regs); uc_context_free(saved_context);
uc_assert_success(uc_close(uc)); uc_assert_success(uc_close(uc));
} }
/******************************************************************************/ /******************************************************************************/

31
uc.c
View File

@ -1156,8 +1156,8 @@ uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result)
return UC_ERR_OK; return UC_ERR_OK;
} }
size_t cpu_regs_size(uc_arch arch, uc_mode mode); size_t cpu_context_size(uc_arch arch, uc_mode mode);
size_t cpu_regs_size(uc_arch arch, uc_mode mode) size_t cpu_context_size(uc_arch arch, uc_mode mode)
{ {
// each of these constants is defined by offsetof(CPUXYZState, tlb_table) // each of these constants is defined by offsetof(CPUXYZState, tlb_table)
// tbl_table is the first entry in the CPU_COMMON macro, so it marks the end // tbl_table is the first entry in the CPU_COMMON macro, so it marks the end
@ -1176,13 +1176,14 @@ size_t cpu_regs_size(uc_arch arch, uc_mode mode)
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_context_alloc(uc_engine *uc, uc_context **context) uc_err uc_context_alloc(uc_engine *uc, uc_context **context)
{ {
size_t size = cpu_regs_size(uc->arch, uc->mode); struct uc_context **_context = context;
*context = malloc(size + sizeof(uc_context)); size_t size = cpu_context_size(uc->arch, uc->mode);
if (*context) { *_context = malloc(size + sizeof(uc_context));
(*context)->size = size; if (*_context) {
(*context)->arch = uc->arch; (*_context)->size = size;
(*context)->mode = uc->mode; (*_context)->arch = uc->arch;
(*context)->used = false; (*_context)->mode = uc->mode;
(*_context)->used = false;
return UC_ERR_OK; return UC_ERR_OK;
} else { } else {
return UC_ERR_NOMEM; return UC_ERR_NOMEM;
@ -1199,11 +1200,12 @@ uc_err uc_context_free(uc_context *context)
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_context_save(uc_engine *uc, uc_context *context) uc_err uc_context_save(uc_engine *uc, uc_context *context)
{ {
if (context->arch != uc->arch || context->mode != uc->mode) { struct uc_context *_context = context;
if (_context->arch != uc->arch || _context->mode != uc->mode) {
return UC_ERR_ARG; return UC_ERR_ARG;
} else { } else {
memcpy(context->data, uc->cpu->env_ptr, context->size); memcpy(_context->data, uc->cpu->env_ptr, _context->size);
context->used = true; _context->used = true;
return UC_ERR_OK; return UC_ERR_OK;
} }
} }
@ -1211,10 +1213,11 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context)
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_context_restore(uc_engine *uc, uc_context *context) uc_err uc_context_restore(uc_engine *uc, uc_context *context)
{ {
if (context->arch != uc->arch || context->mode != uc->mode || !context->used) { struct uc_context *_context = context;
if (_context->arch != uc->arch || _context->mode != uc->mode || !_context->used) {
return UC_ERR_ARG; return UC_ERR_ARG;
} else { } else {
memcpy(uc->cpu->env_ptr, context->data, context->size); memcpy(uc->cpu->env_ptr, _context->data, _context->size);
return UC_ERR_OK; return UC_ERR_OK;
} }
} }