Merge branch 'memleak' into m2

This commit is contained in:
Nguyen Anh Quynh 2016-04-18 12:48:13 +08:00
commit cc6cbc5cf7
40 changed files with 1225 additions and 66 deletions

7
.gitignore vendored
View file

@ -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

View file

@ -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];

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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',

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -90,6 +90,9 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
GetLastError());
exit(1);
}
CloseHandle(cpu->hThread);
cpu->hThread = 0;
}
#endif
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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]);
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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]);
}

View file

@ -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:

View file

@ -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);
}
}

178
tests/regress/memleak_arm.c Normal file
View file

@ -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 <io.h>
#include <windows.h>
#define PRIx64 "llX"
#ifdef DYNLOAD
#include "unicorn_dynload.h"
#else // DYNLOAD
#include <unicorn/unicorn.h>
#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 <unistd.h>
#include <inttypes.h>
#include <unicorn/unicorn.h>
#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;
}

View file

@ -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 <io.h>
#include <windows.h>
#define PRIx64 "llX"
#ifdef DYNLOAD
#include "unicorn_dynload.h"
#else // DYNLOAD
#include <unicorn/unicorn.h>
#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 <unistd.h>
#include <inttypes.h>
#include <unicorn/unicorn.h>
#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;
}

View file

@ -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 <io.h>
#include <windows.h>
#define PRIx64 "llX"
#ifdef DYNLOAD
#include "unicorn_dynload.h"
#else // DYNLOAD
#include <unicorn/unicorn.h>
#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 <unistd.h>
#include <inttypes.h>
#include <unicorn/unicorn.h>
#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;
}

View file

@ -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 <io.h>
#include <windows.h>
#define PRIx64 "llX"
#ifdef DYNLOAD
#include "unicorn_dynload.h"
#else // DYNLOAD
#include <unicorn/unicorn.h>
#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 <unistd.h>
#include <inttypes.h>
#include <unicorn/unicorn.h>
#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;
}

View file

@ -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 <io.h>
#include <windows.h>
#define PRIx64 "llX"
#ifdef DYNLOAD
#include "unicorn_dynload.h"
#else // DYNLOAD
#include <unicorn/unicorn.h>
#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 <unistd.h>
#include <inttypes.h>
#include <unicorn/unicorn.h>
#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;
}

306
tests/regress/memleak_x86.c Normal file
View file

@ -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 <io.h>
#include <windows.h>
#define PRIx64 "llX"
#ifdef DYNLOAD
#include "unicorn_dynload.h"
#else // DYNLOAD
#include <unicorn/unicorn.h>
#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 <unistd.h>
#include <inttypes.h>
#include <unicorn/unicorn.h>
#endif // _MSC_VER
// common includes
#include <string.h>
// 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;
}

View file

@ -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");

View file

@ -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);
}

View file

@ -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);
}

6
uc.c
View file

@ -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;