Fix memory leaks as reported by DrMemory and Valgrind.

ARM and probably the rest of the arches have significant memory leaks as
they have no release interface.

Additionally, DrMemory does not have 64-bit support and thus I can't
test the 64-bit version under Windows. Under Linux valgrind supports
both 32-bit and 64-bit but there are different macros and code for Linux
and Windows.
This commit is contained in:
farmdve 2016-01-08 01:41:45 +02:00
parent 13726b3d40
commit 036763d6ae
22 changed files with 85 additions and 45 deletions

View File

@ -130,10 +130,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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); // qq: fix qemu_thread_join() to work for instance
free(cpu->thread);
cpu->thread = NULL;
}
}
@ -164,6 +167,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

@ -2420,7 +2420,6 @@ symbols = (
'qemu_clock_get_us',
'qemu_clock_ptr',
'qemu_clocks',
'qemu_cond_destroy',
'qemu_cpu_is_self',
'qemu_cpu_kick_thread',
'qemu_daemon',
@ -2448,7 +2447,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

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

@ -2414,7 +2414,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
@ -2442,7 +2441,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
memcpy(&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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -2414,7 +2414,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
@ -2442,7 +2441,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

@ -35,6 +35,7 @@ static void release_common(void *t)
{
TCGContext *s = (TCGContext *)t;
struct uc_struct* uc = s->uc;
CPUState *cpu;
// Clean TCG.
TCGOpDef* def = &s->tcg_op_defs[0];
@ -55,9 +56,48 @@ 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(int 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

@ -107,15 +107,18 @@ int machine_initialize(struct uc_struct *uc)
module_call_init(uc, MODULE_INIT_MACHINE);
// this will auto initialize all register objects above.
machine_class = find_default_machine(uc, uc->arch);
if (machine_class == NULL) {
//fprintf(stderr, "No machine specified, and there is no default.\n"
// "Use -machine help to list supported machines!\n");
return -2;
if(!uc->machine_state)
{
if (machine_class == NULL) {
//fprintf(stderr, "No machine specified, and there is no default.\n"
// "Use -machine help to list supported machines!\n");
return -2;
}
current_machine = MACHINE(uc, object_new(uc, object_class_get_name(
OBJECT_CLASS(machine_class))));
uc->machine_state = current_machine;
}
current_machine = MACHINE(uc, object_new(uc, object_class_get_name(
OBJECT_CLASS(machine_class))));
current_machine->uc = uc;
uc->cpu_exec_init_all(uc);

View File

@ -2414,7 +2414,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
@ -2442,7 +2441,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

8
uc.c
View File

@ -263,9 +263,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);
@ -273,8 +271,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++) {
@ -282,7 +278,7 @@ uc_err uc_close(uc_engine *uc)
}
// TODO: remove uc->root (created with object_new())
uc->root->free(uc->root);
//uc->root->free(uc->root);
free(uc->hook_callbacks);
@ -524,7 +520,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;