diff --git a/COMPILE.TXT b/COMPILE.TXT index 5887f094..fa2b1d7c 100644 --- a/COMPILE.TXT +++ b/COMPILE.TXT @@ -178,8 +178,16 @@ Unicorn requires few dependent packages as followings [7] Compile on Windows with MinGW (MSYS2) To compile with MinGW you need to install MSYS2: https://msys2.github.io/ - Follow the install instructions and don't forget to update the system packages as written in 5 & 6 paragraphs + Follow the install instructions and don't forget to update the system packages with: + + $ pacman --needed -Sy bash pacman pacman-mirrors msys2-runtime + + Then close MSYS2, run it again from Start menu and update the rest with: + + $ pacman -Su + Finally, compile Unicorn with the next steps: + - To compile Windows 32-bit binary with MinGW, run: $ pacman -S make $ pacman -S pkg-config diff --git a/hook.c b/hook.c index 31fcaabf..850c9564 100644 --- a/hook.c +++ b/hook.c @@ -63,17 +63,17 @@ size_t hook_add(struct uc_struct *uc, int type, uint64_t begin, uint64_t end, vo if (begin > end) uc->hook_insn_idx = i; break; - case UC_MEM_READ: + case UC_HOOK_MEM_READ: uc->hook_mem_read = true; if (begin > end) uc->hook_read_idx = i; break; - case UC_MEM_WRITE: + case UC_HOOK_MEM_WRITE: uc->hook_mem_write = true; if (begin > end) uc->hook_write_idx = i; break; - case UC_MEM_READ_WRITE: + case UC_HOOK_MEM_READ_WRITE: uc->hook_mem_read = true; uc->hook_mem_write = true; if (begin > end) { @@ -151,12 +151,13 @@ static struct hook_struct *_hook_find(struct uc_struct *uc, int type, uint64_t a if (uc->hook_insn_idx) return &uc->hook_callbacks[uc->hook_insn_idx]; break; - case UC_MEM_READ: + case UC_HOOK_MEM_READ: // already hooked all memory read? - if (uc->hook_read_idx) + if (uc->hook_read_idx) { return &uc->hook_callbacks[uc->hook_read_idx]; + } break; - case UC_MEM_WRITE: + case UC_HOOK_MEM_WRITE: // already hooked all memory write? if (uc->hook_write_idx) return &uc->hook_callbacks[uc->hook_write_idx]; @@ -174,14 +175,14 @@ static struct hook_struct *_hook_find(struct uc_struct *uc, int type, uint64_t a return &uc->hook_callbacks[i]; } break; - case UC_MEM_READ: - if (uc->hook_callbacks[i].hook_type == UC_MEM_READ || uc->hook_callbacks[i].hook_type == UC_MEM_READ_WRITE) { + case UC_HOOK_MEM_READ: + if (uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_READ || uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_READ_WRITE) { if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end) return &uc->hook_callbacks[i]; } break; - case UC_MEM_WRITE: - if (uc->hook_callbacks[i].hook_type == UC_MEM_WRITE || uc->hook_callbacks[i].hook_type == UC_MEM_READ_WRITE) { + case UC_HOOK_MEM_WRITE: + if (uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_WRITE || uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_READ_WRITE) { if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end) return &uc->hook_callbacks[i]; } diff --git a/include/uc_priv.h b/include/uc_priv.h index 6e43a930..195d719c 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -172,6 +172,8 @@ struct uc_struct { bool block_full; MemoryRegion **mapped_blocks; uint32_t mapped_block_count; + + void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c) }; #include "qemu_macro.h" diff --git a/qemu/cpus.c b/qemu/cpus.c index ecc66e83..e274fe5a 100644 --- a/qemu/cpus.c +++ b/qemu/cpus.c @@ -124,7 +124,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) struct uc_struct *uc = cpu->uc; //qemu_tcg_init_cpu_signals(); - qemu_thread_get_self(cpu->thread); + qemu_thread_get_self(uc, cpu->thread); qemu_mutex_lock(&uc->qemu_global_mutex); CPU_FOREACH(cpu) { @@ -185,7 +185,7 @@ static void qemu_tcg_init_vcpu(CPUState *cpu) uc->tcg_halt_cond = cpu->halt_cond; snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG", cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_tcg_cpu_thread_fn, + qemu_thread_create(uc, cpu->thread, thread_name, qemu_tcg_cpu_thread_fn, cpu, QEMU_THREAD_JOINABLE); #ifdef _WIN32 cpu->hThread = qemu_thread_get_handle(cpu->thread); diff --git a/qemu/include/qemu/thread.h b/qemu/include/qemu/thread.h index ef2f6962..de5956b2 100644 --- a/qemu/include/qemu/thread.h +++ b/qemu/include/qemu/thread.h @@ -52,12 +52,13 @@ void qemu_event_reset(QemuEvent *ev); void qemu_event_wait(QemuEvent *ev); void qemu_event_destroy(QemuEvent *ev); -void qemu_thread_create(QemuThread *thread, const char *name, +struct uc_struct; +void qemu_thread_create(struct uc_struct *uc, QemuThread *thread, const char *name, void *(*start_routine)(void *), void *arg, int mode); void *qemu_thread_join(QemuThread *thread); -void qemu_thread_get_self(QemuThread *thread); +void qemu_thread_get_self(struct uc_struct *uc, QemuThread *thread); bool qemu_thread_is_self(QemuThread *thread); -void qemu_thread_exit(void *retval); +void qemu_thread_exit(struct uc_struct *uc, void *retval); #endif diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index 50d6e424..bda85dce 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -183,7 +183,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // Unicorn: callback on memory read if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) { - struct hook_struct *trace = hook_find(env->uc, UC_MEM_READ, addr); + struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr); if (trace) { ((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ, (uint64_t)addr, (int)DATA_SIZE, (int64_t)0, trace->user_data); @@ -328,7 +328,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // Unicorn: callback on memory read if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) { - struct hook_struct *trace = hook_find(env->uc, UC_MEM_READ, addr); + struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr); if (trace) { ((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ, (uint64_t)addr, (int)DATA_SIZE, (int64_t)0, trace->user_data); @@ -510,8 +510,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, MemoryRegion *mr = memory_mapping(uc, addr); // Unicorn: callback on memory write - if (env->uc->hook_mem_write) { - struct hook_struct *trace = hook_find(uc, UC_MEM_WRITE, addr); + if (uc->hook_mem_write) { + struct hook_struct *trace = hook_find(uc, UC_HOOK_MEM_WRITE, addr); if (trace) { ((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE, (uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data); @@ -649,7 +649,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, // Unicorn: callback on memory write if (uc->hook_mem_write) { - struct hook_struct *trace = hook_find(uc, UC_MEM_WRITE, addr); + struct hook_struct *trace = hook_find(uc, UC_HOOK_MEM_WRITE, addr); if (trace) { ((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE, (uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data); diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 209b1d58..6d93efe2 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -2944,8 +2944,8 @@ typedef void (*SSEFunc_0_epl)(TCGContext *s, TCGv_ptr env, TCGv_ptr reg, TCGv_i6 typedef void (*SSEFunc_0_epp)(TCGContext *s, TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b); typedef void (*SSEFunc_0_eppi)(TCGContext *s, TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); -typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); -typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, +typedef void (*SSEFunc_0_ppi)(TCGContext *s, TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); +typedef void (*SSEFunc_0_eppt)(TCGContext *s, TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv val); #define SSE_SPECIAL ((void *)1) @@ -4669,7 +4669,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(tcg_ctx, cpu_ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp; - sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(tcg_ctx, val)); + sse_fn_ppi(tcg_ctx, cpu_ptr0, cpu_ptr1, tcg_const_i32(tcg_ctx, val)); break; case 0xc2: /* compare insns */ @@ -4694,7 +4694,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(tcg_ctx, cpu_ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp; - sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0); + sse_fn_eppt(tcg_ctx, cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0); break; default: tcg_gen_addi_ptr(tcg_ctx, cpu_ptr0, cpu_env, op1_offset); @@ -8175,9 +8175,15 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, // printf("\n"); if (changed_cc_op) { if (cc_op_dirty) +#if TCG_TARGET_REG_BITS == 32 + *(save_opparam_ptr + 16) = s->pc - pc_start; + else + *(save_opparam_ptr + 14) = s->pc - pc_start; +#else *(save_opparam_ptr + 12) = s->pc - pc_start; else *(save_opparam_ptr + 10) = s->pc - pc_start; +#endif } else { *(save_opparam_ptr + 1) = s->pc - pc_start; } diff --git a/qemu/util/qemu-thread-posix.c b/qemu/util/qemu-thread-posix.c index 1e8f8304..34632bca 100644 --- a/qemu/util/qemu-thread-posix.c +++ b/qemu/util/qemu-thread-posix.c @@ -389,7 +389,7 @@ void qemu_event_wait(QemuEvent *ev) } } -void qemu_thread_create(QemuThread *thread, const char *name, +void qemu_thread_create(struct uc_struct *uc, QemuThread *thread, const char *name, void *(*start_routine)(void*), void *arg, int mode) { @@ -426,7 +426,7 @@ void qemu_thread_create(QemuThread *thread, const char *name, pthread_attr_destroy(&attr); } -void qemu_thread_get_self(QemuThread *thread) +void qemu_thread_get_self(struct uc_struct *uc, QemuThread *thread) { thread->thread = pthread_self(); } @@ -436,7 +436,7 @@ bool qemu_thread_is_self(QemuThread *thread) return pthread_equal(pthread_self(), thread->thread); } -void qemu_thread_exit(void *retval) +void qemu_thread_exit(struct uc_struct *uc, void *retval) { pthread_exit(retval); } diff --git a/qemu/util/qemu-thread-win32.c b/qemu/util/qemu-thread-win32.c index 004f17bf..3f7f7015 100644 --- a/qemu/util/qemu-thread-win32.c +++ b/qemu/util/qemu-thread-win32.c @@ -16,6 +16,8 @@ #include #include +#include "uc_priv.h" + static void error_exit(int err, const char *msg) { @@ -264,10 +266,9 @@ struct QemuThreadData { bool exited; void *ret; CRITICAL_SECTION cs; + struct uc_struct *uc; }; -static __thread QemuThreadData *qemu_thread_data; - static unsigned __stdcall win32_start_routine(void *arg) { QemuThreadData *data = (QemuThreadData *) arg; @@ -278,14 +279,13 @@ static unsigned __stdcall win32_start_routine(void *arg) g_free(data); data = NULL; } - qemu_thread_data = data; - qemu_thread_exit(start_routine(thread_arg)); + qemu_thread_exit(data->uc, start_routine(thread_arg)); abort(); } -void qemu_thread_exit(void *arg) +void qemu_thread_exit(struct uc_struct *uc, void *arg) { - QemuThreadData *data = qemu_thread_data; + QemuThreadData *data = uc->qemu_thread_data; if (data) { assert(data->mode != QEMU_THREAD_DETACHED); @@ -326,7 +326,7 @@ void *qemu_thread_join(QemuThread *thread) return ret; } -void qemu_thread_create(QemuThread *thread, const char *name, +void qemu_thread_create(struct uc_struct *uc, QemuThread *thread, const char *name, void *(*start_routine)(void *), void *arg, int mode) { @@ -338,6 +338,9 @@ void qemu_thread_create(QemuThread *thread, const char *name, data->arg = arg; data->mode = mode; data->exited = false; + data->uc = uc; + + uc->qemu_thread_data = data; if (data->mode != QEMU_THREAD_DETACHED) { InitializeCriticalSection(&data->cs); @@ -352,9 +355,9 @@ void qemu_thread_create(QemuThread *thread, const char *name, thread->data = (mode == QEMU_THREAD_DETACHED) ? NULL : data; } -void qemu_thread_get_self(QemuThread *thread) +void qemu_thread_get_self(struct uc_struct *uc, QemuThread *thread) { - thread->data = qemu_thread_data; + thread->data = uc->qemu_thread_data; thread->tid = GetCurrentThreadId(); } diff --git a/regress/rep_movsb.c b/regress/rep_movsb.c index ab49175b..c9fb6f15 100644 --- a/regress/rep_movsb.c +++ b/regress/rep_movsb.c @@ -128,7 +128,7 @@ int main(int argc, char **argv, char **envp) printf("ok %d - Program written to memory\n", log_num++); } - if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); return 5; } @@ -137,7 +137,7 @@ int main(int argc, char **argv, char **envp) } // intercept memory write events only, NOT read events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) { + if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); return 6; } diff --git a/uc.c b/uc.c index 0492ba6e..efe02622 100644 --- a/uc.c +++ b/uc.c @@ -414,7 +414,7 @@ static void *_timeout_fn(void *arg) static void enable_emu_timer(struct uc_struct *uc, uint64_t timeout) { uc->timeout = timeout; - qemu_thread_create(&uc->timer, "timeout", _timeout_fn, + qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn, uc, QEMU_THREAD_JOINABLE); } @@ -530,7 +530,7 @@ static int _hook_code(struct uc_struct *uc, int type, uint64_t begin, uint64_t e } -static uc_err _hook_mem_access(struct uc_struct *uc, uc_mem_type type, +static uc_err _hook_mem_access(struct uc_struct *uc, uc_hook_t type, uint64_t begin, uint64_t end, void *callback, void *user_data, uc_hook_h *hh) { @@ -718,16 +718,17 @@ uc_err uc_hook_add(struct uc_struct *uc, uc_hook_h *hh, uc_hook_t type, void *ca case UC_HOOK_MEM_READ: begin = va_arg(valist, uint64_t); end = va_arg(valist, uint64_t); - ret = _hook_mem_access(uc, UC_MEM_READ, begin, end, callback, user_data, hh); + ret = _hook_mem_access(uc, UC_HOOK_MEM_READ, begin, end, callback, user_data, hh); break; case UC_HOOK_MEM_WRITE: begin = va_arg(valist, uint64_t); end = va_arg(valist, uint64_t); - ret = _hook_mem_access(uc, UC_MEM_WRITE, begin, end, callback, user_data, hh); + ret = _hook_mem_access(uc, UC_HOOK_MEM_WRITE, begin, end, callback, user_data, hh); + break; case UC_HOOK_MEM_READ_WRITE: begin = va_arg(valist, uint64_t); end = va_arg(valist, uint64_t); - ret = _hook_mem_access(uc, UC_MEM_READ_WRITE, begin, end, callback, user_data, hh); + ret = _hook_mem_access(uc, UC_HOOK_MEM_READ_WRITE, begin, end, callback, user_data, hh); break; }