From 05a4412f11e9f48c8a67c48cd2fc71684873bb63 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 24 Dec 2013 10:37:58 +0100 Subject: [PATCH] libdwfl: Fix memory leak in linux-core-attach. Allow reiterating threads. core_next_thread would allocate a new thread_arg each time but never free it. We only need one active thread_arg to keep the state. Free it when there are no more threads. It was also not possible to start walking all threads in the core again. Just reset the note offset at the start. Signed-off-by: Mark Wielaard --- libdwfl/ChangeLog | 6 ++++++ libdwfl/linux-core-attach.c | 27 +++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 807fc2b1e..3f9c52554 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,9 @@ +2013-12-24 Mark Wielaard + + * linux-core-attach.c (core_next_thread): Check whether thread_argp + is NULL. Reset core_arg->thread_note_offset and malloc a thread_arg + in that case. Free thread_arg if there are no more threads. + 2013-12-23 Mark Wielaard * dwfl_segment_report_module.c (dwfl_segment_report_module): Free diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c index f259b2c34..cc11467b2 100644 --- a/libdwfl/linux-core-attach.c +++ b/libdwfl/linux-core-attach.c @@ -106,6 +106,23 @@ core_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg, size_t desc_offset; Elf_Data *note_data = core_arg->note_data; size_t offset; + + struct thread_arg *thread_arg; + if (*thread_argp == NULL) + { + core_arg->thread_note_offset = 0; + thread_arg = malloc (sizeof (*thread_arg)); + if (thread_arg == NULL) + { + __libdwfl_seterrno (DWFL_E_NOMEM); + return -1; + } + thread_arg->core_arg = core_arg; + *thread_argp = thread_arg; + } + else + thread_arg = (struct thread_arg *) *thread_argp; + while (offset = core_arg->thread_note_offset, offset < note_data->d_size && (core_arg->thread_note_offset = gelf_getnote (note_data, offset, &nhdr, &name_offset, @@ -138,17 +155,11 @@ core_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg, ? be32toh (val32) : le32toh (val32)); pid_t tid = (int32_t) val32; eu_static_assert (sizeof val32 <= sizeof tid); - struct thread_arg *thread_arg = malloc (sizeof (*thread_arg)); - if (thread_arg == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - thread_arg->core_arg = core_arg; thread_arg->note_offset = offset; - *thread_argp = thread_arg; return tid; } + + free (thread_arg); return 0; } -- 2.47.2