public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Multiple apparent leaks in dwarf2.c
@ 2005-04-21  6:03 John Levon
  2005-04-23 21:00 ` [PATCH] " John Levon
  0 siblings, 1 reply; 3+ messages in thread
From: John Levon @ 2005-04-21  6:03 UTC (permalink / raw)
  To: binutils; +Cc: Philippe Elie


With the following:

#include <bfd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
        bfd * b;
        long f;
        void *syms;
        size_t size;
        asymbol **as;
        const char *file;
        const char *func;
        int line;

        if (argc < 2) {
                printf("usage: valbfd <file>\n");
                exit(1);
        }

        if (!(b = bfd_openr(argv[1], NULL))) {
                printf("failed to open %s.\n", argv[1]);
                exit(1);
        }

        if (!bfd_check_format_matches(b, bfd_object, NULL)) {
                printf("no match.\n");
                exit(1);
        }

        if (!(bfd_get_file_flags(b) & HAS_SYMS)) {
                printf("no syms.\n");
                exit(1);
        }

        size = bfd_get_symtab_upper_bound(b);
        syms = malloc(size);
        as = syms;
        bfd_canonicalize_symtab(b, syms);
        bfd_find_nearest_line(b, (*as)->section, as, 4000000, &file, &func, &line);
        bfd_close(b);
        free(syms);
}

valgrind tells us:

==15031== 18577 bytes in 1 blocks are definitely lost in loss record 1 of 4
==15031==    at 0x1B903534: malloc (vg_replace_malloc.c:130)
==15031==    by 0x8049790: bfd_malloc (libbfd.c:152)
==15031==    by 0x808CE7E: bfd_simple_get_relocated_section_contents (simple.c:150)
==15031==    by 0x808B75F: read_abbrevs (dwarf2.c:447)
==15031==    by 0x808C77A: parse_comp_unit (dwarf2.c:1483)
==15031==    by 0x808CB76: _bfd_dwarf2_find_nearest_line (dwarf2.c:1832)
==15031==    by 0x805D324: _bfd_elf_find_nearest_line (elf.c:6111)
==15031==    by 0x8049281: main (valbfd.c:40)
==15031==
==15031==
==15031== 43184 bytes in 619 blocks are definitely lost in loss record 2 of 4
==15031==    at 0x1B903F5A: realloc (vg_replace_malloc.c:196)
==15031==    by 0x80497D0: bfd_realloc (libbfd.c:175)
==15031==    by 0x808B679: read_abbrevs (dwarf2.c:495)
==15031==    by 0x808C77A: parse_comp_unit (dwarf2.c:1483)
==15031==    by 0x808CB76: _bfd_dwarf2_find_nearest_line (dwarf2.c:1832)
==15031==    by 0x805D324: _bfd_elf_find_nearest_line (elf.c:6111)
==15031==    by 0x8049281: main (valbfd.c:40)
==15031==
==15031==
==15031== 48831 (23816 direct, 25015 indirect) bytes in 742 blocks are definitely lost in loss record 3 of 4
==15031==    at 0x1B903534: malloc (vg_replace_malloc.c:130)
==15031==    by 0x8049800: bfd_realloc (libbfd.c:173)
==15031==    by 0x808B679: read_abbrevs (dwarf2.c:495)
==15031==    by 0x808C77A: parse_comp_unit (dwarf2.c:1483)
==15031==    by 0x808CB76: _bfd_dwarf2_find_nearest_line (dwarf2.c:1832)
==15031==    by 0x805D324: _bfd_elf_find_nearest_line (elf.c:6111)
==15031==    by 0x8049281: main (valbfd.c:40)

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).

Using an earlier binutils, there was also leaks in decode_line_info()
centering around concat_filename(). These appear to have been mostly
fixed, though code inspection shows some obvious error path leaks:

   1058       char * filename = table->num_files ? concat_filename (table, 1) : NULL;
...
   1142                   bfd_set_error (bfd_error_bad_value);
   1143                   return 0;
...
   1125                       if (! table->files)
   1126                         return 0;
...
   1208       if (filename)
   1209         free (filename);

It's the other ones that are the big concern though: this is leaking 4Mb with
our application. Any chance of these getting fixed? I couldn't see a
particular reason that bfd_simple_get_relocated_section_contents()
wasn't allocating from abfd->memory, but I don't know what's best for
the realloc ones. Do we need some gunk in _bfd_elf_close_and_cleanup() ?

(I haven't looked hard at the source, so it's possible I've got things
wrong).

cheers,
john

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] Re: Multiple apparent leaks in dwarf2.c
  2005-04-21  6:03 Multiple apparent leaks in dwarf2.c John Levon
@ 2005-04-23 21:00 ` John Levon
  2005-05-05 14:34   ` Nick Clifton
  0 siblings, 1 reply; 3+ messages in thread
From: John Levon @ 2005-04-23 21:00 UTC (permalink / raw)
  To: binutils; +Cc: Philippe Elie

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);
 }
 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Re: Multiple apparent leaks in dwarf2.c
  2005-04-23 21:00 ` [PATCH] " John Levon
@ 2005-05-05 14:34   ` Nick Clifton
  0 siblings, 0 replies; 3+ messages in thread
From: Nick Clifton @ 2005-05-05 14:34 UTC (permalink / raw)
  To: John Levon; +Cc: binutils, Philippe Elie

Hi John,

> 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 very much for submitting this.  I have applied your patch 
together with this ChangeLog entry:

bfd/ChangeLog
2005-05-05  John Levon  <levon@movementarian.org>

	* dwarf2.c (read_abbrevs): If bfd_realloc fails, free currently
	allocated memory before returning.
	(decode_line_info): Likewise.
	(_bfd_dwarf2_cleanup_debug_info): New function:  Frees memory
	allocated by functions in this file.
	* elf-bfd.h (_bfd_dwarf2_cleanup_debug_info): Prototype.
	* elf.c (bfd_elf_close_and_cleanup): Call
	_bfd_dwarf2_cleanup_debug_info.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2005-05-05 14:24 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-04-21  6:03 Multiple apparent leaks in dwarf2.c John Levon
2005-04-23 21:00 ` [PATCH] " John Levon
2005-05-05 14:34   ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).