Save jit state before/after callback
This commit is contained in:
@@ -274,7 +274,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
|
||||
}
|
||||
|
||||
if (HOOK_BOUND_CHECK(hook, (uint64_t)tb->pc)) {
|
||||
((uc_hook_edge_gen_t)hook->callback)(uc, &cur_tb, &prev_tb, hook->user_data);
|
||||
JIT_CALLBACK_GUARD(((uc_hook_edge_gen_t)hook->callback)(uc, &cur_tb, &prev_tb, hook->user_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,6 +334,7 @@ static inline void cpu_handle_debug_exception(CPUState *cpu)
|
||||
static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
{
|
||||
bool catched = false;
|
||||
bool executable = false;
|
||||
struct uc_struct *uc = cpu->uc;
|
||||
struct hook *hook;
|
||||
|
||||
@@ -347,7 +348,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
if (hook->to_delete) {
|
||||
continue;
|
||||
}
|
||||
catched = ((uc_cb_hookinsn_invalid_t)hook->callback)(uc, hook->user_data);
|
||||
JIT_CALLBACK_GUARD_VAR(catched, ((uc_cb_hookinsn_invalid_t)hook->callback)(uc, hook->user_data));
|
||||
if (catched) {
|
||||
break;
|
||||
}
|
||||
@@ -401,7 +402,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
if (hook->to_delete) {
|
||||
continue;
|
||||
}
|
||||
((uc_cb_hookintr_t)hook->callback)(uc, cpu->exception_index, hook->user_data);
|
||||
JIT_CALLBACK_GUARD(((uc_cb_hookintr_t)hook->callback)(uc, cpu->exception_index, hook->user_data));
|
||||
catched = true;
|
||||
}
|
||||
// Unicorn: If un-catched interrupt, stop executions.
|
||||
|
||||
@@ -1475,7 +1475,9 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, paddr, size, 0, hook->user_data)))
|
||||
JIT_CALLBACK_GUARD_VAR(handled,
|
||||
((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, paddr, size, 0, hook->user_data));
|
||||
if (handled)
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
@@ -1490,7 +1492,9 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, paddr, size, 0, hook->user_data)))
|
||||
JIT_CALLBACK_GUARD_VAR(handled,
|
||||
((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, paddr, size, 0, hook->user_data));
|
||||
if (handled)
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
@@ -1551,7 +1555,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, paddr, size, 0, hook->user_data);
|
||||
JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, paddr, size, 0, hook->user_data));
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
if (uc->stop_request)
|
||||
@@ -1566,7 +1570,9 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, paddr, size, 0, hook->user_data)))
|
||||
JIT_CALLBACK_GUARD_VAR(handled,
|
||||
((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, paddr, size, 0, hook->user_data));
|
||||
if (handled)
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
@@ -1610,7 +1616,9 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, paddr, size, 0, hook->user_data)))
|
||||
JIT_CALLBACK_GUARD_VAR(handled,
|
||||
((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, paddr, size, 0, hook->user_data));
|
||||
if (handled)
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
@@ -1718,8 +1726,7 @@ _out:
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, paddr, size, res, hook->user_data);
|
||||
|
||||
JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, paddr, size, res, hook->user_data));
|
||||
// the last callback may already asked to stop emulation
|
||||
if (uc->stop_request)
|
||||
break;
|
||||
@@ -2062,8 +2069,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, paddr, size, val, hook->user_data);
|
||||
|
||||
JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, paddr, size, val, hook->user_data));
|
||||
// the last callback may already asked to stop emulation
|
||||
if (uc->stop_request)
|
||||
break;
|
||||
@@ -2078,7 +2084,9 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, paddr, size, val, hook->user_data)))
|
||||
JIT_CALLBACK_GUARD_VAR(handled,
|
||||
((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, paddr, size, val, hook->user_data));
|
||||
if (handled)
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
@@ -2125,7 +2133,9 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, paddr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, paddr, size, val, hook->user_data)))
|
||||
JIT_CALLBACK_GUARD_VAR(handled,
|
||||
((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, paddr, size, val, hook->user_data));
|
||||
if (handled)
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
|
||||
@@ -2183,6 +2183,9 @@ static void tb_exec_change(struct uc_struct *uc, bool executable)
|
||||
if (uc->current_executable != executable) {
|
||||
jit_write_protect(executable);
|
||||
uc->current_executable = executable;
|
||||
assert(
|
||||
executable == thread_executable()
|
||||
);
|
||||
}
|
||||
}
|
||||
#else /* not needed on non-Darwin platforms */
|
||||
|
||||
@@ -63,6 +63,28 @@ __attribute__((unused)) static bool thread_executable()
|
||||
return thread_mask() == 1;
|
||||
}
|
||||
|
||||
#define JIT_CALLBACK_GUARD(x) \
|
||||
{ \
|
||||
bool executable = uc->current_executable; \
|
||||
assert (executable == thread_executable()); \
|
||||
x; \
|
||||
if (executable != thread_executable()) { \
|
||||
jit_write_protect(executable); \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
#define JIT_CALLBACK_GUARD_VAR(var, x) \
|
||||
{ \
|
||||
bool executable = uc->current_executable; \
|
||||
assert (executable == thread_executable()); \
|
||||
var = x; \
|
||||
if (executable != thread_executable()) { \
|
||||
jit_write_protect(executable); \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
#else /* defined(__aarch64__) && defined(CONFIG_DARWIN) */
|
||||
|
||||
static inline void jit_write_protect(int enabled)
|
||||
@@ -70,6 +92,19 @@ static inline void jit_write_protect(int enabled)
|
||||
return;
|
||||
}
|
||||
|
||||
#define JIT_CALLBACK_GUARD(x) \
|
||||
{ \
|
||||
(void*)uc; \
|
||||
x; \
|
||||
} \
|
||||
|
||||
|
||||
#define JIT_CALLBACK_GUARD_VAR(var, x) \
|
||||
{ \
|
||||
(void*)uc; \
|
||||
var = x; \
|
||||
} \
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* define TCG_APPLE_JIT_H */
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/memory.h"
|
||||
#include "uc_priv.h"
|
||||
|
||||
#include "tcg/tcg-apple-jit.h"
|
||||
|
||||
void cpu_outb(struct uc_struct *uc, uint32_t addr, uint8_t val)
|
||||
{
|
||||
@@ -43,8 +43,9 @@ void cpu_outb(struct uc_struct *uc, uint32_t addr, uint8_t val)
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_OUT)
|
||||
((uc_cb_insn_out_t)hook->callback)(uc, addr, 1, val, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_OUT) {
|
||||
JIT_CALLBACK_GUARD(((uc_cb_insn_out_t)hook->callback)(uc, addr, 1, val, hook->user_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +64,9 @@ void cpu_outw(struct uc_struct *uc, uint32_t addr, uint16_t val)
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_OUT)
|
||||
((uc_cb_insn_out_t)hook->callback)(uc, addr, 2, val, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_OUT) {
|
||||
JIT_CALLBACK_GUARD(((uc_cb_insn_out_t)hook->callback)(uc, addr, 2, val, hook->user_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +85,9 @@ void cpu_outl(struct uc_struct *uc, uint32_t addr, uint32_t val)
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_OUT)
|
||||
((uc_cb_insn_out_t)hook->callback)(uc, addr, 4, val, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_OUT) {
|
||||
JIT_CALLBACK_GUARD(((uc_cb_insn_out_t)hook->callback)(uc, addr, 4, val, hook->user_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +105,11 @@ uint8_t cpu_inb(struct uc_struct *uc, uint32_t addr)
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_IN)
|
||||
return ((uc_cb_insn_in_t)hook->callback)(uc, addr, 1, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_IN) {
|
||||
uint8_t ret;
|
||||
JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_insn_in_t)hook->callback)(uc, addr, 1, hook->user_data));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -124,8 +130,11 @@ uint16_t cpu_inw(struct uc_struct *uc, uint32_t addr)
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_IN)
|
||||
return ((uc_cb_insn_in_t)hook->callback)(uc, addr, 2, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_IN) {
|
||||
uint16_t ret;
|
||||
JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_insn_in_t)hook->callback)(uc, addr, 2, hook->user_data));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -148,8 +157,11 @@ uint32_t cpu_inl(struct uc_struct *uc, uint32_t addr)
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_IN)
|
||||
return ((uc_cb_insn_in_t)hook->callback)(uc, addr, 4, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_IN) {
|
||||
uint32_t ret;
|
||||
JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_insn_in_t)hook->callback)(uc, addr, 4, hook->user_data));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -63,7 +63,8 @@ bool unicorn_fill_tlb(CPUState *cs, vaddr address, int size,
|
||||
continue;
|
||||
}
|
||||
handled = true;
|
||||
if ((ret = ((uc_cb_tlbevent_t)hook->callback)(uc, address & TARGET_PAGE_MASK, rw_to_mem_type(rw), &e, hook->user_data))) {
|
||||
JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_tlbevent_t)hook->callback)(uc, address & TARGET_PAGE_MASK, rw_to_mem_type(rw), &e, hook->user_data));
|
||||
if (ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -939,6 +939,7 @@ uint32_t HELPER(uc_hooksys64)(CPUARMState *env, uint32_t insn, void *hk)
|
||||
struct hook *hook = (struct hook*)hk;
|
||||
uc_arm64_cp_reg cp_reg;
|
||||
uint32_t rt;
|
||||
uc_engine *uc = env->uc;
|
||||
|
||||
if (hook->to_delete) {
|
||||
return 0;
|
||||
@@ -965,5 +966,7 @@ uint32_t HELPER(uc_hooksys64)(CPUARMState *env, uint32_t insn, void *hk)
|
||||
cp_reg.val = 0;
|
||||
}
|
||||
|
||||
return ((uc_cb_insn_sys_t)(hook->callback))(env->uc, uc_rt, &cp_reg, hook->user_data);
|
||||
uint32_t ret;
|
||||
JIT_CALLBACK_GUARD_VAR(ret, ((uc_cb_insn_sys_t)(hook->callback))(env->uc, uc_rt, &cp_reg, hook->user_data));
|
||||
return ret;
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "exec/ioport.h"
|
||||
|
||||
#include "uc_priv.h"
|
||||
#include "tcg/tcg-apple-jit.h"
|
||||
|
||||
void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
|
||||
{
|
||||
@@ -105,6 +106,7 @@ void helper_into(CPUX86State *env, int next_eip_addend)
|
||||
void helper_cpuid(CPUX86State *env)
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
uc_engine *uc = env->uc;
|
||||
struct hook *hook;
|
||||
int skip_cpuid = 0;
|
||||
|
||||
@@ -120,8 +122,9 @@ void helper_cpuid(CPUX86State *env)
|
||||
|
||||
// Multiple cpuid callbacks returning different values is undefined.
|
||||
// true -> skip the cpuid instruction
|
||||
if (hook->insn == UC_X86_INS_CPUID)
|
||||
skip_cpuid = ((uc_cb_insn_cpuid_t)hook->callback)(env->uc, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_CPUID) {
|
||||
JIT_CALLBACK_GUARD_VAR(skip_cpuid, ((uc_cb_insn_cpuid_t)hook->callback)(env->uc, hook->user_data));
|
||||
}
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
if (env->uc->stop_request)
|
||||
|
||||
@@ -973,14 +973,17 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
|
||||
{
|
||||
// Unicorn: call registered syscall hooks
|
||||
struct hook *hook;
|
||||
uc_engine *uc = env->uc;
|
||||
|
||||
HOOK_FOREACH_VAR_DECLARE;
|
||||
HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, env->eip))
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_SYSCALL)
|
||||
((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_SYSCALL) {
|
||||
JIT_CALLBACK_GUARD(((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data));
|
||||
}
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
if (env->uc->stop_request)
|
||||
@@ -2348,14 +2351,17 @@ void helper_sysenter(CPUX86State *env, int next_eip_addend)
|
||||
{
|
||||
// Unicorn: call registered SYSENTER hooks
|
||||
struct hook *hook;
|
||||
uc_engine *uc = env->uc;
|
||||
|
||||
HOOK_FOREACH_VAR_DECLARE;
|
||||
HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, env->eip))
|
||||
continue;
|
||||
if (hook->insn == UC_X86_INS_SYSENTER)
|
||||
((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data);
|
||||
if (hook->insn == UC_X86_INS_SYSENTER) {
|
||||
JIT_CALLBACK_GUARD(((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data));
|
||||
}
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
if (env->uc->stop_request)
|
||||
|
||||
12
uc.c
12
uc.c
@@ -1957,8 +1957,8 @@ void helper_uc_traceopcode(struct hook *hook, uint64_t arg1, uint64_t arg2,
|
||||
// hold in most cases for uc_tracecode.
|
||||
//
|
||||
// TODO: Shall we have a flag to allow users to control whether updating PC?
|
||||
((uc_hook_tcg_op_2)hook->callback)(uc, address, arg1, arg2, size,
|
||||
hook->user_data);
|
||||
JIT_CALLBACK_GUARD(((uc_hook_tcg_op_2)hook->callback)(
|
||||
uc, address, arg1, arg2, size, hook->user_data));
|
||||
|
||||
if (unlikely(uc->stop_request)) {
|
||||
return;
|
||||
@@ -2002,16 +2002,16 @@ void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle,
|
||||
if (size == 0) {
|
||||
if (index == UC_HOOK_CODE_IDX && uc->count_hook) {
|
||||
// this is the instruction counter (first hook in the list)
|
||||
((uc_cb_hookcode_t)hook->callback)(uc, address, size,
|
||||
hook->user_data);
|
||||
JIT_CALLBACK_GUARD(((uc_cb_hookcode_t)hook->callback)(
|
||||
uc, address, size, hook->user_data));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (HOOK_BOUND_CHECK(hook, (uint64_t)address)) {
|
||||
((uc_cb_hookcode_t)hook->callback)(uc, address, size,
|
||||
hook->user_data);
|
||||
JIT_CALLBACK_GUARD(((uc_cb_hookcode_t)hook->callback)(
|
||||
uc, address, size, hook->user_data));
|
||||
}
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
|
||||
Reference in New Issue
Block a user