* dwarf2.c (read_abbrevs): If bfd_realloc fails, free currently allocated memory
authorNick Clifton <nickc@redhat.com>
Thu, 5 May 2005 14:25:23 +0000 (14:25 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 5 May 2005 14:25:23 +0000 (14:25 +0000)
  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.

bfd/ChangeLog
bfd/dwarf2.c
bfd/elf-bfd.h
bfd/elf.c

index 87ec00da0af02292d24bca24b0f498fcc2bb11b8..4faeff8f564e82f79d15e602a8788d9a963c0a56 100644 (file)
@@ -1,3 +1,14 @@
+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.
+
 2005-05-05  Hans-Peter Nilsson  <hp@axis.com>
 
        * Makefile.am (INCLUDES): Don't -D_GNU_SOURCE here.
index 8b630845aa2958deed083298ded3cffe09af29c9..365758a2c498ca8848364f29f2a5c121ba4cbd4f 100644 (file)
@@ -447,11 +447,28 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
        {
          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 == NULL)
+               {
+                 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 NULL;
+               }
+             cur_abbrev->attrs = tmp;
            }
 
          cur_abbrev->attrs[cur_abbrev->num_attrs].name
@@ -963,11 +980,18 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 
       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 == NULL)
+           {
+             free (table->dirs);
+             return NULL;
+           }
+         table->dirs = tmp;
        }
 
       table->dirs[table->num_dirs++] = cur_dir;
@@ -982,11 +1006,19 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 
       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 == NULL)
+           {
+             free (table->files);
+             free (table->dirs);
+             return NULL;
+           }
+         table->files = tmp;
        }
 
       table->files[table->num_files].name = cur_file;
@@ -1073,11 +1105,19 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                  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 == NULL)
+                       {
+                         free (table->files);
+                         free (table->dirs);
+                         free (filename);
+                         return NULL;
+                       }
+                     table->files = tmp;
                    }
                  table->files[table->num_files].name = cur_file;
                  table->files[table->num_files].dir =
@@ -1094,7 +1134,10 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                default:
                  (*_bfd_error_handler) (_("Dwarf Error: mangled line number section."));
                  bfd_set_error (bfd_error_bad_value);
-                 return 0;
+                 free (filename);
+                 free (table->files);
+                 free (table->dirs);
+                 return NULL;
                }
              break;
            case DW_LNS_copy:
@@ -2003,3 +2046,45 @@ _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;
+
+  if (abfd == NULL || elf_tdata (abfd) == NULL)
+    return;
+
+  stash = elf_tdata (abfd)->dwarf2_find_line_info;
+
+  if (stash == NULL)
+    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 d5814c10cecb819aa9de9d5735168fe9e62cae7e..603395166fffecf4de59f0dd5e3bbb817125401c 100644 (file)
@@ -1728,6 +1728,10 @@ extern int bfd_elf_link_record_local_dynamic_symbol
 
 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 c2e84387bd6c41410b9f707ae2082f543f5c6790..5477ba633a1f0b9f6b697260ec4962839ec35e0f 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6684,6 +6684,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);
 }