Support change page size
This commit is contained in:
@ -267,6 +267,7 @@ struct uc_struct {
|
|||||||
unsigned int alloc_hint;
|
unsigned int alloc_hint;
|
||||||
/* qemu/exec-vary.c */
|
/* qemu/exec-vary.c */
|
||||||
TargetPageBits *init_target_page;
|
TargetPageBits *init_target_page;
|
||||||
|
int target_bits; // User defined page bits by uc_ctl
|
||||||
BounceBuffer bounce; // qemu/cpu-exec.c
|
BounceBuffer bounce; // qemu/cpu-exec.c
|
||||||
volatile sig_atomic_t exit_request; // qemu/cpu-exec.c
|
volatile sig_atomic_t exit_request; // qemu/cpu-exec.c
|
||||||
/* qemu/accel/tcg/cpu-exec-common.c */
|
/* qemu/accel/tcg/cpu-exec-common.c */
|
||||||
@ -339,6 +340,7 @@ struct uc_struct {
|
|||||||
struct list saved_contexts; // The contexts saved by this uc_struct.
|
struct list saved_contexts; // The contexts saved by this uc_struct.
|
||||||
bool no_exit_request; // Disable check_exit_request temporarily. A
|
bool no_exit_request; // Disable check_exit_request temporarily. A
|
||||||
// workaround to treat the IT block as a whole block.
|
// workaround to treat the IT block as a whole block.
|
||||||
|
bool init_done; // Whether the initialization is done.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
||||||
|
@ -35,7 +35,17 @@ bool set_preferred_target_page_bits(struct uc_struct *uc, int bits)
|
|||||||
* a particular size.
|
* a particular size.
|
||||||
*/
|
*/
|
||||||
#ifdef TARGET_PAGE_BITS_VARY
|
#ifdef TARGET_PAGE_BITS_VARY
|
||||||
assert(bits >= TARGET_PAGE_BITS_MIN);
|
//assert(bits >= TARGET_PAGE_BITS_MIN);
|
||||||
|
if (uc->init_target_page == NULL) {
|
||||||
|
uc->init_target_page = calloc(1, sizeof(TargetPageBits));
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < TARGET_PAGE_BITS_MIN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (uc->init_target_page->bits == 0 || uc->init_target_page->bits > bits) {
|
if (uc->init_target_page->bits == 0 || uc->init_target_page->bits > bits) {
|
||||||
if (uc->init_target_page->decided) {
|
if (uc->init_target_page->decided) {
|
||||||
return false;
|
return false;
|
||||||
@ -50,10 +60,15 @@ void finalize_target_page_bits(struct uc_struct *uc)
|
|||||||
{
|
{
|
||||||
#ifdef TARGET_PAGE_BITS_VARY
|
#ifdef TARGET_PAGE_BITS_VARY
|
||||||
if (uc->init_target_page == NULL) {
|
if (uc->init_target_page == NULL) {
|
||||||
uc->init_target_page = g_new0(TargetPageBits, 1);
|
uc->init_target_page = calloc(1, sizeof(TargetPageBits));
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uc->target_bits != 0) {
|
||||||
|
uc->init_target_page->bits = uc->target_bits;
|
||||||
|
}
|
||||||
|
|
||||||
if (uc->init_target_page->bits == 0) {
|
if (uc->init_target_page->bits == 0) {
|
||||||
uc->init_target_page->bits = TARGET_PAGE_BITS_MIN;
|
uc->init_target_page->bits = TARGET_PAGE_BITS_MIN;
|
||||||
}
|
}
|
||||||
|
@ -156,10 +156,29 @@ static void test_uc_ctl_tb_cache()
|
|||||||
OK(uc_close(uc));
|
OK(uc_close(uc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
OK(uc_ctl_set_page_size(uc, 4096));
|
||||||
|
|
||||||
|
OK(uc_mem_map(uc2, 1 << 10, 1 << 10, UC_PROT_ALL));
|
||||||
|
uc_assert_err(UC_ERR_ARG, uc_mem_map(uc, 1 << 10, 1 << 10, UC_PROT_ALL));
|
||||||
|
|
||||||
|
OK(uc_close(uc));
|
||||||
|
OK(uc_close(uc2));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
||||||
{"test_uc_ctl_page_size", test_uc_ctl_page_size},
|
{"test_uc_ctl_page_size", test_uc_ctl_page_size},
|
||||||
{"test_uc_ctl_arch", test_uc_ctl_arch},
|
{"test_uc_ctl_arch", test_uc_ctl_arch},
|
||||||
{"test_uc_ctl_time_out", test_uc_ctl_time_out},
|
{"test_uc_ctl_time_out", test_uc_ctl_time_out},
|
||||||
{"test_uc_ctl_exits", test_uc_ctl_exits},
|
{"test_uc_ctl_exits", test_uc_ctl_exits},
|
||||||
{"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache},
|
{"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache},
|
||||||
|
{"test_uc_ctl_change_page_size", test_uc_ctl_change_page_size},
|
||||||
{NULL, NULL}};
|
{NULL, NULL}};
|
131
uc.c
131
uc.c
@ -25,6 +25,7 @@
|
|||||||
#include "qemu/target/riscv/unicorn.h"
|
#include "qemu/target/riscv/unicorn.h"
|
||||||
|
|
||||||
#include "qemu/include/qemu/queue.h"
|
#include "qemu/include/qemu/queue.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
unsigned int uc_version(unsigned int *major, unsigned int *minor)
|
unsigned int uc_version(unsigned int *major, unsigned int *minor)
|
||||||
@ -136,6 +137,14 @@ bool uc_arch_supported(uc_arch arch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define UC_INIT(uc) \
|
||||||
|
if (unlikely(!(uc)->init_done)) { \
|
||||||
|
int __init_ret = uc_init(uc); \
|
||||||
|
if (unlikely(__init_ret != UC_ERR_OK)) { \
|
||||||
|
return __init_ret; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
static gint uc_exits_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
|
static gint uc_exits_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||||
{
|
{
|
||||||
uint64_t lhs = *((uint64_t *)a);
|
uint64_t lhs = *((uint64_t *)a);
|
||||||
@ -150,6 +159,31 @@ static gint uc_exits_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uc_err uc_init(uc_engine *uc)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (uc->init_done) {
|
||||||
|
return UC_ERR_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uc->exits = g_tree_new_full(uc_exits_cmp, NULL, g_free, NULL);
|
||||||
|
|
||||||
|
if (machine_initialize(uc)) {
|
||||||
|
return UC_ERR_RESOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init fpu softfloat
|
||||||
|
uc->softfloat_initialize();
|
||||||
|
|
||||||
|
if (uc->reg_reset) {
|
||||||
|
uc->reg_reset(uc);
|
||||||
|
}
|
||||||
|
|
||||||
|
uc->init_done = true;
|
||||||
|
|
||||||
|
return UC_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
||||||
{
|
{
|
||||||
@ -175,8 +209,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
|||||||
|
|
||||||
QTAILQ_INIT(&uc->address_spaces);
|
QTAILQ_INIT(&uc->address_spaces);
|
||||||
|
|
||||||
uc->exits = g_tree_new_full(uc_exits_cmp, NULL, g_free, NULL);
|
|
||||||
|
|
||||||
switch (arch) {
|
switch (arch) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -315,19 +347,10 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
|||||||
return UC_ERR_ARCH;
|
return UC_ERR_ARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (machine_initialize(uc)) {
|
uc->init_done = false;
|
||||||
return UC_ERR_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init fpu softfloat
|
|
||||||
uc->softfloat_initialize();
|
|
||||||
|
|
||||||
*result = uc;
|
*result = uc;
|
||||||
|
|
||||||
if (uc->reg_reset) {
|
|
||||||
uc->reg_reset(uc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
} else {
|
} else {
|
||||||
return UC_ERR_ARCH;
|
return UC_ERR_ARCH;
|
||||||
@ -342,6 +365,11 @@ uc_err uc_close(uc_engine *uc)
|
|||||||
struct hook *hook;
|
struct hook *hook;
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
|
|
||||||
|
if (!uc->init_done) {
|
||||||
|
free(uc);
|
||||||
|
return UC_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup internally.
|
// Cleanup internally.
|
||||||
if (uc->release) {
|
if (uc->release) {
|
||||||
uc->release(uc->tcg_ctx);
|
uc->release(uc->tcg_ctx);
|
||||||
@ -425,6 +453,9 @@ UNICORN_EXPORT
|
|||||||
uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count)
|
uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count)
|
||||||
{
|
{
|
||||||
int ret = UC_ERR_OK;
|
int ret = UC_ERR_OK;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (uc->reg_read) {
|
if (uc->reg_read) {
|
||||||
ret = uc->reg_read(uc, (unsigned int *)ids, vals, count);
|
ret = uc->reg_read(uc, (unsigned int *)ids, vals, count);
|
||||||
} else {
|
} else {
|
||||||
@ -438,6 +469,9 @@ UNICORN_EXPORT
|
|||||||
uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
|
uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
|
||||||
{
|
{
|
||||||
int ret = UC_ERR_OK;
|
int ret = UC_ERR_OK;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (uc->reg_write) {
|
if (uc->reg_write) {
|
||||||
ret = uc->reg_write(uc, (unsigned int *)ids, vals, count);
|
ret = uc->reg_write(uc, (unsigned int *)ids, vals, count);
|
||||||
} else {
|
} else {
|
||||||
@ -450,12 +484,14 @@ uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
|
|||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
|
uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
|
||||||
{
|
{
|
||||||
|
UC_INIT(uc);
|
||||||
return uc_reg_read_batch(uc, ®id, &value, 1);
|
return uc_reg_read_batch(uc, ®id, &value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
||||||
{
|
{
|
||||||
|
UC_INIT(uc);
|
||||||
return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1);
|
return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,6 +521,8 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size)
|
|||||||
size_t count = 0, len;
|
size_t count = 0, len;
|
||||||
uint8_t *bytes = _bytes;
|
uint8_t *bytes = _bytes;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
// qemu cpu_physical_memory_rw() size is an int
|
// qemu cpu_physical_memory_rw() size is an int
|
||||||
if (size > INT_MAX)
|
if (size > INT_MAX)
|
||||||
return UC_ERR_ARG;
|
return UC_ERR_ARG;
|
||||||
@ -528,6 +566,8 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes,
|
|||||||
size_t count = 0, len;
|
size_t count = 0, len;
|
||||||
const uint8_t *bytes = _bytes;
|
const uint8_t *bytes = _bytes;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
// qemu cpu_physical_memory_rw() size is an int
|
// qemu cpu_physical_memory_rw() size is an int
|
||||||
if (size > INT_MAX)
|
if (size > INT_MAX)
|
||||||
return UC_ERR_ARG;
|
return UC_ERR_ARG;
|
||||||
@ -657,6 +697,8 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
|
|||||||
uc->timed_out = false;
|
uc->timed_out = false;
|
||||||
uc->first_tb = true;
|
uc->first_tb = true;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
switch (uc->arch) {
|
switch (uc->arch) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -777,6 +819,8 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
|
|||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_emu_stop(uc_engine *uc)
|
uc_err uc_emu_stop(uc_engine *uc)
|
||||||
{
|
{
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (uc->emulation_done) {
|
if (uc->emulation_done) {
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
@ -918,6 +962,8 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms)
|
|||||||
{
|
{
|
||||||
uc_err res;
|
uc_err res;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (uc->mem_redirect) {
|
if (uc->mem_redirect) {
|
||||||
address = uc->mem_redirect(address);
|
address = uc->mem_redirect(address);
|
||||||
}
|
}
|
||||||
@ -937,6 +983,8 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size,
|
|||||||
{
|
{
|
||||||
uc_err res;
|
uc_err res;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
return UC_ERR_ARG;
|
return UC_ERR_ARG;
|
||||||
}
|
}
|
||||||
@ -961,6 +1009,8 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size,
|
|||||||
{
|
{
|
||||||
uc_err res;
|
uc_err res;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (uc->mem_redirect) {
|
if (uc->mem_redirect) {
|
||||||
address = uc->mem_redirect(address);
|
address = uc->mem_redirect(address);
|
||||||
}
|
}
|
||||||
@ -1167,6 +1217,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
|||||||
size_t count, len;
|
size_t count, len;
|
||||||
bool remove_exec = false;
|
bool remove_exec = false;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
// trivial case, no change
|
// trivial case, no change
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
@ -1237,6 +1289,8 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
|||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
size_t count, len;
|
size_t count, len;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
// nothing to unmap
|
// nothing to unmap
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
@ -1323,6 +1377,8 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
|
|||||||
int ret = UC_ERR_OK;
|
int ret = UC_ERR_OK;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
struct hook *hook = calloc(1, sizeof(struct hook));
|
struct hook *hook = calloc(1, sizeof(struct hook));
|
||||||
if (hook == NULL) {
|
if (hook == NULL) {
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
@ -1439,6 +1495,8 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh)
|
|||||||
int i;
|
int i;
|
||||||
struct hook *hook = (struct hook *)hh;
|
struct hook *hook = (struct hook *)hh;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
// we can't dereference hook->type if hook is invalid
|
// we can't dereference hook->type if hook is invalid
|
||||||
// so for now we need to iterate over all possible types to remove the hook
|
// so for now we need to iterate over all possible types to remove the hook
|
||||||
// which is less efficient
|
// which is less efficient
|
||||||
@ -1554,6 +1612,8 @@ uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uc_mem_region *r = NULL;
|
uc_mem_region *r = NULL;
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
*count = uc->mapped_block_count;
|
*count = uc->mapped_block_count;
|
||||||
|
|
||||||
if (*count) {
|
if (*count) {
|
||||||
@ -1578,6 +1638,8 @@ uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count)
|
|||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result)
|
uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result)
|
||||||
{
|
{
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
default:
|
default:
|
||||||
return UC_ERR_ARG;
|
return UC_ERR_ARG;
|
||||||
@ -1613,6 +1675,8 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context)
|
|||||||
struct uc_context **_context = context;
|
struct uc_context **_context = context;
|
||||||
size_t size = uc_context_size(uc);
|
size_t size = uc_context_size(uc);
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
*_context = g_malloc(size);
|
*_context = g_malloc(size);
|
||||||
if (*_context) {
|
if (*_context) {
|
||||||
(*_context)->jmp_env_size = sizeof(*uc->cpu->jmp_env);
|
(*_context)->jmp_env_size = sizeof(*uc->cpu->jmp_env);
|
||||||
@ -1640,6 +1704,7 @@ uc_err uc_free(void *mem)
|
|||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
size_t uc_context_size(uc_engine *uc)
|
size_t uc_context_size(uc_engine *uc)
|
||||||
{
|
{
|
||||||
|
UC_INIT(uc);
|
||||||
// return the total size of struct uc_context
|
// return the total size of struct uc_context
|
||||||
return sizeof(uc_context) + uc->cpu_context_size +
|
return sizeof(uc_context) + uc->cpu_context_size +
|
||||||
sizeof(*uc->cpu->jmp_env);
|
sizeof(*uc->cpu->jmp_env);
|
||||||
@ -1648,6 +1713,8 @@ size_t uc_context_size(uc_engine *uc)
|
|||||||
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)
|
||||||
{
|
{
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
memcpy(context->data, uc->cpu->env_ptr, context->context_size);
|
memcpy(context->data, uc->cpu->env_ptr, context->context_size);
|
||||||
memcpy(context->data + context->context_size, uc->cpu->jmp_env,
|
memcpy(context->data + context->context_size, uc->cpu->jmp_env,
|
||||||
context->jmp_env_size);
|
context->jmp_env_size);
|
||||||
@ -1819,6 +1886,8 @@ uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals,
|
|||||||
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)
|
||||||
{
|
{
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
memcpy(uc->cpu->env_ptr, context->data, context->context_size);
|
memcpy(uc->cpu->env_ptr, context->data, context->context_size);
|
||||||
if (list_exists(&uc->saved_contexts, context)) {
|
if (list_exists(&uc->saved_contexts, context)) {
|
||||||
memcpy(uc->cpu->jmp_env, context->data + context->context_size,
|
memcpy(uc->cpu->jmp_env, context->data + context->context_size,
|
||||||
@ -1899,11 +1968,33 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
|||||||
|
|
||||||
case UC_CTL_UC_PAGE_SIZE: {
|
case UC_CTL_UC_PAGE_SIZE: {
|
||||||
if (rw == UC_CTL_IO_READ) {
|
if (rw == UC_CTL_IO_READ) {
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
uint32_t *page_size = va_arg(args, uint32_t *);
|
uint32_t *page_size = va_arg(args, uint32_t *);
|
||||||
*page_size = uc->target_page_size;
|
*page_size = uc->target_page_size;
|
||||||
} else {
|
} else {
|
||||||
// Not implemented.
|
uint32_t page_size = va_arg(args, uint32_t);
|
||||||
err = UC_ERR_ARG;
|
int bits = 0;
|
||||||
|
|
||||||
|
if (uc->arch != UC_ARCH_ARM) {
|
||||||
|
err = UC_ERR_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((page_size & (page_size - 1))) {
|
||||||
|
err = UC_ERR_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (page_size) {
|
||||||
|
bits++;
|
||||||
|
page_size >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uc->target_bits = bits;
|
||||||
|
|
||||||
|
err = UC_ERR_OK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1918,6 +2009,9 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case UC_CTL_UC_EXITS_CNT: {
|
case UC_CTL_UC_EXITS_CNT: {
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (!uc->use_exits) {
|
if (!uc->use_exits) {
|
||||||
err = UC_ERR_ARG;
|
err = UC_ERR_ARG;
|
||||||
} else if (rw == UC_CTL_IO_READ) {
|
} else if (rw == UC_CTL_IO_READ) {
|
||||||
@ -1930,6 +2024,9 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case UC_CTL_UC_EXITS: {
|
case UC_CTL_UC_EXITS: {
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (!uc->use_exits) {
|
if (!uc->use_exits) {
|
||||||
err = UC_ERR_ARG;
|
err = UC_ERR_ARG;
|
||||||
} else if (rw == UC_CTL_IO_READ) {
|
} else if (rw == UC_CTL_IO_READ) {
|
||||||
@ -1965,6 +2062,9 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case UC_CTL_TB_REQUEST_CACHE: {
|
case UC_CTL_TB_REQUEST_CACHE: {
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (rw == UC_CTL_IO_READ_WRITE) {
|
if (rw == UC_CTL_IO_READ_WRITE) {
|
||||||
uint64_t addr = va_arg(args, uint64_t);
|
uint64_t addr = va_arg(args, uint64_t);
|
||||||
uc_tb *tb = va_arg(args, uc_tb *);
|
uc_tb *tb = va_arg(args, uc_tb *);
|
||||||
@ -1976,6 +2076,9 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case UC_CTL_TB_REMOVE_CACHE: {
|
case UC_CTL_TB_REMOVE_CACHE: {
|
||||||
|
|
||||||
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (rw == UC_CTL_IO_READ) {
|
if (rw == UC_CTL_IO_READ) {
|
||||||
uint64_t addr = va_arg(args, uint64_t);
|
uint64_t addr = va_arg(args, uint64_t);
|
||||||
uc->uc_invalidate_tb(uc, addr, 1);
|
uc->uc_invalidate_tb(uc, addr, 1);
|
||||||
|
Reference in New Issue
Block a user