Basic implementation of uc_ctl

This commit is contained in:
lazymio
2021-11-01 00:39:36 +01:00
parent b07baede63
commit 3dd2e0f95d
19 changed files with 459 additions and 52 deletions

View File

@ -41,6 +41,8 @@
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | ((b & 0xff) << 8))
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
struct TranslationBlock;
typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type,
size_t *result);
@ -114,6 +116,14 @@ typedef void (*uc_softfloat_initialize)(void);
// tcg flush softmmu tlb
typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc);
// Invalidate the TB at given address
typedef void (*uc_invalidate_tb_t)(struct uc_struct *uc, uint64_t start,
size_t len);
// Request generating TB at given address
typedef struct TranslationBlock *(*uc_gen_tb_t)(struct uc_struct *uc,
uint64_t pc);
struct hook {
int type; // UC_HOOK_*
int insn; // instruction for HOOK_INSN
@ -226,6 +236,8 @@ struct uc_struct {
uc_target_page_init target_page;
uc_softfloat_initialize softfloat_initialize;
uc_tcg_flush_tlb tcg_flush_tlb;
uc_invalidate_tb_t uc_invalidate_tb;
uc_gen_tb_t uc_gen_tb;
/* only 1 cpu in unicorn,
do not need current_cpu to handle current running cpu. */
@ -288,8 +300,9 @@ struct uc_struct {
uint64_t invalid_addr; // invalid address to be accessed
int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE
uint64_t addr_end; // address where emulation stops (@end param of
// uc_emu_start())
int use_exit;
GTree *exits; // addresses where emulation stops (@until param of
// uc_emu_start()) Also see UC_CTL_USE_EXITS for more details.
int thumb; // thumb mode for ARM
MemoryRegion **mapped_blocks;
@ -328,5 +341,20 @@ struct uc_context {
// check if this address is mapped in (via uc_mem_map())
MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address);
// We have to support 32bit system so we can't hold uint64_t on void*
static inline void uc_add_exit(uc_engine *uc, uint64_t addr)
{
uint64_t *new_exit = g_malloc(sizeof(uint64_t));
*new_exit = addr;
g_tree_insert(uc->exits, (gpointer)new_exit, (gpointer)1);
}
// This function has to exist since we would like to accept uint32_t or
// it's complex to achieve so.
static inline int uc_addr_is_exit(uc_engine *uc, uint64_t addr)
{
return g_tree_lookup(uc->exits, (gpointer)(&addr)) == (gpointer)1;
}
#endif
/* vim: set ts=4 noet: */

View File

@ -427,40 +427,43 @@ typedef enum uc_query_type {
// If a control don't have `Set` or `Get` for @args, it means it's r/o or w/o.
typedef enum uc_control_type {
// Current mode.
// Read: @args = (*int)
// Read: @args = (int*)
UC_CTL_UC_MODE = 0,
// Curent page size.
// Write: @args = (int)
// Read: @args = (*int)
// Write: @args = (uint32_t)
// Read: @args = (uint32_t*)
UC_CTL_UC_PAGE_SIZE,
// Current arch.
// Read: @args = (*int)
// Read: @args = (int*)
UC_CTL_UC_ARCH,
// Current timeout.
// Read: @args = (*uint64_t)
// Read: @args = (uint64_t*)
UC_CTL_UC_TIMEOUT,
// Enable multiple exists.
// Without this control, reading/setting exists won't work.
// This is for API backward compatibility.
// Write: @args = (int)
UC_CTL_UC_USE_EXITS,
// The number of current exists.
// Read: @args = (*size_t)
// Read: @args = (size_t*)
UC_CTL_UC_EXITS_CNT,
// Current exists.
// Write: @args = (*uint64_t exists, size_t len)
// Write: @args = (uint64_t* exists, size_t len)
// @len = UC_CTL_UC_EXITS_CNT
// Read: @args = (*uint64_t exists, size_t len)
// Read: @args = (uint64_t* exists, size_t len)
// @len = UC_CTL_UC_EXITS_CNT
UC_CTL_UC_EXITS,
// Set the cpu model of uc.
// Note this option can only be set before any Unicorn
// API is called except for uc_open.
// Write: @args = (int)
// Read: @args = (int)
UC_CTL_CPU_MODEL,
// Request the edge of two TBs.
// Read: @args = (uint64_t, uint64_t, *uint64_t)
UC_CTL_TB_EDGE,
// Request a tb cache at a specific address
// Read: @args = (uint64_t)
UC_CTL_TB_REQUEST_CACHE,
// Remove a tb cache at a specific address
// Invalidate a tb cache at a specific address
// Read: @args = (uint64_t)
UC_CTL_TB_REMOVE_CACHE
@ -469,13 +472,15 @@ typedef enum uc_control_type {
#define uc_ctl_get_mode(uc, mode) \
uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_MODE, 1), (mode))
#define uc_ctl_get_page_size(uc, ptr) \
uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_PAGE_SIZE, 1, (ptr))
uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_PAGE_SIZE, 1), (ptr))
#define uc_ctl_set_page_size(uc, page_size) \
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_PAGE_SIZE, 1), (page_size))
#define uc_ctl_get_arch(uc, arch) \
uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_ARCH, 1), (arch))
#define uc_ctl_get_timeout(uc, ptr) \
uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_TIMEOUT, 1), (ptr))
#define uc_ctl_exits_enabled(uc, enabled) \
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_USE_EXITS, 1), (enabled))
#define uc_ctl_get_exists_cnt(uc, ptr) \
uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_EXITS_CNT, 1), (ptr))
#define uc_ctl_get_exists(uc, buffer, len) \
@ -487,11 +492,9 @@ typedef enum uc_control_type {
#define uc_ctl_set_cpu_model(uc, model) \
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_CPU_MODEL, 1), (model))
#define uc_ctl_remove_cache(uc, address) \
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REMOVE_CACHE, 1), (address))
uc_ctl(uc, UC_CTL_READ(UC_CTL_TB_REMOVE_CACHE, 1), (address))
#define uc_ctl_request_cache(uc, address) \
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REQUEST_CACHE, 1), (address))
#define uc_ctl_get_edge(uc, addr1, addr2, ptr) \
uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_EDGE, 3), (addr1), (addr2), (ptr))
uc_ctl(uc, UC_CTL_READ(UC_CTL_TB_REQUEST_CACHE, 1), (address))
// Opaque storage for CPU context, used with uc_context_*()
struct uc_context;