diff --git a/.gitignore b/.gitignore index d80af2ce..bcce4e55 100644 --- a/.gitignore +++ b/.gitignore @@ -152,6 +152,13 @@ mem_fuzz test_x86_soft_paging test_hookcounts +memleak_x86 +memleak_arm +memleak_arm64 +memleak_mips +memleak_m68k +memleak_sparc + ################# ## Visual Studio diff --git a/include/uc_priv.h b/include/uc_priv.h index 916f0c56..d91b3b64 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -199,10 +199,12 @@ struct uc_struct { QemuMutex flat_view_mutex; QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners; QTAILQ_HEAD(, AddressSpace) address_spaces; + MachineState *machine_state; // qom/object.c GHashTable *type_table; Type type_interface; Object *root; + Object *owner; bool enumerating_types; // util/module.c ModuleTypeList init_type_list[MODULE_INIT_MAX]; diff --git a/qemu/aarch64.h b/qemu/aarch64.h index d75c06e1..ad923e4d 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_aarch64 #define qemu_clock_ptr qemu_clock_ptr_aarch64 #define qemu_clocks qemu_clocks_aarch64 -#define qemu_cond_destroy qemu_cond_destroy_aarch64 #define qemu_cpu_is_self qemu_cpu_is_self_aarch64 #define qemu_cpu_kick_thread qemu_cpu_kick_thread_aarch64 #define qemu_daemon qemu_daemon_aarch64 @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_aarch64 #define qemu_loglevel_mask qemu_loglevel_mask_aarch64 #define qemu_log_vprintf qemu_log_vprintf_aarch64 -#define qemu_mutex_destroy qemu_mutex_destroy_aarch64 #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_aarch64 #define qemu_mutex_trylock qemu_mutex_trylock_aarch64 #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index ef850c24..009168bf 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_arm #define qemu_clock_ptr qemu_clock_ptr_arm #define qemu_clocks qemu_clocks_arm -#define qemu_cond_destroy qemu_cond_destroy_arm #define qemu_cpu_is_self qemu_cpu_is_self_arm #define qemu_cpu_kick_thread qemu_cpu_kick_thread_arm #define qemu_daemon qemu_daemon_arm @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_arm #define qemu_loglevel_mask qemu_loglevel_mask_arm #define qemu_log_vprintf qemu_log_vprintf_arm -#define qemu_mutex_destroy qemu_mutex_destroy_arm #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_arm #define qemu_mutex_trylock qemu_mutex_trylock_arm #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_arm diff --git a/qemu/cpus.c b/qemu/cpus.c index 64c73b0b..e11d943b 100644 --- a/qemu/cpus.c +++ b/qemu/cpus.c @@ -28,6 +28,7 @@ #include "config-host.h" #include "sysemu/sysemu.h" #include "sysemu/cpus.h" +#include "qemu/thread.h" #include "exec/address-spaces.h" // debug, can be removed later @@ -76,7 +77,9 @@ void pause_all_vcpus(struct uc_struct *uc) CPUState *cpu; CPU_FOREACH(cpu) { - qemu_thread_join(cpu->thread); // qq: fix qemu_thread_join() to work for instance + qemu_thread_join(uc, cpu->thread); + free(cpu->thread); + cpu->thread = NULL; } } @@ -146,17 +149,6 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) } while (1) { -#if 0 - int count = 0; - if (count < 10) { - count++; - unsigned int eip = X86_CPU(mycpu)->env.eip; - printf(">>> current EIP = %x\n", eip); - printf(">>> ECX = %x\n", (unsigned int)X86_CPU(mycpu)->env.regs[R_ECX]); - printf(">>> EDX = %x\n", (unsigned int)X86_CPU(mycpu)->env.regs[R_EDX]); - } -#endif - if (tcg_exec_all(uc)) break; } @@ -164,6 +156,13 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) CPU_FOREACH(cpu) { cpu->thread_id = 0; cpu->created = false; + qemu_cond_destroy(cpu->halt_cond); + free(cpu->halt_cond); +#ifdef _WIN32 + if (cpu->hThread) + CloseHandle(cpu->hThread); +#endif + cpu->halt_cond = NULL; } qemu_mutex_unlock(&uc->qemu_global_mutex); diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 46bab7c9..14906321 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -2423,7 +2423,6 @@ symbols = ( 'qemu_clock_get_us', 'qemu_clock_ptr', 'qemu_clocks', - 'qemu_cond_destroy', 'qemu_cpu_is_self', 'qemu_cpu_kick_thread', 'qemu_daemon', @@ -2451,7 +2450,6 @@ symbols = ( 'qemu_log_flush', 'qemu_loglevel_mask', 'qemu_log_vprintf', - 'qemu_mutex_destroy', 'qemu_mutex_lock_ramlist', 'qemu_mutex_trylock', 'qemu_mutex_unlock_ramlist', diff --git a/qemu/hw/arm/tosa.c b/qemu/hw/arm/tosa.c index fe9eaf6e..8630e46e 100644 --- a/qemu/hw/arm/tosa.c +++ b/qemu/hw/arm/tosa.c @@ -20,7 +20,7 @@ static int tosa_init(struct uc_struct *uc, MachineState *machine) { //cpu_arm_init(uc, "pxa255"); - cpu_arm_init(uc, "cortex-a15"); // FIXME + uc->cpu = cpu_arm_init(uc, "cortex-a15"); // FIXME return 0; } diff --git a/qemu/hw/arm/virt.c b/qemu/hw/arm/virt.c index 554e89d7..e2a68412 100644 --- a/qemu/hw/arm/virt.c +++ b/qemu/hw/arm/virt.c @@ -54,7 +54,7 @@ static int machvirt_init(struct uc_struct *uc, MachineState *machine) return -1; } - cpuobj = object_new(uc, object_class_get_name(oc)); + uc->cpu = cpuobj = object_new(uc, object_class_get_name(oc)); object_property_set_bool(uc, cpuobj, true, "realized", NULL); } diff --git a/qemu/include/qemu/thread.h b/qemu/include/qemu/thread.h index 2a402673..d8f477d7 100644 --- a/qemu/include/qemu/thread.h +++ b/qemu/include/qemu/thread.h @@ -57,7 +57,7 @@ struct uc_struct; int 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_join(struct uc_struct *uc, QemuThread *thread); void qemu_thread_get_self(struct uc_struct *uc, QemuThread *thread); bool qemu_thread_is_self(QemuThread *thread); void qemu_thread_exit(struct uc_struct *uc, void *retval); diff --git a/qemu/m68k.h b/qemu/m68k.h index 8e41d569..7c671e16 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_m68k #define qemu_clock_ptr qemu_clock_ptr_m68k #define qemu_clocks qemu_clocks_m68k -#define qemu_cond_destroy qemu_cond_destroy_m68k #define qemu_cpu_is_self qemu_cpu_is_self_m68k #define qemu_cpu_kick_thread qemu_cpu_kick_thread_m68k #define qemu_daemon qemu_daemon_m68k @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_m68k #define qemu_loglevel_mask qemu_loglevel_mask_m68k #define qemu_log_vprintf qemu_log_vprintf_m68k -#define qemu_mutex_destroy qemu_mutex_destroy_m68k #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_m68k #define qemu_mutex_trylock qemu_mutex_trylock_m68k #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_m68k diff --git a/qemu/main-loop.c b/qemu/main-loop.c index bb7c3d02..9d7d6290 100644 --- a/qemu/main-loop.c +++ b/qemu/main-loop.c @@ -90,6 +90,9 @@ static void qemu_cpu_kick_thread(CPUState *cpu) GetLastError()); exit(1); } + + CloseHandle(cpu->hThread); + cpu->hThread = 0; } #endif } diff --git a/qemu/memory.c b/qemu/memory.c index af38155f..3ab5c7a3 100644 --- a/qemu/memory.c +++ b/qemu/memory.c @@ -70,6 +70,7 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr) { int i; target_ulong addr; + Object *obj; // Make sure all pages associated with the MemoryRegion are flushed // Only need to do this if we are in a running state @@ -87,8 +88,12 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr) //shift remainder of array down over deleted pointer memmove(&uc->mapped_blocks[i], &uc->mapped_blocks[i + 1], sizeof(MemoryRegion*) * (uc->mapped_block_count - i)); mr->destructor(mr); - g_free((char *)mr->name); + obj = OBJECT(mr); + obj->ref = 1; + obj->free = g_free; g_free(mr->ioeventfds); + g_free((char *)mr->name); + mr->name = NULL; break; } } @@ -97,6 +102,7 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr) int memory_free(struct uc_struct *uc) { MemoryRegion *mr; + Object *obj; int i; get_system_memory(uc)->enabled = false; @@ -105,9 +111,10 @@ int memory_free(struct uc_struct *uc) mr->enabled = false; memory_region_del_subregion(get_system_memory(uc), mr); mr->destructor(mr); - g_free((char *)mr->name); + obj = OBJECT(mr); + obj->ref = 1; + obj->free = g_free; g_free(mr->ioeventfds); - g_free(mr); } return 0; @@ -948,6 +955,7 @@ void memory_region_init(struct uc_struct *uc, MemoryRegion *mr, { if (!owner) { owner = qdev_get_machine(uc); + uc->owner = owner; } object_initialize(uc, mr, sizeof(*mr), TYPE_MEMORY_REGION); diff --git a/qemu/mips.h b/qemu/mips.h index 0861ed05..c596a0bb 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_mips #define qemu_clock_ptr qemu_clock_ptr_mips #define qemu_clocks qemu_clocks_mips -#define qemu_cond_destroy qemu_cond_destroy_mips #define qemu_cpu_is_self qemu_cpu_is_self_mips #define qemu_cpu_kick_thread qemu_cpu_kick_thread_mips #define qemu_daemon qemu_daemon_mips @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_mips #define qemu_loglevel_mask qemu_loglevel_mask_mips #define qemu_log_vprintf qemu_log_vprintf_mips -#define qemu_mutex_destroy qemu_mutex_destroy_mips #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_mips #define qemu_mutex_trylock qemu_mutex_trylock_mips #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index be1a4b4c..8180af93 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_mips64 #define qemu_clock_ptr qemu_clock_ptr_mips64 #define qemu_clocks qemu_clocks_mips64 -#define qemu_cond_destroy qemu_cond_destroy_mips64 #define qemu_cpu_is_self qemu_cpu_is_self_mips64 #define qemu_cpu_kick_thread qemu_cpu_kick_thread_mips64 #define qemu_daemon qemu_daemon_mips64 @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_mips64 #define qemu_loglevel_mask qemu_loglevel_mask_mips64 #define qemu_log_vprintf qemu_log_vprintf_mips64 -#define qemu_mutex_destroy qemu_mutex_destroy_mips64 #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_mips64 #define qemu_mutex_trylock qemu_mutex_trylock_mips64 #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 9e144d9b..e93b082b 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_mips64el #define qemu_clock_ptr qemu_clock_ptr_mips64el #define qemu_clocks qemu_clocks_mips64el -#define qemu_cond_destroy qemu_cond_destroy_mips64el #define qemu_cpu_is_self qemu_cpu_is_self_mips64el #define qemu_cpu_kick_thread qemu_cpu_kick_thread_mips64el #define qemu_daemon qemu_daemon_mips64el @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_mips64el #define qemu_loglevel_mask qemu_loglevel_mask_mips64el #define qemu_log_vprintf qemu_log_vprintf_mips64el -#define qemu_mutex_destroy qemu_mutex_destroy_mips64el #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_mips64el #define qemu_mutex_trylock qemu_mutex_trylock_mips64el #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 8fb00f62..66e0c9d9 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_mipsel #define qemu_clock_ptr qemu_clock_ptr_mipsel #define qemu_clocks qemu_clocks_mipsel -#define qemu_cond_destroy qemu_cond_destroy_mipsel #define qemu_cpu_is_self qemu_cpu_is_self_mipsel #define qemu_cpu_kick_thread qemu_cpu_kick_thread_mipsel #define qemu_daemon qemu_daemon_mipsel @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_mipsel #define qemu_loglevel_mask qemu_loglevel_mask_mipsel #define qemu_log_vprintf qemu_log_vprintf_mipsel -#define qemu_mutex_destroy qemu_mutex_destroy_mipsel #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_mipsel #define qemu_mutex_trylock qemu_mutex_trylock_mipsel #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 5d2f53f2..60c518ac 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_powerpc #define qemu_clock_ptr qemu_clock_ptr_powerpc #define qemu_clocks qemu_clocks_powerpc -#define qemu_cond_destroy qemu_cond_destroy_powerpc #define qemu_cpu_is_self qemu_cpu_is_self_powerpc #define qemu_cpu_kick_thread qemu_cpu_kick_thread_powerpc #define qemu_daemon qemu_daemon_powerpc @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_powerpc #define qemu_loglevel_mask qemu_loglevel_mask_powerpc #define qemu_log_vprintf qemu_log_vprintf_powerpc -#define qemu_mutex_destroy qemu_mutex_destroy_powerpc #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_powerpc #define qemu_mutex_trylock qemu_mutex_trylock_powerpc #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index cf04547f..6c48ce53 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_sparc #define qemu_clock_ptr qemu_clock_ptr_sparc #define qemu_clocks qemu_clocks_sparc -#define qemu_cond_destroy qemu_cond_destroy_sparc #define qemu_cpu_is_self qemu_cpu_is_self_sparc #define qemu_cpu_kick_thread qemu_cpu_kick_thread_sparc #define qemu_daemon qemu_daemon_sparc @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_sparc #define qemu_loglevel_mask qemu_loglevel_mask_sparc #define qemu_log_vprintf qemu_log_vprintf_sparc -#define qemu_mutex_destroy qemu_mutex_destroy_sparc #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_sparc #define qemu_mutex_trylock qemu_mutex_trylock_sparc #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 2195b1d6..8c3d73f1 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_sparc64 #define qemu_clock_ptr qemu_clock_ptr_sparc64 #define qemu_clocks qemu_clocks_sparc64 -#define qemu_cond_destroy qemu_cond_destroy_sparc64 #define qemu_cpu_is_self qemu_cpu_is_self_sparc64 #define qemu_cpu_kick_thread qemu_cpu_kick_thread_sparc64 #define qemu_daemon qemu_daemon_sparc64 @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_sparc64 #define qemu_loglevel_mask qemu_loglevel_mask_sparc64 #define qemu_log_vprintf qemu_log_vprintf_sparc64 -#define qemu_mutex_destroy qemu_mutex_destroy_sparc64 #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_sparc64 #define qemu_mutex_trylock qemu_mutex_trylock_sparc64 #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_sparc64 diff --git a/qemu/target-arm/unicorn_aarch64.c b/qemu/target-arm/unicorn_aarch64.c index 8e4bccfe..e2c593a6 100644 --- a/qemu/target-arm/unicorn_aarch64.c +++ b/qemu/target-arm/unicorn_aarch64.c @@ -15,6 +15,23 @@ static void arm64_set_pc(struct uc_struct *uc, uint64_t address) ((CPUARMState *)uc->current_cpu->env_ptr)->pc = address; } +void arm64_release(void* ctx); + +void arm64_release(void* ctx) +{ + TCGContext *s = (TCGContext *) ctx; + + g_free(s->tb_ctx.tbs); + struct uc_struct* uc = s->uc; + ARMCPU* cpu = (ARMCPU*) uc->cpu; + g_free(cpu->cpreg_indexes); + g_free(cpu->cpreg_values); + g_free(cpu->cpreg_vmstate_indexes); + g_free(cpu->cpreg_vmstate_values); + + release_common(ctx); +} + void arm64_reg_reset(struct uc_struct *uc) { CPUArchState *env = first_cpu->env_ptr; @@ -101,5 +118,6 @@ void arm64_uc_init(struct uc_struct* uc) uc->reg_write = arm64_reg_write; uc->reg_reset = arm64_reg_reset; uc->set_pc = arm64_set_pc; + uc->release = arm64_release; uc_common_init(uc); } diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index a6d9355f..40510b38 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -16,6 +16,23 @@ static void arm_set_pc(struct uc_struct *uc, uint64_t address) ((CPUARMState *)uc->current_cpu->env_ptr)->regs[15] = address; } +void arm_release(void* ctx); + +void arm_release(void* ctx) +{ + TCGContext *s = (TCGContext *) ctx; + + g_free(s->tb_ctx.tbs); + struct uc_struct* uc = s->uc; + ARMCPU* cpu = (ARMCPU*) uc->cpu; + g_free(cpu->cpreg_indexes); + g_free(cpu->cpreg_values); + g_free(cpu->cpreg_vmstate_indexes); + g_free(cpu->cpreg_vmstate_values); + + release_common(ctx); +} + void arm_reg_reset(struct uc_struct *uc) { (void)uc; @@ -137,6 +154,7 @@ void arm_uc_init(struct uc_struct* uc) uc->reg_reset = arm_reg_reset; uc->set_pc = arm_set_pc; uc->stop_interrupt = arm_stop_interrupt; + uc->release = arm_release; uc->query = arm_query; uc_common_init(uc); } diff --git a/qemu/target-i386/unicorn.c b/qemu/target-i386/unicorn.c index f4d134bd..004e2a4a 100644 --- a/qemu/target-i386/unicorn.c +++ b/qemu/target-i386/unicorn.c @@ -21,9 +21,11 @@ void x86_release(void *ctx); void x86_release(void *ctx) { - release_common(ctx); + int i; TCGContext *s = (TCGContext *) ctx; + release_common(ctx); + // arch specific g_free(s->cpu_A0); g_free(s->cpu_T[0]); @@ -35,7 +37,6 @@ void x86_release(void *ctx) g_free(s->cpu_cc_src); g_free(s->cpu_cc_src2); - int i; for (i = 0; i < CPU_NB_REGS; ++i) { g_free(s->cpu_regs[i]); } diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 2df9ccef..ca095b8b 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -35,12 +35,17 @@ static void release_common(void *t) { TCGContext *s = (TCGContext *)t; struct uc_struct* uc = s->uc; + CPUState *cpu; +#if TCG_TARGET_REG_BITS == 32 + int i; +#endif // Clean TCG. TCGOpDef* def = &s->tcg_op_defs[0]; g_free(def->args_ct); g_free(def->sorted_args); g_free(s->tcg_op_defs); + TCGPool *po, *to; for (po = s->pool_first; po; po = to) { to = po->next; @@ -55,9 +60,46 @@ static void release_common(void *t) memory_free(uc); // Clean CPU. + CPU_FOREACH(cpu) { + g_free(cpu->tcg_as_listener); + g_free(cpu->thread); + g_free(cpu->halt_cond); + } + + OBJECT(uc->machine_state->accelerator)->ref = 1; + OBJECT(uc->machine_state)->ref = 1; + OBJECT(uc->owner)->ref = 1; + OBJECT(uc->root)->ref = 1; + + object_unref(uc, OBJECT(uc->machine_state->accelerator)); + object_unref(uc, OBJECT(uc->machine_state)); object_unref(uc, uc->cpu); + object_unref(uc, OBJECT(&uc->io_mem_notdirty)); + object_unref(uc, OBJECT(&uc->io_mem_unassigned)); + object_unref(uc, OBJECT(&uc->io_mem_rom)); + object_unref(uc, OBJECT(uc->root)); g_hash_table_foreach(uc->type_table, free_table, uc); + g_free(uc->system_memory); + + if (uc->qemu_thread_data) + free(uc->qemu_thread_data); + +#if TCG_TARGET_REG_BITS == 32 + for(i = 0; i < s->nb_globals; i++) { + TCGTemp *ts = &s->temps[i]; + if (ts->base_type == TCG_TYPE_I64) { + if (ts->name && ((strcmp(ts->name+(strlen(ts->name)-2), "_0") == 0) || + (strcmp(ts->name+(strlen(ts->name)-2), "_1") == 0))) { + free((void *)ts->name); + } + } + } +#endif + + qemu_mutex_destroy(&uc->qemu_global_mutex); + qemu_cond_destroy(&uc->qemu_cpu_cond); + // Clean cache. tb_cleanup(uc); } diff --git a/qemu/util/qemu-thread-posix.c b/qemu/util/qemu-thread-posix.c index 6430f929..2fbc0bd2 100644 --- a/qemu/util/qemu-thread-posix.c +++ b/qemu/util/qemu-thread-posix.c @@ -441,7 +441,7 @@ void qemu_thread_exit(struct uc_struct *uc, void *retval) pthread_exit(retval); } -void *qemu_thread_join(QemuThread *thread) +void *qemu_thread_join(struct uc_struct *uc, QemuThread *thread) { int err; void *ret; diff --git a/qemu/util/qemu-thread-win32.c b/qemu/util/qemu-thread-win32.c index 2c2cf4ad..4732731d 100644 --- a/qemu/util/qemu-thread-win32.c +++ b/qemu/util/qemu-thread-win32.c @@ -276,6 +276,7 @@ static unsigned __stdcall win32_start_routine(void *arg) void *thread_arg = data->arg; if (data->mode == QEMU_THREAD_DETACHED) { + data->uc->qemu_thread_data = NULL; g_free(data); data = NULL; } @@ -297,7 +298,7 @@ void qemu_thread_exit(struct uc_struct *uc, void *arg) _endthreadex(0); } -void *qemu_thread_join(QemuThread *thread) +void *qemu_thread_join(struct uc_struct *uc, QemuThread *thread) { QemuThreadData *data; void *ret; @@ -322,6 +323,7 @@ void *qemu_thread_join(QemuThread *thread) ret = data->ret; assert(data->mode != QEMU_THREAD_DETACHED); DeleteCriticalSection(&data->cs); + uc->qemu_thread_data = NULL; g_free(data); return ret; } diff --git a/qemu/vl.c b/qemu/vl.c index caf6686f..f1599c6d 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -115,7 +115,7 @@ int machine_initialize(struct uc_struct *uc) current_machine = MACHINE(uc, object_new(uc, object_class_get_name( OBJECT_CLASS(machine_class)))); - + uc->machine_state = current_machine; current_machine->uc = uc; uc->cpu_exec_init_all(uc); diff --git a/qemu/x86_64.h b/qemu/x86_64.h index bbb695e5..ce8e0262 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -2417,7 +2417,6 @@ #define qemu_clock_get_us qemu_clock_get_us_x86_64 #define qemu_clock_ptr qemu_clock_ptr_x86_64 #define qemu_clocks qemu_clocks_x86_64 -#define qemu_cond_destroy qemu_cond_destroy_x86_64 #define qemu_cpu_is_self qemu_cpu_is_self_x86_64 #define qemu_cpu_kick_thread qemu_cpu_kick_thread_x86_64 #define qemu_daemon qemu_daemon_x86_64 @@ -2445,7 +2444,6 @@ #define qemu_log_flush qemu_log_flush_x86_64 #define qemu_loglevel_mask qemu_loglevel_mask_x86_64 #define qemu_log_vprintf qemu_log_vprintf_x86_64 -#define qemu_mutex_destroy qemu_mutex_destroy_x86_64 #define qemu_mutex_lock_ramlist qemu_mutex_lock_ramlist_x86_64 #define qemu_mutex_trylock qemu_mutex_trylock_x86_64 #define qemu_mutex_unlock_ramlist qemu_mutex_unlock_ramlist_x86_64 diff --git a/samples/sample_x86.c b/samples/sample_x86.c index 7b4fc120..620ce5ed 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -148,7 +148,7 @@ static uint32_t hook_in(uc_engine *uc, uint32_t port, int size, void *user_data) // callback for OUT instruction (X86). static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data) { - uint32_t tmp; + uint32_t tmp = 0; uint32_t eip; uc_reg_read(uc, UC_X86_REG_EIP, &eip); @@ -605,6 +605,7 @@ static void test_i386_inout(void) uc_err err; uc_hook trace1, trace2, trace3, trace4; + int r_eax = 0x1234; // EAX register int r_ecx = 0x6789; // ECX register @@ -913,14 +914,6 @@ int main(int argc, char **argv, char **envp) if (!strcmp(argv[1], "-16")) { test_x86_16(); } - - // test memleak - if (!strcmp(argv[1], "-0")) { - while(1) { - test_i386(); - // test_x86_64(); - } - } } else { printf("Syntax: %s <-16|-32|-64>\n", argv[0]); } diff --git a/tests/regress/Makefile b/tests/regress/Makefile index ea965593..e50a0b06 100644 --- a/tests/regress/Makefile +++ b/tests/regress/Makefile @@ -45,6 +45,13 @@ TESTS += 004-segmentation_fault_1 TESTS += 005-qemu__fatal__illegal_instruction__0000___00000404 TESTS += 006-qemu__fatal__illegal_instruction__0421___00040026 +TESTS += memleak_x86 +TESTS += memleak_arm +TESTS += memleak_arm64 +TESTS += memleak_mips +TESTS += memleak_m68k +TESTS += memleak_sparc + all: $(TESTS) clean: diff --git a/tests/regress/emu_stop_in_hook_overrun.c b/tests/regress/emu_stop_in_hook_overrun.c index c9e24647..9b962a25 100644 --- a/tests/regress/emu_stop_in_hook_overrun.c +++ b/tests/regress/emu_stop_in_hook_overrun.c @@ -47,10 +47,10 @@ bool test_passed_ok = false; // This hook is used to show that code is executing in the emulator. static void mips_codehook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { - printf("Executing: %llX\n", address); + printf("Executing: %"PRIx64"\n", address); if( address == 0x100008 ) { - printf("Stopping at: %llX\n", address); + printf("Stopping at: %"PRIx64"\n", address); uc_emu_stop(uc); } } diff --git a/tests/regress/memleak_arm.c b/tests/regress/memleak_arm.c new file mode 100644 index 00000000..21430795 --- /dev/null +++ b/tests/regress/memleak_arm.c @@ -0,0 +1,178 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate ARM code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3 +#define THUMB_CODE "\x83\xb0" // sub sp, #0xc + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_arm(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int r0 = 0x1234; // R0 register + int r2 = 0x6789; // R1 register + int r3 = 0x3333; // R2 register + int r1; // R1 register + + printf("Emulate ARM code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_ARM_REG_R0, &r0); + uc_reg_write(uc, UC_ARM_REG_R2, &r2); + uc_reg_write(uc, UC_ARM_REG_R3, &r3); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_ARM_REG_R0, &r0); + uc_reg_read(uc, UC_ARM_REG_R1, &r1); + printf(">>> R0 = 0x%x\n", r0); + printf(">>> R1 = 0x%x\n", r1); + + uc_close(uc); +} + +static void test_thumb(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int sp = 0x1234; // R0 register + + printf("Emulate THUMB code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, THUMB_CODE, sizeof(THUMB_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_ARM_REG_SP, &sp); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_ARM_REG_SP, &sp); + printf(">>> SP = 0x%x\n", sp); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_arm(); + printf("==========================\n"); + test_thumb(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_arm64.c b/tests/regress/memleak_arm64.c new file mode 100644 index 00000000..e9b43c0e --- /dev/null +++ b/tests/regress/memleak_arm64.c @@ -0,0 +1,122 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate ARM64 code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define ARM_CODE "\xab\x01\x0f\x8b" // add x11, x13, x15 + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_arm64(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int64_t x11 = 0x1234; // X11 register + int64_t x13 = 0x6789; // X13 register + int64_t x15 = 0x3333; // X15 register + + printf("Emulate ARM64 code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_ARM64_REG_X11, &x11); + uc_reg_write(uc, UC_ARM64_REG_X13, &x13); + uc_reg_write(uc, UC_ARM64_REG_X15, &x15); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_ARM64_REG_X11, &x11); + printf(">>> X11 = 0x%" PRIx64 "\n", x11); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + while(1) { + test_arm64(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_m68k.c b/tests/regress/memleak_m68k.c new file mode 100644 index 00000000..8504daf1 --- /dev/null +++ b/tests/regress/memleak_m68k.c @@ -0,0 +1,185 @@ +/* Unicorn Emulator Engine */ +/* By Loi Anh Tuan, 2015 */ + +/* Sample code to demonstrate how to emulate m68k code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + +// code to be emulated +#define M68K_CODE "\x76\xed" // movq #-19, %d3 + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_m68k(void) +{ + uc_engine *uc; + uc_hook trace1, trace2; + uc_err err; + + int d0 = 0x0000; // d0 data register + int d1 = 0x0000; // d1 data register + int d2 = 0x0000; // d2 data register + int d3 = 0x0000; // d3 data register + int d4 = 0x0000; // d4 data register + int d5 = 0x0000; // d5 data register + int d6 = 0x0000; // d6 data register + int d7 = 0x0000; // d7 data register + + int a0 = 0x0000; // a0 address register + int a1 = 0x0000; // a1 address register + int a2 = 0x0000; // a2 address register + int a3 = 0x0000; // a3 address register + int a4 = 0x0000; // a4 address register + int a5 = 0x0000; // a5 address register + int a6 = 0x0000; // a6 address register + int a7 = 0x0000; // a6 address register + + int pc = 0x0000; // program counter + int sr = 0x0000; // status register + + printf("Emulate M68K code\n"); + + // Initialize emulator in M68K mode + err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, M68K_CODE, sizeof(M68K_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_M68K_REG_D0, &d0); + uc_reg_write(uc, UC_M68K_REG_D1, &d1); + uc_reg_write(uc, UC_M68K_REG_D2, &d2); + uc_reg_write(uc, UC_M68K_REG_D3, &d3); + uc_reg_write(uc, UC_M68K_REG_D4, &d4); + uc_reg_write(uc, UC_M68K_REG_D5, &d5); + uc_reg_write(uc, UC_M68K_REG_D6, &d6); + uc_reg_write(uc, UC_M68K_REG_D7, &d7); + + uc_reg_write(uc, UC_M68K_REG_A0, &a0); + uc_reg_write(uc, UC_M68K_REG_A1, &a1); + uc_reg_write(uc, UC_M68K_REG_A2, &a2); + uc_reg_write(uc, UC_M68K_REG_A3, &a3); + uc_reg_write(uc, UC_M68K_REG_A4, &a4); + uc_reg_write(uc, UC_M68K_REG_A5, &a5); + uc_reg_write(uc, UC_M68K_REG_A6, &a6); + uc_reg_write(uc, UC_M68K_REG_A7, &a7); + + uc_reg_write(uc, UC_M68K_REG_PC, &pc); + uc_reg_write(uc, UC_M68K_REG_SR, &sr); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instruction + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_M68K_REG_D0, &d0); + uc_reg_read(uc, UC_M68K_REG_D1, &d1); + uc_reg_read(uc, UC_M68K_REG_D2, &d2); + uc_reg_read(uc, UC_M68K_REG_D3, &d3); + uc_reg_read(uc, UC_M68K_REG_D4, &d4); + uc_reg_read(uc, UC_M68K_REG_D5, &d5); + uc_reg_read(uc, UC_M68K_REG_D6, &d6); + uc_reg_read(uc, UC_M68K_REG_D7, &d7); + + uc_reg_read(uc, UC_M68K_REG_A0, &a0); + uc_reg_read(uc, UC_M68K_REG_A1, &a1); + uc_reg_read(uc, UC_M68K_REG_A2, &a2); + uc_reg_read(uc, UC_M68K_REG_A3, &a3); + uc_reg_read(uc, UC_M68K_REG_A4, &a4); + uc_reg_read(uc, UC_M68K_REG_A5, &a5); + uc_reg_read(uc, UC_M68K_REG_A6, &a6); + uc_reg_read(uc, UC_M68K_REG_A7, &a7); + + uc_reg_read(uc, UC_M68K_REG_PC, &pc); + uc_reg_read(uc, UC_M68K_REG_SR, &sr); + + printf(">>> A0 = 0x%x\t\t>>> D0 = 0x%x\n", a0, d0); + printf(">>> A1 = 0x%x\t\t>>> D1 = 0x%x\n", a1, d1); + printf(">>> A2 = 0x%x\t\t>>> D2 = 0x%x\n", a2, d2); + printf(">>> A3 = 0x%x\t\t>>> D3 = 0x%x\n", a3, d3); + printf(">>> A4 = 0x%x\t\t>>> D4 = 0x%x\n", a4, d4); + printf(">>> A5 = 0x%x\t\t>>> D5 = 0x%x\n", a5, d5); + printf(">>> A6 = 0x%x\t\t>>> D6 = 0x%x\n", a6, d6); + printf(">>> A7 = 0x%x\t\t>>> D7 = 0x%x\n", a7, d7); + printf(">>> PC = 0x%x\n", pc); + printf(">>> SR = 0x%x\n", sr); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_m68k(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_mips.c b/tests/regress/memleak_mips.c new file mode 100644 index 00000000..e82a301b --- /dev/null +++ b/tests/regress/memleak_mips.c @@ -0,0 +1,171 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate Mips code (big endian) */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define MIPS_CODE_EB "\x34\x21\x34\x56" // ori $at, $at, 0x3456; +#define MIPS_CODE_EL "\x56\x34\x21\x34" // ori $at, $at, 0x3456; + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_mips_eb(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int r1 = 0x6789; // R1 register + + printf("Emulate MIPS code (big-endian)\n"); + + // Initialize emulator in MIPS mode + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, MIPS_CODE_EB, sizeof(MIPS_CODE_EB) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_MIPS_REG_1, &r1); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_MIPS_REG_1, &r1); + printf(">>> R1 = 0x%x\n", r1); + + uc_close(uc); +} + +static void test_mips_el(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int r1 = 0x6789; // R1 register + + printf("===========================\n"); + printf("Emulate MIPS code (little-endian)\n"); + + // Initialize emulator in MIPS mode + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_MIPS_REG_1, &r1); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_MIPS_REG_1, &r1); + printf(">>> R1 = 0x%x\n", r1); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_mips_eb(); + test_mips_el(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_sparc.c b/tests/regress/memleak_sparc.c new file mode 100644 index 00000000..1493d24e --- /dev/null +++ b/tests/regress/memleak_sparc.c @@ -0,0 +1,125 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate Sparc code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define SPARC_CODE "\x86\x00\x40\x02" // add %g1, %g2, %g3; +//#define SPARC_CODE "\xbb\x70\x00\x00" // illegal code + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_sparc(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int g1 = 0x1230; // G1 register + int g2 = 0x6789; // G2 register + int g3 = 0x5555; // G3 register + + printf("Emulate SPARC code\n"); + + // Initialize emulator in Sparc mode + err = uc_open(UC_ARCH_SPARC, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, SPARC_CODE, sizeof(SPARC_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_SPARC_REG_G1, &g1); + uc_reg_write(uc, UC_SPARC_REG_G2, &g2); + uc_reg_write(uc, UC_SPARC_REG_G3, &g3); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instructions with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(SPARC_CODE) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_SPARC_REG_G3, &g3); + printf(">>> G3 = 0x%x\n", g3); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_sparc(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_x86.c b/tests/regress/memleak_x86.c new file mode 100644 index 00000000..737f7305 --- /dev/null +++ b/tests/regress/memleak_x86.c @@ -0,0 +1,306 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh & Dang Hoang Vu, 2015 */ + +/* Sample code to demonstrate how to emulate X86 code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + +// common includes +#include + + +// code to be emulated +#define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx +#define X86_CODE32_JUMP "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop +// #define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41" +//#define X86_CODE32 "\x51\x51\x51\x51" // PUSH ecx; +#define X86_CODE32_LOOP "\x41\x4a\xeb\xfe" // INC ecx; DEC edx; JMP self-loop +#define X86_CODE32_MEM_WRITE "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx +#define X86_CODE32_MEM_READ "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx + +#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx +#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx + +//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash +//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" +#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" +#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al +#define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +// callback for tracing basic blocks +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +// callback for tracing instruction +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + int eflags; + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + + uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); + printf(">>> --- EFLAGS is 0x%x\n", eflags); + + // Uncomment below code to stop the emulation using uc_emu_stop() + // if (address == 0x1000009) + // uc_emu_stop(uc); +} + +// callback for tracing instruction +static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + uint64_t rip; + + uc_reg_read(uc, UC_X86_REG_RIP, &rip); + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> RIP is 0x%"PRIx64 "\n", rip); + + // Uncomment below code to stop the emulation using uc_emu_stop() + // if (address == 0x1000009) + // uc_emu_stop(uc); +} + +static void hook_mem64(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, int64_t value, void *user_data) +{ + switch(type) { + default: break; + case UC_MEM_READ: + printf(">>> Memory is being READ at 0x%"PRIx64 ", data size = %u\n", + address, size); + break; + case UC_MEM_WRITE: + printf(">>> Memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", + address, size, value); + break; + } +} + +static void test_i386(void) +{ + uc_engine *uc; + uc_err err; + uint32_t tmp; + uc_hook trace1, trace2; + + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register + + printf("Emulate i386 code\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)) { + printf("Failed to write emulation code to memory, quit!\n"); + return; + } + + // initialize machine registers + uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instruction by having @begin > @end + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); + printf(">>> ECX = 0x%x\n", r_ecx); + printf(">>> EDX = 0x%x\n", r_edx); + + // read from memory + if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp))) + printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, tmp); + else + printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS); + + uc_close(uc); +} + +static void test_x86_64(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2, trace3, trace4; + + int64_t rax = 0x71f3029efd49d41d; + int64_t rbx = 0xd87b45277f133ddb; + int64_t rcx = 0xab40d1ffd8afc461; + int64_t rdx = 0x919317b4a733f01; + int64_t rsi = 0x4c24e753a17ea358; + int64_t rdi = 0xe509a57d2571ce96; + int64_t r8 = 0xea5b108cc2b9ab1f; + int64_t r9 = 0x19ec097c8eb618c1; + int64_t r10 = 0xec45774f00c5f682; + int64_t r11 = 0xe17e9dbec8c074aa; + int64_t r12 = 0x80f86a8dc0f6d457; + int64_t r13 = 0x48288ca5671c5492; + int64_t r14 = 0x595f72f6e4017f6e; + int64_t r15 = 0x1efd97aea331cccc; + + int64_t rsp = ADDRESS + 0x200000; + + + printf("Emulate x86_64 code\n"); + + // Initialize emulator in X86-64bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, X86_CODE64, sizeof(X86_CODE64) - 1)) { + printf("Failed to write emulation code to memory, quit!\n"); + return; + } + + // initialize machine registers + uc_reg_write(uc, UC_X86_REG_RSP, &rsp); + + uc_reg_write(uc, UC_X86_REG_RAX, &rax); + uc_reg_write(uc, UC_X86_REG_RBX, &rbx); + uc_reg_write(uc, UC_X86_REG_RCX, &rcx); + uc_reg_write(uc, UC_X86_REG_RDX, &rdx); + uc_reg_write(uc, UC_X86_REG_RSI, &rsi); + uc_reg_write(uc, UC_X86_REG_RDI, &rdi); + uc_reg_write(uc, UC_X86_REG_R8, &r8); + uc_reg_write(uc, UC_X86_REG_R9, &r9); + uc_reg_write(uc, UC_X86_REG_R10, &r10); + uc_reg_write(uc, UC_X86_REG_R11, &r11); + uc_reg_write(uc, UC_X86_REG_R12, &r12); + uc_reg_write(uc, UC_X86_REG_R13, &r13); + uc_reg_write(uc, UC_X86_REG_R14, &r14); + uc_reg_write(uc, UC_X86_REG_R15, &r15); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instructions in the range [ADDRESS, ADDRESS+20] + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, (uint64_t)ADDRESS, (uint64_t)(ADDRESS+20)); + + // tracing all memory WRITE access (with @begin > @end) + uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all memory READ access (with @begin > @end) + uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_X86_REG_RAX, &rax); + uc_reg_read(uc, UC_X86_REG_RBX, &rbx); + uc_reg_read(uc, UC_X86_REG_RCX, &rcx); + uc_reg_read(uc, UC_X86_REG_RDX, &rdx); + uc_reg_read(uc, UC_X86_REG_RSI, &rsi); + uc_reg_read(uc, UC_X86_REG_RDI, &rdi); + uc_reg_read(uc, UC_X86_REG_R8, &r8); + uc_reg_read(uc, UC_X86_REG_R9, &r9); + uc_reg_read(uc, UC_X86_REG_R10, &r10); + uc_reg_read(uc, UC_X86_REG_R11, &r11); + uc_reg_read(uc, UC_X86_REG_R12, &r12); + uc_reg_read(uc, UC_X86_REG_R13, &r13); + uc_reg_read(uc, UC_X86_REG_R14, &r14); + uc_reg_read(uc, UC_X86_REG_R15, &r15); + + printf(">>> RAX = 0x%" PRIx64 "\n", rax); + printf(">>> RBX = 0x%" PRIx64 "\n", rbx); + printf(">>> RCX = 0x%" PRIx64 "\n", rcx); + printf(">>> RDX = 0x%" PRIx64 "\n", rdx); + printf(">>> RSI = 0x%" PRIx64 "\n", rsi); + printf(">>> RDI = 0x%" PRIx64 "\n", rdi); + printf(">>> R8 = 0x%" PRIx64 "\n", r8); + printf(">>> R9 = 0x%" PRIx64 "\n", r9); + printf(">>> R10 = 0x%" PRIx64 "\n", r10); + printf(">>> R11 = 0x%" PRIx64 "\n", r11); + printf(">>> R12 = 0x%" PRIx64 "\n", r12); + printf(">>> R13 = 0x%" PRIx64 "\n", r13); + printf(">>> R14 = 0x%" PRIx64 "\n", r14); + printf(">>> R15 = 0x%" PRIx64 "\n", r15); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + while(1) { + test_i386(); + test_x86_64(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/mips_branch_likely_issue.c b/tests/regress/mips_branch_likely_issue.c index b02cf864..75926692 100644 --- a/tests/regress/mips_branch_likely_issue.c +++ b/tests/regress/mips_branch_likely_issue.c @@ -61,7 +61,7 @@ bool test2_delayslot_hooked = false; // This hook is used to show that code is executing in the emulator. static void mips_codehook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { - printf("Test %d Executing: %llX\n", test_num, address); + printf("Test %d Executing: %"PRIx64"\n", test_num, address); if( test_num == 1 && address == 0x100010 ) { printf("Delay slot hook called!\n"); diff --git a/tests/regress/mips_delay_slot_code_hook.c b/tests/regress/mips_delay_slot_code_hook.c index 663ae979..1feca5c1 100644 --- a/tests/regress/mips_delay_slot_code_hook.c +++ b/tests/regress/mips_delay_slot_code_hook.c @@ -59,7 +59,7 @@ static void mips_codehook(uc_engine *uc, uint64_t address, uint32_t size, void * printf("\nloop %d:\n", loop_count); loop_count++; } - printf("Code: %llX\n", address); + printf("Code: %"PRIx64"\n", address); } diff --git a/tests/regress/threaded_emu_start.c b/tests/regress/threaded_emu_start.c index de6907e3..b75261c4 100644 --- a/tests/regress/threaded_emu_start.c +++ b/tests/regress/threaded_emu_start.c @@ -65,7 +65,7 @@ int loop_count = 0; // This hook is used to show that code is executing in the emulator. static void mips_codehook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { - printf("Code: %llX\n", address); + printf("Code: %"PRIx64"\n", address); } diff --git a/uc.c b/uc.c index 90ea8da3..188affab 100644 --- a/uc.c +++ b/uc.c @@ -285,9 +285,7 @@ uc_err uc_close(uc_engine *uc) if (uc->release) uc->release(uc->tcg_ctx); -#ifndef _WIN32 free(uc->l1_map); -#endif if (uc->bounce.buffer) { free(uc->bounce.buffer); @@ -295,8 +293,6 @@ uc_err uc_close(uc_engine *uc) g_free(uc->tcg_ctx); - free((void*) uc->system_memory->name); - g_free(uc->system_memory); g_hash_table_destroy(uc->type_table); for (i = 0; i < DIRTY_MEMORY_NUM; i++) { @@ -586,7 +582,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time if (timeout) { // wait for the timer to finish - qemu_thread_join(&uc->timer); + qemu_thread_join(uc, &uc->timer); } return uc->invalid_error;