[PATCH] libdw: Don't leak duplicate FDEs.
by Mark Wielaard
Although it isn't supposed to happen there could be FDEs that cover the
same address range. Don't leak such FDEs and use an existing FDE for
consistency.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 4 ++++
libdw/fde.c | 11 ++++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 10df13b..f8b4793 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,7 @@
+2015-12-02 Mark Wielaard <mjw(a)redhat.com>
+
+ * fde.c (intern_fde): Don't leak duplicate FDEs.
+
2015-12-01 Mark Wielaard <mjw(a)redhat.com>
* fde.c (intern_fde): Don't intern an fde that doesn't cover a
diff --git a/libdw/fde.c b/libdw/fde.c
index 2a59d3e..f5f6fbe 100644
--- a/libdw/fde.c
+++ b/libdw/fde.c
@@ -119,12 +119,21 @@ intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry)
fde->instructions += cie->fde_augmentation_data_size;
/* Add the new entry to the search tree. */
- if (tsearch (fde, &cache->fde_tree, &compare_fde) == NULL)
+ struct dwarf_fde **tres = tsearch (fde, &cache->fde_tree, &compare_fde);
+ if (tres == NULL)
{
free (fde);
__libdw_seterrno (DWARF_E_NOMEM);
return NULL;
}
+ else if (*tres != fde)
+ {
+ /* There is already an FDE in the cache that covers the same
+ address range. That is odd. Ignore this FDE. And just use
+ the one in the cache for consistency. */
+ free (fde);
+ return *tres;
+ }
return fde;
}
--
2.5.0
8 years, 3 months
[PATCH] nm: If the file is ET_REL and we need Dwarf use libdwfl to get it relocated.
by Mark Wielaard
If we need Dwarf and the file is ET_REL use the same trick as in readelf
to get a relocated Dwarf. Otherwise lots of references in the debug_info
will come out as zero.
This also explains the "bogus" Dwarf seen that caused the memory leak in
the local_root that was fixed previously.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 10 ++++++
src/nm.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 116 insertions(+), 8 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index ffc1b29..b5b5e4a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,15 @@
2015-12-02 Mark Wielaard <mjw(a)redhat.com>
+ * nm.c (process_file): Accept fd and pass it on.
+ (handle_elf): Likewise.
+ (find_no_debuginfo): New.
+ (struct getdbg): Likewise.
+ (getdbg_dwflmod): Likewise.
+ (show_symbols): Take fd. If the file is ET_REL use libdwfl to get
+ the relocated Dwarf.
+
+2015-12-02 Mark Wielaard <mjw(a)redhat.com>
+
* nm.c (get_local_names): Check for duplicates in local_root tree.
2015-12-02 Mark Wielaard <mjw(a)redhat.com>
diff --git a/src/nm.c b/src/nm.c
index 69623fe..2911afa 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -45,6 +45,7 @@
#include <system.h>
#include "../libebl/libeblP.h"
+#include "../libdwfl/libdwflP.h"
/* Name and version of program. */
@@ -131,7 +132,7 @@ static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
const char *suffix);
/* Handle ELF file. */
-static int handle_elf (Elf *elf, const char *prefix, const char *fname,
+static int handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
const char *suffix);
@@ -384,7 +385,7 @@ process_file (const char *fname, bool more_than_one)
{
if (elf_kind (elf) == ELF_K_ELF)
{
- int result = handle_elf (elf, more_than_one ? "" : NULL,
+ int result = handle_elf (fd, elf, more_than_one ? "" : NULL,
fname, NULL);
if (elf_end (elf) != 0)
@@ -493,7 +494,7 @@ handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
&& strcmp (arhdr->ar_name, "/SYM64/") != 0)
{
if (elf_kind (subelf) == ELF_K_ELF)
- result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
+ result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name,
new_suffix);
else if (elf_kind (subelf) == ELF_K_AR)
result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
@@ -1153,8 +1154,63 @@ sort_by_name (const void *p1, const void *p2)
return reverse_sort ? -result : result;
}
+/* Stub libdwfl callback, only the ELF handle already open is ever
+ used. Only used for finding the alternate debug file if the Dwarf
+ comes from the main file. We are not interested in separate
+ debuginfo. */
+static int
+find_no_debuginfo (Dwfl_Module *mod,
+ void **userdata,
+ const char *modname,
+ Dwarf_Addr base,
+ const char *file_name,
+ const char *debuglink_file,
+ GElf_Word debuglink_crc,
+ char **debuginfo_file_name)
+{
+ Dwarf_Addr dwbias;
+ dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
+
+ /* We are only interested if the Dwarf has been setup on the main
+ elf file but is only missing the alternate debug link. If dwbias
+ hasn't even been setup, this is searching for separate debuginfo
+ for the main elf. We don't care in that case. */
+ if (dwbias == (Dwarf_Addr) -1)
+ return -1;
+
+ return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
+ file_name, debuglink_file,
+ debuglink_crc, debuginfo_file_name);
+}
+
+/* Get the Dwarf for the module/file we want. */
+struct getdbg
+{
+ const char *name;
+ Dwarf **dbg;
+};
+
+static int
+getdbg_dwflmod (Dwfl_Module *dwflmod,
+ void **userdata __attribute__ ((unused)),
+ const char *name,
+ Dwarf_Addr base __attribute__ ((unused)),
+ void *arg)
+{
+ struct getdbg *get = (struct getdbg *) arg;
+ if (get != NULL && get->name != NULL && strcmp (get->name, name) == 0)
+ {
+ Dwarf_Addr bias;
+ *get->dbg = dwfl_module_getdwarf (dwflmod, &bias);
+ return DWARF_CB_ABORT;
+ }
+
+ return DWARF_CB_OK;
+}
+
static void
-show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
+show_symbols (int fd, Ebl *ebl, GElf_Ehdr *ehdr,
+ Elf_Scn *scn, Elf_Scn *xndxscn,
GElf_Shdr *shdr, const char *prefix, const char *fname,
const char *fullname)
{
@@ -1194,9 +1250,48 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
/* Get a DWARF debugging descriptor. It's no problem if this isn't
possible. We just won't print any line number information. */
Dwarf *dbg = NULL;
+ Dwfl *dwfl = NULL;
if (format == format_sysv)
{
- dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
+ if (ehdr->e_type != ET_REL)
+ dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
+ else
+ {
+ /* Abuse libdwfl to do the relocations for us. This is just
+ for the ET_REL file containing Dwarf, so no need for
+ fancy lookups. */
+
+ /* Duplicate an fd for dwfl_report_offline to swallow. */
+ int dwfl_fd = dup (fd);
+ if (likely (dwfl_fd >= 0))
+ {
+ static const Dwfl_Callbacks callbacks =
+ {
+ .section_address = dwfl_offline_section_address,
+ .find_debuginfo = find_no_debuginfo
+ };
+ dwfl = dwfl_begin (&callbacks);
+ if (likely (dwfl != NULL))
+ {
+ /* Let 0 be the logical address of the file (or
+ first in archive). */
+ dwfl->offline_next_address = 0;
+ if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd)
+ == NULL)
+ {
+ /* Consumed on success, not on failure. */
+ close (dwfl_fd);
+ }
+ else
+ {
+ dwfl_report_end (dwfl, NULL, NULL);
+
+ struct getdbg get = { .name = fname, .dbg = &dbg };
+ dwfl_getmodules (dwfl, &getdbg_dwflmod, &get, 0);
+ }
+ }
+ }
+ }
if (dbg != NULL)
{
(void) dwarf_getpubnames (dbg, get_global, NULL, 0);
@@ -1401,13 +1496,16 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
tdestroy (local_root, free);
local_root = NULL;
- (void) dwarf_end (dbg);
+ if (dwfl == NULL)
+ (void) dwarf_end (dbg);
}
+ if (dwfl != NULL)
+ dwfl_end (dwfl);
}
static int
-handle_elf (Elf *elf, const char *prefix, const char *fname,
+handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
const char *suffix)
{
size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
@@ -1486,7 +1584,7 @@ handle_elf (Elf *elf, const char *prefix, const char *fname,
}
}
- show_symbols (ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
+ show_symbols (fd, ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
fullname);
}
}
--
2.5.0
8 years, 3 months
[PATCH] nm: Don't leak duplicate Dwarf local names.
by Mark Wielaard
Badly formed DWARF can have duplicate local names. In which case we do
want to detect those so we don't leak the memory.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 4 ++++
src/nm.c | 15 ++++++++++-----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index be7768f..ffc1b29 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,9 @@
2015-12-02 Mark Wielaard <mjw(a)redhat.com>
+ * nm.c (get_local_names): Check for duplicates in local_root tree.
+
+2015-12-02 Mark Wielaard <mjw(a)redhat.com>
+
* unstrip.c (struct data_list): New.
(new_data_list): Likewise.
(record_new_data): Likewise.
diff --git a/src/nm.c b/src/nm.c
index 15d9da4..69623fe 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -708,11 +708,16 @@ get_local_names (Dwarf *dbg)
newp->lowpc = lowpc;
newp->highpc = highpc;
- /* Since we cannot deallocate individual memory we do not test
- for duplicates in the tree. This should not happen anyway. */
- if (tsearch (newp, &local_root, local_compare) == NULL)
- error (EXIT_FAILURE, errno,
- gettext ("cannot create search tree"));
+ /* Check whether a similar local_name is already in the
+ cache. That should not happen. But if it does, we
+ don't want to leak memory. */
+ struct local_name **tres = tsearch (newp, &local_root,
+ local_compare);
+ if (tres == NULL)
+ error (EXIT_FAILURE, errno,
+ gettext ("cannot create search tree"));
+ else if (*tres != newp)
+ free (newp);
}
while (dwarf_siblingof (die, die) == 0);
}
--
2.5.0
8 years, 3 months
[PATCH] unstrip: Don't leak new section data.
by Mark Wielaard
When we copy elided sections some section data is newly allocated.
Track those allocations so we can free them when done.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 10 ++++++++++
src/unstrip.c | 39 +++++++++++++++++++++++++++++++++++++--
2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 27c638f..be7768f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
+2015-12-02 Mark Wielaard <mjw(a)redhat.com>
+
+ * unstrip.c (struct data_list): New.
+ (new_data_list): Likewise.
+ (record_new_data): Likewise.
+ (free_new_data): Likewise.
+ (adjust_relocs): Call record_new_data.
+ (add_new_section_symbols): Likewise.
+ (copy_elided_sections): Call free_new_data.
+
2015-12-01 Mark Wielaard <mjw(a)redhat.com>
* elfcmp.c (main): Close ebl1 and ebl2 backends.
diff --git a/src/unstrip.c b/src/unstrip.c
index bc8ed50..85e0a1d 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -311,6 +311,38 @@ make_directories (const char *path)
error (EXIT_FAILURE, errno, _("cannot create directory '%s'"), dir);
}
+/* Keep track of new section data we are creating, so we can free it
+ when done. */
+struct data_list
+{
+ void *data;
+ struct data_list *next;
+};
+
+struct data_list *new_data_list;
+
+static void
+record_new_data (void *data)
+{
+ struct data_list *next = new_data_list;
+ new_data_list = xmalloc (sizeof (struct data_list));
+ new_data_list->data = data;
+ new_data_list->next = next;
+}
+
+static void
+free_new_data (void)
+{
+ struct data_list *list = new_data_list;
+ while (list != NULL)
+ {
+ struct data_list *next = list->next;
+ free (list->data);
+ free (list);
+ list = next;
+ }
+ new_data_list = NULL;
+}
/* The binutils linker leaves gratuitous section symbols in .symtab
that strip has to remove. Older linkers likewise include a
@@ -472,6 +504,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
if (old_chain[i] != STN_UNDEF) \
new_chain[map[i - 1]] = map[old_chain[i] - 1]; \
\
+ record_new_data (new_hash); \
data->d_buf = new_hash; \
data->d_size = nent * sizeof new_hash[0]; \
}
@@ -514,6 +547,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
ELF_CHECK (v != NULL, _("cannot get symbol version: %s"));
}
+ record_new_data (versym);
data->d_buf = versym;
data->d_size = nent * shdr->sh_entsize;
elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
@@ -571,6 +605,7 @@ add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum,
symdata->d_size = shdr->sh_size;
symdata->d_buf = xmalloc (symdata->d_size);
+ record_new_data (symdata->d_buf);
/* Copy the existing section symbols. */
Elf_Data *old_symdata = elf_getdata (old_symscn, NULL);
@@ -1762,6 +1797,7 @@ more sections in stripped file than debug file -- arguments reversed?"));
shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize;
symdata->d_buf = xmalloc (symdata->d_size);
+ record_new_data (symdata->d_buf);
GElf_Sym sym;
memset (&sym, 0, sizeof sym);
@@ -1927,13 +1963,12 @@ more sections in stripped file than debug file -- arguments reversed?"));
free (strtab_data->d_buf);
}
- if (symdata != NULL)
- free (symdata->d_buf);
if (symstrtab != NULL)
{
ebl_strtabfree (symstrtab);
free (symstrdata->d_buf);
}
+ free_new_data ();
}
/* Process one pair of files, already opened. */
--
2.5.0
8 years, 3 months
[PATCH] libdwfl: Fix memory leak in link_map.c dwfl_link_map_report.
by Mark Wielaard
The phdrs buffer could come from the core file or through the executable.
dwfl_link_map_report would leak the buffer if it came from the executable.
Track where the buffer came from and free appropriately.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/link_map.c | 9 +++++++--
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 9640b4f..30a5205 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,10 @@
2015-12-01 Mark Wielaard <mjw(a)redhat.com>
+ * link_map.c (dwfl_link_map_report): Track whether in.d_buf comes
+ from exec or memory_callback, free as appropriate.
+
+2015-12-01 Mark Wielaard <mjw(a)redhat.com>
+
* libdwflP.h (struct Dwfl_User_Core): New.
(struct DWfl): Replace executable_for_core with user_core.
* argp-std.c (parse_opt): Store core and fd in Dwfl user_core.
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index e73b219..2bc0400 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -791,6 +791,7 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
&in.d_size, phdr, phnum * phent,
memory_callback_arg);
+ bool in_from_exec = false;
if (! in_ok
&& dwfl->user_core != NULL
&& dwfl->user_core->executable_for_core != NULL)
@@ -855,6 +856,7 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
return false;
}
in_ok = true;
+ in_from_exec = true;
}
if (in_ok)
{
@@ -903,8 +905,11 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
}
}
- (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
- memory_callback_arg);
+ if (in_from_exec)
+ free (in.d_buf);
+ else
+ (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
+ memory_callback_arg);
free (buf);
}
else
--
2.5.0
8 years, 3 months
[PATCH] libdwfl: Don't leak core Elf and core file descriptor from argp-std.
by Mark Wielaard
Our argp helper would leak the core Elf and core file descriptor when
given by the user. Store both in the Dwfl as a new Dwfl_User_Core so
they get cleaned up by dwfl_end.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 14 ++++++++++++++
libdwfl/argp-std.c | 16 ++++++++++++++--
libdwfl/core-file.c | 22 ++++++++++++++++++----
libdwfl/dwfl_build_id_find_elf.c | 9 ++++++---
libdwfl/dwfl_end.c | 12 ++++++++++--
libdwfl/libdwflP.h | 14 ++++++++++++--
libdwfl/link_map.c | 12 ++++++++----
7 files changed, 82 insertions(+), 17 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 3c48b5e..9640b4f 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,17 @@
+2015-12-01 Mark Wielaard <mjw(a)redhat.com>
+
+ * libdwflP.h (struct Dwfl_User_Core): New.
+ (struct DWfl): Replace executable_for_core with user_core.
+ * argp-std.c (parse_opt): Store core and fd in Dwfl user_core.
+ * core-file.c (dwfl_core_file_report): Check and store
+ executable_for_core in Dwfl user_core.
+ * dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Check and use
+ executable_for_core in Dwfl user_core.
+ * dwfl_end.c (dwfl_end): Release resources held in Dwfl user_core.
+ * link-map.c (report_r_debug): Check executable_for_core in Dwfl
+ user_core.
+ (dwfl_link_map_report): Likewise.
+
2015-11-19 Mark Wielaard <mjw(a)redhat.com>
* dwfl_module.c (__libdwfl_module_free): Remove Dwfl_Module Ebl from
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index 2bbf74f..501530a 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -1,5 +1,5 @@
/* Standard argp argument parsers for tools using libdwfl.
- Copyright (C) 2005-2010, 2012 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2012, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -303,7 +303,19 @@ parse_opt (int key, char *arg, struct argp_state *state)
/* Non-fatal to not be able to attach to core, ignore error. */
INTUSE(dwfl_core_file_attach) (dwfl, core);
- /* From now we leak FD and CORE. */
+ /* Store core Elf and fd in Dwfl to expose with dwfl_end. */
+ if (dwfl->user_core == NULL)
+ {
+ dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
+ if (dwfl->user_core == NULL)
+ {
+ argp_failure (state, EXIT_FAILURE, 0,
+ _("Not enough memory"));
+ return ENOMEM;
+ }
+ }
+ dwfl->user_core->core = core;
+ dwfl->user_core->fd = fd;
if (result == 0)
{
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index b317eca..6ba38f7 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -441,13 +441,27 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
return -1;
}
- free (dwfl->executable_for_core);
+ if (dwfl->user_core != NULL)
+ free (dwfl->user_core->executable_for_core);
if (executable == NULL)
- dwfl->executable_for_core = NULL;
+ {
+ if (dwfl->user_core != NULL)
+ dwfl->user_core->executable_for_core = NULL;
+ }
else
{
- dwfl->executable_for_core = strdup (executable);
- if (dwfl->executable_for_core == NULL)
+ if (dwfl->user_core == NULL)
+ {
+ dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
+ if (dwfl->user_core == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return -1;
+ }
+ dwfl->user_core->fd = -1;
+ }
+ dwfl->user_core->executable_for_core = strdup (executable);
+ if (dwfl->user_core->executable_for_core == NULL)
{
__libdwfl_seterrno (DWFL_E_NOMEM);
return -1;
diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c
index 2e30b7a..903e193 100644
--- a/libdwfl/dwfl_build_id_find_elf.c
+++ b/libdwfl/dwfl_build_id_find_elf.c
@@ -140,16 +140,19 @@ dwfl_build_id_find_elf (Dwfl_Module *mod,
char **file_name, Elf **elfp)
{
*elfp = NULL;
- if (mod->is_executable && mod->dwfl->executable_for_core != NULL)
+ if (mod->is_executable
+ && mod->dwfl->user_core != NULL
+ && mod->dwfl->user_core->executable_for_core != NULL)
{
/* When dwfl_core_file_report was called with a non-NULL executable file
name this callback will replace the Dwfl_Module main.name with the
recorded executable file when MOD was identified as main executable
(which then triggers opening and reporting of the executable). */
- int fd = open (mod->dwfl->executable_for_core, O_RDONLY);
+ const char *executable = mod->dwfl->user_core->executable_for_core;
+ int fd = open (executable, O_RDONLY);
if (fd >= 0)
{
- *file_name = strdup (mod->dwfl->executable_for_core);
+ *file_name = strdup (executable);
if (*file_name != NULL)
return fd;
else
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
index 33cae48..0b35bd2 100644
--- a/libdwfl/dwfl_end.c
+++ b/libdwfl/dwfl_end.c
@@ -1,5 +1,5 @@
/* Finish a session using libdwfl.
- Copyright (C) 2005, 2008, 2012-2013 Red Hat, Inc.
+ Copyright (C) 2005, 2008, 2012-2013, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
+#include <unistd.h>
void
dwfl_end (Dwfl *dwfl)
@@ -49,6 +50,13 @@ dwfl_end (Dwfl *dwfl)
__libdwfl_module_free (dead);
}
- free (dwfl->executable_for_core);
+ if (dwfl->user_core != NULL)
+ {
+ free (dwfl->user_core->executable_for_core);
+ elf_end (dwfl->user_core->core);
+ if (dwfl->user_core->fd != -1)
+ close (dwfl->user_core->fd);
+ free (dwfl->user_core);
+ }
free (dwfl);
}
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 63556d5..2a83646 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -1,5 +1,5 @@
/* Internal definitions for libdwfl.
- Copyright (C) 2005-2014 Red Hat, Inc.
+ Copyright (C) 2005-2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -104,6 +104,16 @@ typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
+/* Resources we might keep for the user about the core file that the
+ Dwfl might have been created from. Can currently only be set
+ through std-argp. */
+struct Dwfl_User_Core
+{
+ char *executable_for_core; /* --executable if --core was specified. */
+ Elf *core; /* non-NULL if we need to free it. */
+ int fd; /* close if >= 0. */
+};
+
struct Dwfl
{
const Dwfl_Callbacks *callbacks;
@@ -130,7 +140,7 @@ struct Dwfl
GElf_Off lookup_tail_offset;
int lookup_tail_ndx;
- char *executable_for_core; /* --executable if --core was specified. */
+ struct Dwfl_User_Core *user_core;
};
#define OFFLINE_REDZONE 0x10000
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 13cac52..e73b219 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -356,8 +356,10 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
if (name != NULL && name[0] == '\0')
name = NULL;
- if (iterations == 1 && dwfl->executable_for_core != NULL)
- name = dwfl->executable_for_core;
+ if (iterations == 1
+ && dwfl->user_core != NULL
+ && dwfl->user_core->executable_for_core != NULL)
+ name = dwfl->user_core->executable_for_core;
struct r_debug_info_module *r_debug_info_module = NULL;
if (r_debug_info != NULL)
@@ -789,7 +791,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
&in.d_size, phdr, phnum * phent,
memory_callback_arg);
- if (! in_ok && dwfl->executable_for_core != NULL)
+ if (! in_ok
+ && dwfl->user_core != NULL
+ && dwfl->user_core->executable_for_core != NULL)
{
/* AUXV -> PHDR -> DYNAMIC
Both AUXV and DYNAMIC should be always present in a core file.
@@ -797,7 +801,7 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the
core file. */
- int fd = open (dwfl->executable_for_core, O_RDONLY);
+ int fd = open (dwfl->user_core->executable_for_core, O_RDONLY);
Elf *elf;
Dwfl_Error error = DWFL_E_ERRNO;
if (fd != -1)
--
2.5.0
8 years, 3 months
[PATCH] tests: Fix some memory leaks in testcases.
by Mark Wielaard
Make sure all structures allocated in the testcases are disposed so
running them under valgrind will show no memory leaks.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 12 ++++++++++++
tests/addrcfi.c | 17 +++++++++++++----
tests/addrscopes.c | 1 +
tests/alldts.c | 3 +++
tests/allregs.c | 1 +
tests/dwarf-getstring.c | 1 +
tests/funcscopes.c | 1 +
tests/rerequest_tag.c | 1 +
tests/test-flag-nobits.c | 3 +++
9 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 69a25fc..4c56400 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,15 @@
+2015-12-01 Mark Wielaard <mjw(a)redhat.com>
+
+ * test-flag-nobits.c (main): Call elf_end.
+ * rerequest_tag.c (main): Call dwarf_end.
+ * funcscopes.c (handle_function): Free scopes.
+ * dwarf-getstring.c (main): Call dwarf_end.
+ * allregs.c (main): Free state.info.
+ * alldts.c (main): Free dyn.
+ * addrcfi.c (handle_address): Free stuff.frame between handle_cfi
+ calls.
+ * addrscopes.c (handle_address): Free scopes.
+
2015-10-16 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am [BUILD_STATIC] (libdw): Add -lz.
diff --git a/tests/addrcfi.c b/tests/addrcfi.c
index eb950c0..589b851 100644
--- a/tests/addrcfi.c
+++ b/tests/addrcfi.c
@@ -160,10 +160,19 @@ handle_address (GElf_Addr pc, Dwfl *dwfl)
Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc);
struct stuff stuff;
- return (handle_cfi (dwfl, ".eh_frame",
- dwfl_module_eh_cfi (mod, &stuff.bias), pc, &stuff)
- & handle_cfi (dwfl, ".debug_frame",
- dwfl_module_dwarf_cfi (mod, &stuff.bias), pc, &stuff));
+ stuff.frame = NULL;
+ stuff.bias = 0;
+ int res = handle_cfi (dwfl, ".eh_frame",
+ dwfl_module_eh_cfi (mod, &stuff.bias), pc, &stuff);
+ free (stuff.frame);
+
+ stuff.frame = NULL;
+ stuff.bias = 0;
+ res &= handle_cfi (dwfl, ".debug_frame",
+ dwfl_module_dwarf_cfi (mod, &stuff.bias), pc, &stuff);
+ free (stuff.frame);
+
+ return res;
}
int
diff --git a/tests/addrscopes.c b/tests/addrscopes.c
index 2285d2c..791569f 100644
--- a/tests/addrscopes.c
+++ b/tests/addrscopes.c
@@ -134,6 +134,7 @@ handle_address (GElf_Addr pc, Dwfl *dwfl)
print_vars (indent + INDENT, die);
}
+ free (scopes);
}
}
diff --git a/tests/alldts.c b/tests/alldts.c
index c39b8fb..eaecaf5 100644
--- a/tests/alldts.c
+++ b/tests/alldts.c
@@ -256,6 +256,9 @@ main (void)
/* And the data allocated in the .shstrtab section. */
free (data->d_buf);
+ /* And the dynamic entries. */
+ free (dyn);
+
/* All done. */
if (elf_end (elf) != 0)
{
diff --git a/tests/allregs.c b/tests/allregs.c
index 901d4e8..286f7e3 100644
--- a/tests/allregs.c
+++ b/tests/allregs.c
@@ -184,6 +184,7 @@ main (int argc, char **argv)
dwarf_encoding_string (state.info[i].type),
state.info[i].bits);
}
+ free (state.info);
}
else
do
diff --git a/tests/dwarf-getstring.c b/tests/dwarf-getstring.c
index 824edef..ffa3e37 100644
--- a/tests/dwarf-getstring.c
+++ b/tests/dwarf-getstring.c
@@ -70,6 +70,7 @@ main (int argc, char *argv[])
offset += len + 1;
}
+ dwarf_end (dbg);
close (fd);
}
diff --git a/tests/funcscopes.c b/tests/funcscopes.c
index 55cb4fa..9c90185 100644
--- a/tests/funcscopes.c
+++ b/tests/funcscopes.c
@@ -162,6 +162,7 @@ handle_function (Dwarf_Die *funcdie, void *arg)
print_vars (indent + INDENT, die);
}
+ free (scopes);
}
return 0;
diff --git a/tests/rerequest_tag.c b/tests/rerequest_tag.c
index d0bf5f2..b4d4627 100644
--- a/tests/rerequest_tag.c
+++ b/tests/rerequest_tag.c
@@ -42,5 +42,6 @@ main (int argc, char **argv)
assert (die == &die_mem);
assert (dwarf_tag (die) == 0);
+ dwarf_end (dw);
return 0;
}
diff --git a/tests/test-flag-nobits.c b/tests/test-flag-nobits.c
index ff19ce2..15d44ea 100644
--- a/tests/test-flag-nobits.c
+++ b/tests/test-flag-nobits.c
@@ -36,4 +36,7 @@ main (int argc, char **argv)
Elf_Scn *scn = NULL;
while ((scn = elf_nextscn (stripped, scn)) != NULL)
elf_flagdata (elf_getdata (scn, NULL), ELF_C_SET, ELF_F_DIRTY);
+
+ elf_end (stripped);
+ return 0;
}
--
2.5.0
8 years, 3 months
[PATCH] libdw: Don't leak fake_loc_cu.
by Mark Wielaard
The fake_loc_cu is used when synthesizing attributes for Dwarf_Ops that
came from a location list entry in dwarf_getlocation_attr. Make sure
we remove the loc cache stored in it when disposing of the fake_loc_cu.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 4d02449..81eeae6 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,7 @@
+2015-12-01 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwarf_end.c (dwarf_end): Call cu_free on fake_loc_cu if it exists.
+
2015-10-19 Mark Wielaard <mjw(a)redhat.com>
* frame-cache.c (__libdw_destroy_frame_cache): Call ebl_closebackend
--
2.5.0
8 years, 3 months
[PATCH] elfcmp: Fix leaking Ebl handles.
by Mark Wielaard
open_file () explicitly gets Ebl handles for both Elf files to compare.
Make sure to close those when done.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 4 ++++
src/elfcmp.c | 2 ++
2 files changed, 6 insertions(+)
diff --git a/src/ChangeLog b/src/ChangeLog
index d6d2936..27c638f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+2015-12-01 Mark Wielaard <mjw(a)redhat.com>
+
+ * elfcmp.c (main): Close ebl1 and ebl2 backends.
+
2015-10-16 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am [BUILD_STATIC](libdw): Add -lz.
diff --git a/src/elfcmp.c b/src/elfcmp.c
index 0250fbe..852b92f 100644
--- a/src/elfcmp.c
+++ b/src/elfcmp.c
@@ -655,6 +655,8 @@ cannot read note section [%zu] '%s' in '%s': %s"),
out:
elf_end (elf1);
elf_end (elf2);
+ ebl_closebackend (ebl1);
+ ebl_closebackend (ebl2);
close (fd1);
close (fd2);
--
2.5.0
8 years, 3 months