This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] Re: Multiple apparent leaks in dwarf2.c
- From: John Levon <levon at movementarian dot org>
- To: binutils at sources dot redhat dot com
- Cc: Philippe Elie <phil dot el at wanadoo dot fr>
- Date: Sat, 23 Apr 2005 21:59:50 +0100
- Subject: [PATCH] Re: Multiple apparent leaks in dwarf2.c
- References: <20050421060339.GA86259@compsoc.man.ac.uk>
On Thu, Apr 21, 2005 at 07:03:40AM +0100, John Levon wrote:
> These appear to indeed be valid leaks: the code is using the
> non-objalloc'd bfd_realloc/bfd_malloc routines, but there's nothing to
> clear up the debug info stash that I can see (binutils 2.15).
Here's a patch that fixes up the issues I found in dwarf2.c. With this
patch applied to CVS, our application is valgrind-clean.
thanks,
john
Index: binutils-cvs/bfd/dwarf2.c
===================================================================
RCS file: /cvs/src/src/bfd/dwarf2.c,v
retrieving revision 1.65
diff -u -a -p -r1.65 dwarf2.c
--- binutils-cvs/bfd/dwarf2.c 3 Apr 2005 20:36:37 -0000 1.65
+++ binutils-cvs/bfd/dwarf2.c 23 Apr 2005 20:45:22 -0000
@@ -447,11 +447,26 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
{
if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
{
+ struct attr_abbrev *tmp;
amt = cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK;
amt *= sizeof (struct attr_abbrev);
- cur_abbrev->attrs = bfd_realloc (cur_abbrev->attrs, amt);
- if (! cur_abbrev->attrs)
- return 0;
+ tmp = bfd_realloc (cur_abbrev->attrs, amt);
+ if (! tmp)
+ {
+ size_t i;
+
+ for (i = 0; i < ABBREV_HASH_SIZE; i++)
+ {
+ struct abbrev_info *abbrev = abbrevs[i];
+ while (abbrev)
+ {
+ free (abbrev->attrs);
+ abbrev = abbrev->next;
+ }
+ }
+ return 0;
+ }
+ cur_abbrev->attrs = tmp;
}
cur_abbrev->attrs[cur_abbrev->num_attrs].name
@@ -963,11 +978,16 @@ decode_line_info (struct comp_unit *unit
if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0)
{
+ char **tmp;
amt = table->num_dirs + DIR_ALLOC_CHUNK;
amt *= sizeof (char *);
- table->dirs = bfd_realloc (table->dirs, amt);
- if (! table->dirs)
- return 0;
+ tmp = bfd_realloc (table->dirs, amt);
+ if (! tmp)
+ {
+ free (table->dirs);
+ return 0;
+ }
+ table->dirs = tmp;
}
table->dirs[table->num_dirs++] = cur_dir;
@@ -982,11 +1002,17 @@ decode_line_info (struct comp_unit *unit
if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
{
+ struct fileinfo *tmp;
amt = table->num_files + FILE_ALLOC_CHUNK;
amt *= sizeof (struct fileinfo);
- table->files = bfd_realloc (table->files, amt);
- if (! table->files)
- return 0;
+ tmp = bfd_realloc (table->files, amt);
+ if (! tmp)
+ {
+ free (table->files);
+ free (table->dirs);
+ return 0;
+ }
+ table->files = tmp;
}
table->files[table->num_files].name = cur_file;
@@ -1073,11 +1099,18 @@ decode_line_info (struct comp_unit *unit
line_ptr += bytes_read;
if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
{
+ struct fileinfo *tmp;
amt = table->num_files + FILE_ALLOC_CHUNK;
amt *= sizeof (struct fileinfo);
- table->files = bfd_realloc (table->files, amt);
- if (! table->files)
- return 0;
+ tmp = bfd_realloc (table->files, amt);
+ if (! tmp)
+ {
+ free (table->files);
+ free (table->dirs);
+ free (filename);
+ return 0;
+ }
+ table->files = tmp;
}
table->files[table->num_files].name = cur_file;
table->files[table->num_files].dir =
@@ -1094,6 +1127,9 @@ decode_line_info (struct comp_unit *unit
default:
(*_bfd_error_handler) (_("Dwarf Error: mangled line number section."));
bfd_set_error (bfd_error_bad_value);
+ free (filename);
+ free (table->files);
+ free (table->dirs);
return 0;
}
break;
@@ -2003,3 +2039,39 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
return FALSE;
}
+
+void
+_bfd_dwarf2_cleanup_debug_info(bfd *abfd)
+{
+ struct comp_unit *each;
+ struct dwarf2_debug *stash = elf_tdata (abfd)->dwarf2_find_line_info;
+
+ if (! stash)
+ return;
+
+ for (each = stash->all_comp_units; each; each = each->next_unit)
+ {
+ struct abbrev_info **abbrevs = each->abbrevs;
+ size_t i;
+
+ for (i = 0; i < ABBREV_HASH_SIZE; i++)
+ {
+ struct abbrev_info *abbrev = abbrevs[i];
+ while (abbrev)
+ {
+ free (abbrev->attrs);
+ abbrev = abbrev->next;
+ }
+ }
+
+ if (each->line_table)
+ {
+ free (each->line_table->dirs);
+ free (each->line_table->files);
+ }
+ }
+
+ free (stash->dwarf_abbrev_buffer);
+ free (stash->dwarf_line_buffer);
+ free (stash->dwarf_ranges_buffer);
+}
Index: binutils-cvs/bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.179
diff -u -a -p -r1.179 elf-bfd.h
--- binutils-cvs/bfd/elf-bfd.h 4 Apr 2005 16:11:02 -0000 1.179
+++ binutils-cvs/bfd/elf-bfd.h 23 Apr 2005 20:45:25 -0000
@@ -1728,6 +1728,8 @@ extern int bfd_elf_link_record_local_dyn
extern bfd_boolean _bfd_elf_close_and_cleanup
(bfd *);
+extern void _bfd_dwarf2_cleanup_debug_info
+ (bfd *);
extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn
(bfd *, arelent *, struct bfd_symbol *, void *,
asection *, bfd *, char **);
Index: binutils-cvs/bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.280
diff -u -a -p -r1.280 elf.c
--- binutils-cvs/bfd/elf.c 21 Apr 2005 12:13:37 -0000 1.280
+++ binutils-cvs/bfd/elf.c 23 Apr 2005 20:45:36 -0000
@@ -6676,6 +6676,8 @@ _bfd_elf_close_and_cleanup (bfd *abfd)
_bfd_elf_strtab_free (elf_shstrtab (abfd));
}
+ _bfd_dwarf2_cleanup_debug_info (abfd);
+
return _bfd_generic_close_and_cleanup (abfd);
}