summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2013-12-24 10:37:58 +0100
committerMark Wielaard <[email protected]>2013-12-31 13:58:32 +0100
commit05a4412f11e9f48c8a67c48cd2fc71684873bb63 (patch)
tree4bbf1f0f691e5906a3071a5d7c5c4ef4e4baf80f
parentb20ca0bd7fba0743fa97df2d42f6fd3c7b206039 (diff)
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 <[email protected]>
-rw-r--r--libdwfl/ChangeLog6
-rw-r--r--libdwfl/linux-core-attach.c27
2 files changed, 25 insertions, 8 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 807fc2b1..3f9c5255 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2013-12-24 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
* 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 f259b2c3..cc11467b 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;
}