]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Free linker hash table from bfd_close.
authorAlan Modra <amodra@gmail.com>
Fri, 13 Jun 2014 09:41:39 +0000 (19:11 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 13 Jun 2014 09:41:39 +0000 (19:11 +0930)
Also tidies numerous error exit paths in various link_hash_table_create
functions that failed to free memory.

include/
* bfdlink.h (struct bfd_link_hash_table): Add hash_table_free field.
bfd/
* archive.c: Include bfdlink.h.
(_bfd_archive_close_and_cleanup): Call linker hash_table_free.
* bfd.c (struct bfd): Add is_linker_output field.
* elf-bfd.h (_bfd_elf_link_hash_table_free): Update prototype.
* linker.c (_bfd_link_hash_table_init): Set up hash_table_free,
link.hash and is_linker_output.
(_bfd_generic_link_hash_table_free): Replace bfd_link_hash_table*
param with bfd*.  Assert is_linker_output and link.hash, and
clear them before exit.
* elf-m10300.c (elf32_mn10300_link_hash_table_free): Replace
bfd_link_hash_table* param with bfd*.  Hack is_linker_output
and link.hash so we can free two linker hash tables.
(elf32_mn10300_link_hash_table_create): Create static_hash_table
first.  Clean up on errors.  Set hash_table_free pointer.
* elf32-arm.c (elf32_arm_link_hash_table_free): Replace
bfd_link_hash_table* param with bfd*.
(elf32_arm_link_hash_table_create): Clean up on errors.  Set
hash_table_free pointer.
* elf32-avr.c, * elf32-hppa.c, * elf32-i386.c, * elf32-m68hc1x.c,
* elf32-m68k.c, * elf32-metag.c, * elf32-nios2.c, * elf32-xgate.c,
* elf64-ia64-vms.c, * elf64-ppc.c, * elf64-x86-64.c, * elflink.c,
* elfnn-aarch64.c, * elfnn-ia64.c, * elfxx-sparc.c,
* xcofflink.c: Similarly.
* simple.c (bfd_simple_get_relocated_section_contents): Save and
clear link.next before creating linker hash table.  Clean up on
errors, and restore link.next on exit.
* elf32-m68hc1x.h (m68hc11_elf_bfd_link_hash_table_free): Delete.
* elf32-xgate.h (xgate_elf_bfd_link_hash_table_free): Delete.
* elfxx-sparc.h (_bfd_sparc_elf_link_hash_table_free): Delete.
* libcoff-in.h (_bfd_xcoff_bfd_link_hash_table_free): Delete.
* hash.c (bfd_hash_table_init_n): Free table on error.
* libbfd-in.h (_bfd_generic_link_hash_table_free): Update proto.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* libcoff.h: Regenerate.

35 files changed:
bfd/ChangeLog
bfd/archive.c
bfd/bfd-in2.h
bfd/bfd.c
bfd/elf-bfd.h
bfd/elf-m10300.c
bfd/elf32-arm.c
bfd/elf32-avr.c
bfd/elf32-hppa.c
bfd/elf32-i386.c
bfd/elf32-m68hc1x.c
bfd/elf32-m68hc1x.h
bfd/elf32-m68k.c
bfd/elf32-metag.c
bfd/elf32-nios2.c
bfd/elf32-xgate.c
bfd/elf32-xgate.h
bfd/elf64-ia64-vms.c
bfd/elf64-ppc.c
bfd/elf64-x86-64.c
bfd/elflink.c
bfd/elfnn-aarch64.c
bfd/elfnn-ia64.c
bfd/elfxx-sparc.c
bfd/elfxx-sparc.h
bfd/hash.c
bfd/libbfd-in.h
bfd/libbfd.h
bfd/libcoff-in.h
bfd/libcoff.h
bfd/linker.c
bfd/simple.c
bfd/xcofflink.c
include/ChangeLog
include/bfdlink.h

index 4cb3d06b9d6238355f167f6b911394337accb133..0caff71a83c490280a2c9d6d04ef149a17b4d8f5 100644 (file)
@@ -1,3 +1,41 @@
+2014-06-13  Alan Modra  <amodra@gmail.com>
+
+       * archive.c: Include bfdlink.h.
+       (_bfd_archive_close_and_cleanup): Call linker hash_table_free.
+       * bfd.c (struct bfd): Add is_linker_output field.
+       * elf-bfd.h (_bfd_elf_link_hash_table_free): Update prototype.
+       * linker.c (_bfd_link_hash_table_init): Set up hash_table_free,
+       link.hash and is_linker_output.
+       (_bfd_generic_link_hash_table_free): Replace bfd_link_hash_table*
+       param with bfd*.  Assert is_linker_output and link.hash, and
+       clear them before exit.
+       * elf-m10300.c (elf32_mn10300_link_hash_table_free): Replace
+       bfd_link_hash_table* param with bfd*.  Hack is_linker_output
+       and link.hash so we can free two linker hash tables.
+       (elf32_mn10300_link_hash_table_create): Create static_hash_table
+       first.  Clean up on errors.  Set hash_table_free pointer.
+       * elf32-arm.c (elf32_arm_link_hash_table_free): Replace
+       bfd_link_hash_table* param with bfd*.
+       (elf32_arm_link_hash_table_create): Clean up on errors.  Set
+       hash_table_free pointer.
+       * elf32-avr.c, * elf32-hppa.c, * elf32-i386.c, * elf32-m68hc1x.c,
+       * elf32-m68k.c, * elf32-metag.c, * elf32-nios2.c, * elf32-xgate.c,
+       * elf64-ia64-vms.c, * elf64-ppc.c, * elf64-x86-64.c, * elflink.c,
+       * elfnn-aarch64.c, * elfnn-ia64.c, * elfxx-sparc.c,
+       * xcofflink.c: Similarly.
+       * simple.c (bfd_simple_get_relocated_section_contents): Save and
+       clear link.next before creating linker hash table.  Clean up on
+       errors, and restore link.next on exit.
+       * elf32-m68hc1x.h (m68hc11_elf_bfd_link_hash_table_free): Delete.
+       * elf32-xgate.h (xgate_elf_bfd_link_hash_table_free): Delete.
+       * elfxx-sparc.h (_bfd_sparc_elf_link_hash_table_free): Delete.
+       * libcoff-in.h (_bfd_xcoff_bfd_link_hash_table_free): Delete.
+       * hash.c (bfd_hash_table_init_n): Free table on error.
+       * libbfd-in.h (_bfd_generic_link_hash_table_free): Update proto.
+       * bfd-in2.h: Regenerate.
+       * libbfd.h: Regenerate.
+       * libcoff.h: Regenerate.
+
 2014-06-13  Alan Modra  <amodra@gmail.com>
 
        PR 17047
index 157a3f7c4d41e6727f4d7a5adafc343995ac6c8f..1c3ad5240ff11af810086ce494cf2854d5240788 100644 (file)
@@ -140,6 +140,7 @@ SUBSECTION
 #include "safe-ctype.h"
 #include "hashtab.h"
 #include "filenames.h"
+#include "bfdlink.h"
 
 #ifndef errno
 extern int errno;
@@ -2751,5 +2752,8 @@ _bfd_archive_close_and_cleanup (bfd *abfd)
            }
        }
     }
+  if (abfd->is_linker_output)
+    (*abfd->link.hash->hash_table_free) (abfd);
+
   return TRUE;
 }
index 07d94dfce2a6e30c06ecb181e8321e9e2a71a1d8..d9056ce33ff584a7b3c578afe5ac00e610437307 100644 (file)
@@ -6488,6 +6488,9 @@ struct bfd
   /* Set if only required symbols should be added in the link hash table for
      this object.  Used by VMS linkers.  */
   unsigned int selective_search : 1;
+
+  /* Set if this is the linker output BFD.  */
+  unsigned int is_linker_output : 1;
 };
 
 /* See note beside bfd_set_section_userdata.  */
index 2406319db573ffb8f01df9d0679ab0143cb34a22..e19bcf77afe13d203c0f99e97ba628ae47b567e6 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -313,6 +313,9 @@ CODE_FRAGMENT
 .  {* Set if only required symbols should be added in the link hash table for
 .     this object.  Used by VMS linkers.  *}
 .  unsigned int selective_search : 1;
+.
+.  {* Set if this is the linker output BFD.  *}
+.  unsigned int is_linker_output : 1;
 .};
 .
 .{* See note beside bfd_set_section_userdata.  *}
index 1bbe771cfc5aa7df895f49d20ea6dbf5df5bc0a5..a06c54bda52edb3408ebc393dced38c350c0d2c9 100644 (file)
@@ -1816,7 +1816,7 @@ extern struct bfd_hash_entry *_bfd_elf_link_hash_newfunc
 extern struct bfd_link_hash_table *_bfd_elf_link_hash_table_create
   (bfd *);
 extern void _bfd_elf_link_hash_table_free
-  (struct bfd_link_hash_table *);
+  (bfd *);
 extern void _bfd_elf_link_hash_copy_indirect
   (struct bfd_link_info *, struct elf_link_hash_entry *,
    struct elf_link_hash_entry *);
index 4cc879ec32ac405cd1d7a2a58e2d481c7dc7d4a3..f29025d5d92a0c9e6e3828c7816e38bd0844263c 100644 (file)
@@ -4601,15 +4601,16 @@ _bfd_mn10300_copy_indirect_symbol (struct bfd_link_info *        info,
 /* Destroy an mn10300 ELF linker hash table.  */
 
 static void
-elf32_mn10300_link_hash_table_free (struct bfd_link_hash_table *hash)
+elf32_mn10300_link_hash_table_free (bfd *obfd)
 {
   struct elf32_mn10300_link_hash_table *ret
-    = (struct elf32_mn10300_link_hash_table *) hash;
+    = (struct elf32_mn10300_link_hash_table *) obfd->link.hash;
 
-  _bfd_elf_link_hash_table_free
-    ((struct bfd_link_hash_table *) ret->static_hash_table);
-  _bfd_elf_link_hash_table_free
-    ((struct bfd_link_hash_table *) ret);
+  obfd->link.hash = &ret->static_hash_table->root.root;
+  _bfd_elf_link_hash_table_free (obfd);
+  obfd->is_linker_output = TRUE;
+  obfd->link.hash = &ret->root.root;
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create an mn10300 ELF linker hash table.  */
@@ -4624,17 +4625,6 @@ elf32_mn10300_link_hash_table_create (bfd *abfd)
   if (ret == NULL)
     return NULL;
 
-  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
-                                     elf32_mn10300_link_hash_newfunc,
-                                     sizeof (struct elf32_mn10300_link_hash_entry),
-                                     MN10300_ELF_DATA))
-    {
-      free (ret);
-      return NULL;
-    }
-
-  ret->tls_ldm_got.offset = -1;
-
   amt = sizeof (struct elf_link_hash_table);
   ret->static_hash_table = bfd_zmalloc (amt);
   if (ret->static_hash_table == NULL)
@@ -4652,7 +4642,24 @@ elf32_mn10300_link_hash_table_create (bfd *abfd)
       free (ret);
       return NULL;
     }
-  (void) elf32_mn10300_link_hash_table_free;
+
+  abfd->is_linker_output = FALSE;
+  abfd->link.hash = NULL;
+  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+                                     elf32_mn10300_link_hash_newfunc,
+                                     sizeof (struct elf32_mn10300_link_hash_entry),
+                                     MN10300_ELF_DATA))
+    {
+      abfd->is_linker_output = TRUE;
+      abfd->link.hash = &ret->static_hash_table->root.root;
+      _bfd_elf_link_hash_table_free (abfd);
+      free (ret);
+      return NULL;
+    }
+  ret->root.root.hash_table_free = elf32_mn10300_link_hash_table_free;
+
+  ret->tls_ldm_got.offset = -1;
+
   return & ret->root.root;
 }
 
index 6358b580ba5a337101fccf692a6706bc30eb4d42..ef8bfa656140408ca8feaedc70fdd39e0f937084 100644 (file)
@@ -3526,13 +3526,13 @@ elf32_arm_copy_indirect_symbol (struct bfd_link_info *info,
 /* Destroy an ARM elf linker hash table.  */
 
 static void
-elf32_arm_link_hash_table_free (struct bfd_link_hash_table *hash)
+elf32_arm_link_hash_table_free (bfd *obfd)
 {
   struct elf32_arm_link_hash_table *ret
-    = (struct elf32_arm_link_hash_table *) hash;
+    = (struct elf32_arm_link_hash_table *) obfd->link.hash;
 
   bfd_hash_table_free (&ret->stub_hash_table);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create an ARM elf linker hash table.  */
@@ -3570,10 +3570,10 @@ elf32_arm_link_hash_table_create (bfd *abfd)
   if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc,
                            sizeof (struct elf32_arm_stub_hash_entry)))
     {
-      free (ret);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) elf32_arm_link_hash_table_free;
+  ret->root.root.hash_table_free = elf32_arm_link_hash_table_free;
 
   return &ret->root.root;
 }
index 55953841ce739495bdb95d92262a8b427923ab79..b46a44c6191d1c2c0bbb392ff6e4564da37edf42 100644 (file)
@@ -714,10 +714,10 @@ elf32_avr_link_hash_newfunc (struct bfd_hash_entry * entry,
 /* Free the derived linker hash table.  */
 
 static void
-elf32_avr_link_hash_table_free (struct bfd_link_hash_table *btab)
+elf32_avr_link_hash_table_free (bfd *obfd)
 {
   struct elf32_avr_link_hash_table *htab
-    = (struct elf32_avr_link_hash_table *) btab;
+    = (struct elf32_avr_link_hash_table *) obfd->link.hash;
 
   /* Free the address mapping table.  */
   if (htab->amt_stub_offsets != NULL)
@@ -726,7 +726,7 @@ elf32_avr_link_hash_table_free (struct bfd_link_hash_table *btab)
     free (htab->amt_destination_addr);
 
   bfd_hash_table_free (&htab->bstab);
-  _bfd_elf_link_hash_table_free (btab);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create the derived linker hash table.  The AVR ELF port uses the derived
@@ -755,8 +755,11 @@ elf32_avr_link_hash_table_create (bfd *abfd)
   /* Init the stub hash table too.  */
   if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc,
                             sizeof (struct elf32_avr_stub_hash_entry)))
-    return NULL;
-  (void) elf32_avr_link_hash_table_free;
+    {
+      _bfd_elf_link_hash_table_free (abfd);
+      return NULL;
+    }
+  htab->etab.root.hash_table_free = elf32_avr_link_hash_table_free;
 
   return &htab->etab.root;
 }
index 635ec42d94348cb10d4e981fdd9d30286eb83d48..0588ebbfcdf332c9de5b87beeaa6fae5f1adfbbd 100644 (file)
@@ -410,13 +410,13 @@ hppa_link_hash_newfunc (struct bfd_hash_entry *entry,
 /* Free the derived linker hash table.  */
 
 static void
-elf32_hppa_link_hash_table_free (struct bfd_link_hash_table *btab)
+elf32_hppa_link_hash_table_free (bfd *obfd)
 {
   struct elf32_hppa_link_hash_table *htab
-    = (struct elf32_hppa_link_hash_table *) btab;
+    = (struct elf32_hppa_link_hash_table *) obfd->link.hash;
 
   bfd_hash_table_free (&htab->bstab);
-  _bfd_elf_link_hash_table_free (btab);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create the derived linker hash table.  The PA ELF port uses the derived
@@ -444,8 +444,11 @@ elf32_hppa_link_hash_table_create (bfd *abfd)
   /* Init the stub hash table too.  */
   if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc,
                            sizeof (struct elf32_hppa_stub_hash_entry)))
-    return NULL;
-  (void) elf32_hppa_link_hash_table_free;
+    {
+      _bfd_elf_link_hash_table_free (abfd);
+      return NULL;
+    }
+  htab->etab.root.hash_table_free = elf32_hppa_link_hash_table_free;
 
   htab->text_segment_base = (bfd_vma) -1;
   htab->data_segment_base = (bfd_vma) -1;
index eb5b3d01be852367648e33241aa0ab586ef9fc47..551d17978e6702b65c51c934cf0dc57261454ff9 100644 (file)
@@ -930,16 +930,16 @@ elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab,
 /* Destroy an i386 ELF linker hash table.  */
 
 static void
-elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash)
+elf_i386_link_hash_table_free (bfd *obfd)
 {
   struct elf_i386_link_hash_table *htab
-    = (struct elf_i386_link_hash_table *) hash;
+    = (struct elf_i386_link_hash_table *) obfd->link.hash;
 
   if (htab->loc_hash_table)
     htab_delete (htab->loc_hash_table);
   if (htab->loc_hash_memory)
     objalloc_free ((struct objalloc *) htab->loc_hash_memory);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create an i386 ELF linker hash table.  */
@@ -970,10 +970,10 @@ elf_i386_link_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      elf_i386_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) elf_i386_link_hash_table_free;
+  ret->elf.root.hash_table_free = elf_i386_link_hash_table_free;
 
   return &ret->elf.root;
 }
index 7c845171ec2060f170ea6799727b7dd47835c86b..c3a99df8e48e11fd37dcd261fc9ca7faa59b4114 100644 (file)
@@ -60,15 +60,15 @@ struct m68hc11_scan_param
 
 /* Destroy a 68HC11/68HC12 ELF linker hash table.  */
 
-void
-m68hc11_elf_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
+static void
+m68hc11_elf_bfd_link_hash_table_free (bfd *obfd)
 {
   struct m68hc11_elf_link_hash_table *ret
-    = (struct m68hc11_elf_link_hash_table *) hash;
+    = (struct m68hc11_elf_link_hash_table *) obfd->link.hash;
 
   bfd_hash_table_free (ret->stub_hash_table);
   free (ret->stub_hash_table);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create a 68HC11/68HC12 ELF linker hash table.  */
@@ -97,12 +97,17 @@ m68hc11_elf_hash_table_create (bfd *abfd)
   ret->stub_hash_table = (struct bfd_hash_table*) bfd_malloc (amt);
   if (ret->stub_hash_table == NULL)
     {
-      free (ret);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
   if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
                            sizeof (struct elf32_m68hc11_stub_hash_entry)))
-    return NULL;
+    {
+      free (ret->stub_hash_table);
+      _bfd_elf_link_hash_table_free (abfd);
+      return NULL;
+    }
+  ret->root.root.hash_table_free = m68hc11_elf_bfd_link_hash_table_free;
 
   return ret;
 }
index 1d1f28814bbfbd71a1c8130cebad2dafc7cff033..89ccd7fd8ad4aa73f2d31d1635c92886912fbb45 100644 (file)
@@ -136,7 +136,6 @@ struct m68hc11_elf_link_hash_table
 
 extern struct m68hc11_elf_link_hash_table* m68hc11_elf_hash_table_create
   (bfd*);
-extern void m68hc11_elf_bfd_link_hash_table_free (struct bfd_link_hash_table*);
 
 extern void m68hc11_elf_get_bank_parameters (struct bfd_link_info*);
 
index b857a0dfa8817d0596a1f3ab2ca2f69dfda50ce1..952d819fe21e6ee054b320ec0c8c3807a72a0f85 100644 (file)
@@ -943,18 +943,18 @@ elf_m68k_link_hash_newfunc (struct bfd_hash_entry *entry,
 /* Destroy an m68k ELF linker hash table.  */
 
 static void
-elf_m68k_link_hash_table_free (struct bfd_link_hash_table *_htab)
+elf_m68k_link_hash_table_free (bfd *obfd)
 {
   struct elf_m68k_link_hash_table *htab;
 
-  htab = (struct elf_m68k_link_hash_table *) _htab;
+  htab = (struct elf_m68k_link_hash_table *) obfd->link.hash;
 
   if (htab->multi_got_.bfd2got != NULL)
     {
       htab_delete (htab->multi_got_.bfd2got);
       htab->multi_got_.bfd2got = NULL;
     }
-  _bfd_elf_link_hash_table_free (_htab);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create an m68k ELF linker hash table.  */
@@ -977,7 +977,7 @@ elf_m68k_link_hash_table_create (bfd *abfd)
       free (ret);
       return NULL;
     }
-  (void) elf_m68k_link_hash_table_free;
+  ret->root.root.hash_table_free = elf_m68k_link_hash_table_free;
 
   ret->multi_got_.global_symndx = 1;
 
index fde454b80e376941b57f079f9a77e5abe6d4ccb2..47ca5debe830d90f42be11b50ad1e16187c63409 100644 (file)
@@ -1020,13 +1020,13 @@ metag_link_hash_newfunc (struct bfd_hash_entry *entry,
 /* Free the derived linker hash table.  */
 
 static void
-elf_metag_link_hash_table_free (struct bfd_link_hash_table *btab)
+elf_metag_link_hash_table_free (bfd *obfd)
 {
   struct elf_metag_link_hash_table *htab
-    = (struct elf_metag_link_hash_table *) btab;
+    = (struct elf_metag_link_hash_table *) obfd->link.hash;
 
   bfd_hash_table_free (&htab->bstab);
-  _bfd_elf_link_hash_table_free (btab);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create the derived linker hash table.  The Meta ELF port uses the derived
@@ -1055,8 +1055,11 @@ elf_metag_link_hash_table_create (bfd *abfd)
   /* Init the stub hash table too.  */
   if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc,
                            sizeof (struct elf_metag_stub_hash_entry)))
-    return NULL;
-  (void) elf_metag_link_hash_table_free;
+    {
+      _bfd_elf_link_hash_table_free (abfd);
+      return NULL;
+    }
+  htab->etab.root.hash_table_free = elf_metag_link_hash_table_free;
 
   return &htab->etab.root;
 }
index ba6a3718323e33c581eda42eeb55be6b9890440b..9b3f4361ad682b7fc7aec86d8888dc238872ef92 100644 (file)
@@ -5106,13 +5106,13 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
 /* Free the derived linker hash table.  */
 static void
-nios2_elf32_link_hash_table_free (struct bfd_link_hash_table *btab)
+nios2_elf32_link_hash_table_free (bfd *obfd)
 {
   struct elf32_nios2_link_hash_table *htab
-    = (struct elf32_nios2_link_hash_table *) btab;
+    = (struct elf32_nios2_link_hash_table *) obfd->link.hash;
 
   bfd_hash_table_free (&htab->bstab);
-  _bfd_elf_link_hash_table_free (btab);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Implement bfd_elf32_bfd_link_hash_table_create.  */
@@ -5139,8 +5139,11 @@ nios2_elf32_link_hash_table_create (bfd *abfd)
   /* Init the stub hash table too.  */
   if (!bfd_hash_table_init (&ret->bstab, stub_hash_newfunc,
                            sizeof (struct elf32_nios2_stub_hash_entry)))
-    return NULL;
-  (void) nios2_elf32_link_hash_table_free;
+    {
+      _bfd_elf_link_hash_table_free (abfd);
+      return NULL;
+    }
+  ret->root.root.hash_table_free = nios2_elf32_link_hash_table_free;
 
   return &ret->root.root;
 }
index 588901bab11c7373cf1613b1d8b0f390e247c617..01f39faed50059d71d2d19f59aacf80f1dc1a61c 100644 (file)
@@ -426,20 +426,20 @@ xgate_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   cache_ptr->howto = &elf_xgate_howto_table[r_type];
 }
 
-/* Free the derived linker hash table.  */
+/* Destroy an XGATE ELF linker hash table.  */
 
-void
-xgate_elf_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
+static void
+xgate_elf_bfd_link_hash_table_free (bfd *obfd)
 {
   struct xgate_elf_link_hash_table *ret =
-      (struct xgate_elf_link_hash_table *) hash;
+      (struct xgate_elf_link_hash_table *) obfd->link.hash;
 
   bfd_hash_table_free (ret->stub_hash_table);
   free (ret->stub_hash_table);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
-/* Create a XGATE ELF linker hash table.  */
+/* Create an XGATE ELF linker hash table.  */
 
 static struct bfd_link_hash_table*
 xgate_elf_bfd_link_hash_table_create (bfd *abfd)
@@ -464,7 +464,7 @@ xgate_elf_bfd_link_hash_table_create (bfd *abfd)
   ret->stub_hash_table = (struct bfd_hash_table*) bfd_zmalloc (amt);
   if (ret->stub_hash_table == NULL)
     {
-      free (ret);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -472,9 +472,10 @@ xgate_elf_bfd_link_hash_table_create (bfd *abfd)
       sizeof(struct elf32_xgate_stub_hash_entry)))
     {
       free (ret->stub_hash_table);
-      free (ret);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
+  ret->root.root.hash_table_free = xgate_elf_bfd_link_hash_table_free;
 
   return &ret->root.root;
 }
index 8a178c22ba2118d58ddad922417c2c4324fc7cc6..f1300014dc15d6de208fb0a10cb67a750a555f77 100644 (file)
@@ -100,7 +100,6 @@ struct xgate_elf_link_hash_table
 
 extern struct xgate_elf_link_hash_table* xgate_elf_hash_table_create
   (bfd *);
-extern void xgate_elf_bfd_link_hash_table_free (struct bfd_link_hash_table *);
 
 extern void xgate_elf_get_bank_parameters (struct bfd_link_info *);
 
index 4beeca204badb47d71d5a6cacf4033440d019551..dd86e3c630807edc56c136cf684242606b94a3e6 100644 (file)
@@ -1023,10 +1023,10 @@ elf64_ia64_local_dyn_info_free (void **slot,
 /* Destroy IA-64 linker hash table.  */
 
 static void
-elf64_ia64_link_hash_table_free (struct bfd_link_hash_table *hash)
+elf64_ia64_link_hash_table_free (bfd *obfd)
 {
   struct elf64_ia64_link_hash_table *ia64_info
-    = (struct elf64_ia64_link_hash_table *) hash;
+    = (struct elf64_ia64_link_hash_table *) obfd->link.hash;
   if (ia64_info->loc_hash_table)
     {
       htab_traverse (ia64_info->loc_hash_table,
@@ -1037,7 +1037,7 @@ elf64_ia64_link_hash_table_free (struct bfd_link_hash_table *hash)
     objalloc_free ((struct objalloc *) ia64_info->loc_hash_memory);
   elf_link_hash_traverse (&ia64_info->root,
                          elf64_ia64_global_dyn_info_free, NULL);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create the derived linker hash table.  The IA-64 ELF port uses this
@@ -1067,10 +1067,10 @@ elf64_ia64_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      elf64_ia64_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) elf64_ia64_link_hash_table_free;
+  ret->root.root.hash_table_free = elf64_ia64_link_hash_table_free;
 
   return &ret->root.root;
 }
index 581ce55f309b3b06df1f5a33d64631b0167f1f76..46cba684175fe7e7ddfb5d05bee649409d56f74a 100644 (file)
@@ -4144,15 +4144,16 @@ tocsave_htab_eq (const void *p1, const void *p2)
 /* Destroy a ppc64 ELF linker hash table.  */
 
 static void
-ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
+ppc64_elf_link_hash_table_free (bfd *obfd)
 {
-  struct ppc_link_hash_table *htab = (struct ppc_link_hash_table *) hash;
+  struct ppc_link_hash_table *htab;
 
-  bfd_hash_table_free (&htab->stub_hash_table);
-  bfd_hash_table_free (&htab->branch_hash_table);
+  htab = (struct ppc_link_hash_table *) obfd->link.hash;
   if (htab->tocsave_htab)
     htab_delete (htab->tocsave_htab);
-  _bfd_elf_link_hash_table_free (hash);
+  bfd_hash_table_free (&htab->branch_hash_table);
+  bfd_hash_table_free (&htab->stub_hash_table);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create a ppc64 ELF linker hash table.  */
@@ -4179,7 +4180,7 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
   if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc,
                            sizeof (struct ppc_stub_hash_entry)))
     {
-      _bfd_elf_link_hash_table_free ((struct bfd_link_hash_table *) htab);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -4188,7 +4189,7 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
                            sizeof (struct ppc_branch_hash_entry)))
     {
       bfd_hash_table_free (&htab->stub_hash_table);
-      _bfd_elf_link_hash_table_free ((struct bfd_link_hash_table *) htab);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -4198,12 +4199,10 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
                                        NULL);
   if (htab->tocsave_htab == NULL)
     {
-      bfd_hash_table_free (&htab->branch_hash_table);
-      bfd_hash_table_free (&htab->stub_hash_table);
-      _bfd_elf_link_hash_table_free ((struct bfd_link_hash_table *) htab);
+      ppc64_elf_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) ppc64_elf_link_hash_table_free;
+  htab->elf.root.hash_table_free = ppc64_elf_link_hash_table_free;
 
   /* Initializing two fields of the union is just cosmetic.  We really
      only care about glist, but when compiled on a 32-bit host the
index 27f0a54fdbb7fe7a535a459b04011344b40269fb..894ab988053c882329f3b44b6e7b2f632546ab49 100644 (file)
@@ -970,16 +970,16 @@ elf_x86_64_get_local_sym_hash (struct elf_x86_64_link_hash_table *htab,
 /* Destroy an X86-64 ELF linker hash table.  */
 
 static void
-elf_x86_64_link_hash_table_free (struct bfd_link_hash_table *hash)
+elf_x86_64_link_hash_table_free (bfd *obfd)
 {
   struct elf_x86_64_link_hash_table *htab
-    = (struct elf_x86_64_link_hash_table *) hash;
+    = (struct elf_x86_64_link_hash_table *) obfd->link.hash;
 
   if (htab->loc_hash_table)
     htab_delete (htab->loc_hash_table);
   if (htab->loc_hash_memory)
     objalloc_free ((struct objalloc *) htab->loc_hash_memory);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create an X86-64 ELF linker hash table.  */
@@ -1027,10 +1027,10 @@ elf_x86_64_link_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      elf_x86_64_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) elf_x86_64_link_hash_table_free;
+  ret->elf.root.hash_table_free = elf_x86_64_link_hash_table_free;
 
   return &ret->elf.root;
 }
index 2d953b57a06534d54273b6af0d70e579f616d104..ee80bcc7e2ee76f1b0263869a3ed57e96267bbee 100644 (file)
@@ -6901,6 +6901,7 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
       free (ret);
       return NULL;
     }
+  ret->root.hash_table_free = _bfd_elf_link_hash_table_free;
 
   return &ret->root;
 }
@@ -6908,13 +6909,15 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
 /* Destroy an ELF linker hash table.  */
 
 void
-_bfd_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
+_bfd_elf_link_hash_table_free (bfd *obfd)
 {
-  struct elf_link_hash_table *htab = (struct elf_link_hash_table *) hash;
+  struct elf_link_hash_table *htab;
+
+  htab = (struct elf_link_hash_table *) obfd->link.hash;
   if (htab->dynstr != NULL)
     _bfd_elf_strtab_free (htab->dynstr);
   _bfd_merge_sections_free (htab->merge_info);
-  _bfd_generic_link_hash_table_free (hash);
+  _bfd_generic_link_hash_table_free (obfd);
 }
 
 /* This is a hook for the ELF emulation code in the generic linker to
index 4baa41b00c4263395ef60241012ea506fdb2e225..a8578dae0cd457ad616812207f0f6c43c522cd09 100644 (file)
@@ -2058,10 +2058,10 @@ elfNN_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
 /* Destroy an AArch64 elf linker hash table.  */
 
 static void
-elfNN_aarch64_link_hash_table_free (struct bfd_link_hash_table *hash)
+elfNN_aarch64_link_hash_table_free (bfd *obfd)
 {
   struct elf_aarch64_link_hash_table *ret
-    = (struct elf_aarch64_link_hash_table *) hash;
+    = (struct elf_aarch64_link_hash_table *) obfd->link.hash;
 
   if (ret->loc_hash_table)
     htab_delete (ret->loc_hash_table);
@@ -2069,7 +2069,7 @@ elfNN_aarch64_link_hash_table_free (struct bfd_link_hash_table *hash)
     objalloc_free ((struct objalloc *) ret->loc_hash_memory);
 
   bfd_hash_table_free (&ret->stub_hash_table);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create an AArch64 elf linker hash table.  */
@@ -2100,7 +2100,7 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
   if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc,
                            sizeof (struct elf_aarch64_stub_hash_entry)))
     {
-      free (ret);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -2111,10 +2111,10 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      elfNN_aarch64_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) elfNN_aarch64_link_hash_table_free;
+  ret->root.root.hash_table_free = elfNN_aarch64_link_hash_table_free;
 
   return &ret->root.root;
 }
index c87dd996efed3cf99bd07bde303511b6e1d1949a..a8d8d0bcc22fe1d4f4bb119e231a83b0142b5a5d 100644 (file)
@@ -1414,10 +1414,10 @@ elfNN_ia64_local_dyn_info_free (void **slot,
 /* Destroy IA-64 linker hash table.  */
 
 static void
-elfNN_ia64_link_hash_table_free (struct bfd_link_hash_table *hash)
+elfNN_ia64_link_hash_table_free (bfd *obfd)
 {
   struct elfNN_ia64_link_hash_table *ia64_info
-    = (struct elfNN_ia64_link_hash_table *) hash;
+    = (struct elfNN_ia64_link_hash_table *) obfd->link.hash;
   if (ia64_info->loc_hash_table)
     {
       htab_traverse (ia64_info->loc_hash_table,
@@ -1428,7 +1428,7 @@ elfNN_ia64_link_hash_table_free (struct bfd_link_hash_table *hash)
     objalloc_free ((struct objalloc *) ia64_info->loc_hash_memory);
   elf_link_hash_traverse (&ia64_info->root,
                          elfNN_ia64_global_dyn_info_free, NULL);
-  _bfd_elf_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create the derived linker hash table.  The IA-64 ELF port uses this
@@ -1458,10 +1458,10 @@ elfNN_ia64_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      elfNN_ia64_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) elfNN_ia64_link_hash_table_free;
+  ret->root.root.hash_table_free = elfNN_ia64_link_hash_table_free;
 
   return &ret->root.root;
 }
index 48ca02af9cd9d4cd95158fe4356ef5431b16f89b..e8ebcb30632e9eb2892a3f64e9038f3bd8e1a38e 100644 (file)
@@ -1104,17 +1104,17 @@ elf_sparc_get_local_sym_hash (struct _bfd_sparc_elf_link_hash_table *htab,
 
 /* Destroy a SPARC ELF linker hash table.  */
 
-void
-_bfd_sparc_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
+static void
+_bfd_sparc_elf_link_hash_table_free (bfd *obfd)
 {
   struct _bfd_sparc_elf_link_hash_table *htab
-    = (struct _bfd_sparc_elf_link_hash_table *) hash;
+    = (struct _bfd_sparc_elf_link_hash_table *) obfd->link.hash;
 
   if (htab->loc_hash_table)
     htab_delete (htab->loc_hash_table);
   if (htab->loc_hash_memory)
     objalloc_free ((struct objalloc *) htab->loc_hash_memory);
-  _bfd_generic_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create a SPARC ELF linker hash table.  */
@@ -1183,9 +1183,10 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      _bfd_sparc_elf_link_hash_table_free (abfd);
       return NULL;
     }
+  ret->elf.root.hash_table_free = _bfd_sparc_elf_link_hash_table_free;
 
   return &ret->elf.root;
 }
index 775c4d73c80e666aa619554a50e97099f72890a0..cf1991b411bcc17dc1b0a4ab85b93a81dbd52dd5 100644 (file)
@@ -106,8 +106,6 @@ extern bfd_boolean _bfd_sparc_elf_mkobject
   (bfd *);
 extern struct bfd_link_hash_table *_bfd_sparc_elf_link_hash_table_create
   (bfd *);
-extern void _bfd_sparc_elf_link_hash_table_free
-  (struct bfd_link_hash_table *);
 extern bfd_boolean _bfd_sparc_elf_create_dynamic_sections
   (bfd *, struct bfd_link_info *);
 extern void _bfd_sparc_elf_copy_indirect_symbol
index 3e6a172ba2f20e2e6c10a3d5a84dac53505d637b..4149474ffff3558f2bb081f9e22619119d817484 100644 (file)
@@ -392,6 +392,7 @@ bfd_hash_table_init_n (struct bfd_hash_table *table,
       objalloc_alloc ((struct objalloc *) table->memory, alloc);
   if (table->table == NULL)
     {
+      bfd_hash_table_free (table);
       bfd_set_error (bfd_error_no_memory);
       return FALSE;
     }
index c17e508289c24daac9a4dd126b9d7be0333f8cd5..03dbd0af347e67894e64e5638e9059c0119e1649 100644 (file)
@@ -588,7 +588,7 @@ extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create
 
 /* Generic link hash table destruction routine.  */
 extern void _bfd_generic_link_hash_table_free
-  (struct bfd_link_hash_table *);
+  (bfd *);
 
 /* Generic add symbol routine.  */
 extern bfd_boolean _bfd_generic_link_add_symbols
index 923eb93d6739aa841361dfd37cdf6c764489f397..3bb37260c77b1408040ebb3866a801d95ce401dc 100644 (file)
@@ -593,7 +593,7 @@ extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create
 
 /* Generic link hash table destruction routine.  */
 extern void _bfd_generic_link_hash_table_free
-  (struct bfd_link_hash_table *);
+  (bfd *);
 
 /* Generic add symbol routine.  */
 extern bfd_boolean _bfd_generic_link_add_symbols
index 367d3bc2e1b59e4abb5a1910f5e38649bda20571..8a45bf62c12f0ccc5552df6b405dc11bb7a842d4 100644 (file)
@@ -603,8 +603,6 @@ extern long _bfd_xcoff_canonicalize_dynamic_reloc
   (bfd *, arelent **, asymbol **);
 extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
   (bfd *);
-extern void _bfd_xcoff_bfd_link_hash_table_free
-  (struct bfd_link_hash_table *);
 extern bfd_boolean _bfd_xcoff_bfd_link_add_symbols
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean _bfd_xcoff_bfd_final_link
index 24b9b57f4e0c6ae58f2266bfe5fd881f48454a26..d2c794deb9ceb752b438ff4a54863ee613598b17 100644 (file)
@@ -607,8 +607,6 @@ extern long _bfd_xcoff_canonicalize_dynamic_reloc
   (bfd *, arelent **, asymbol **);
 extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
   (bfd *);
-extern void _bfd_xcoff_bfd_link_hash_table_free
-  (struct bfd_link_hash_table *);
 extern bfd_boolean _bfd_xcoff_bfd_link_add_symbols
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean _bfd_xcoff_bfd_final_link
index 1afe4ed6f3ed66c39c7dd0bdb9761e6f75976a97..483a0d4ea921a38a213e83919909bb3b3c00356b 100644 (file)
@@ -482,11 +482,22 @@ _bfd_link_hash_table_init
                                      const char *),
    unsigned int entsize)
 {
+  bfd_boolean ret;
+
+  BFD_ASSERT (!abfd->is_linker_output && !abfd->link.hash);
   table->undefs = NULL;
   table->undefs_tail = NULL;
   table->type = bfd_link_generic_hash_table;
 
-  return bfd_hash_table_init (&table->table, newfunc, entsize);
+  ret = bfd_hash_table_init (&table->table, newfunc, entsize);
+  if (ret)
+    {
+      /* Arrange for destruction of this hash table on closing ABFD.  */
+      table->hash_table_free = _bfd_generic_link_hash_table_free;
+      abfd->link.hash = table;
+      abfd->is_linker_output = TRUE;
+    }
+  return ret;
 }
 
 /* Look up a symbol in a link hash table.  If follow is TRUE, we
@@ -771,13 +782,16 @@ _bfd_generic_link_hash_table_create (bfd *abfd)
 }
 
 void
-_bfd_generic_link_hash_table_free (struct bfd_link_hash_table *hash)
+_bfd_generic_link_hash_table_free (bfd *obfd)
 {
-  struct generic_link_hash_table *ret
-    = (struct generic_link_hash_table *) hash;
+  struct generic_link_hash_table *ret;
 
+  BFD_ASSERT (obfd->is_linker_output && obfd->link.hash);
+  ret = (struct generic_link_hash_table *) obfd->link.hash;
   bfd_hash_table_free (&ret->root.table);
   free (ret);
+  obfd->link.hash = NULL;
+  obfd->is_linker_output = FALSE;
 }
 
 /* Grab the symbols for an object file when doing a generic link.  We
index 7d256bf36ef5441ec4949283d6a47ce3a2c74d13..ca64101b83c55ba0fc70bbfea0e9d255231aa9a7 100644 (file)
@@ -188,6 +188,7 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
   bfd_byte *contents, *data;
   int storage_needed;
   struct saved_offsets saved_offsets;
+  bfd *link_next;
 
   /* Don't apply relocation on executable and shared library.  See
      PR 4756.  */
@@ -209,6 +210,8 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
   link_info.input_bfds = abfd;
   link_info.input_bfds_tail = &abfd->link.next;
 
+  link_next = abfd->link.next;
+  abfd->link.next = NULL;
   link_info.hash = _bfd_generic_link_hash_table_create (abfd);
   link_info.callbacks = &callbacks;
   callbacks.warning = simple_dummy_warning;
@@ -232,7 +235,11 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
       bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
       data = (bfd_byte *) bfd_malloc (amt);
       if (data == NULL)
-       return NULL;
+       {
+         _bfd_generic_link_hash_table_free (abfd);
+         abfd->link.next = link_next;
+         return NULL;
+       }
       outbuf = data;
     }
 
@@ -243,6 +250,8 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
     {
       if (data)
        free (data);
+      _bfd_generic_link_hash_table_free (abfd);
+      abfd->link.next = link_next;
       return NULL;
     }
   bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets);
@@ -270,6 +279,7 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
   bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets);
   free (saved_offsets.sections);
 
-  _bfd_generic_link_hash_table_free (link_info.hash);
+  _bfd_generic_link_hash_table_free (abfd);
+  abfd->link.next = link_next;
   return contents;
 }
index f6c7fe6fa303d0a18653885d07e65e988773f2ba..67e1c523d2af487b544676b102dd3fbbfcfe8186 100644 (file)
@@ -573,14 +573,17 @@ xcoff_link_hash_newfunc (struct bfd_hash_entry *entry,
 
 /* Destroy an XCOFF link hash table.  */
 
-void
-_bfd_xcoff_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
+static void
+_bfd_xcoff_bfd_link_hash_table_free (bfd *obfd)
 {
-  struct xcoff_link_hash_table *ret = (struct xcoff_link_hash_table *) hash;
+  struct xcoff_link_hash_table *ret;
 
-  _bfd_stringtab_free (ret->debug_strtab);
-  bfd_hash_table_free (&ret->root.table);
-  free (ret);
+  ret = (struct xcoff_link_hash_table *) obfd->link.hash;
+  if (ret->archive_info)
+    htab_delete (ret->archive_info);
+  if (ret->debug_strtab)
+    _bfd_stringtab_free (ret->debug_strtab);
+  _bfd_generic_link_hash_table_free (obfd);
 }
 
 /* Create an XCOFF link hash table.  */
@@ -604,6 +607,12 @@ _bfd_xcoff_bfd_link_hash_table_create (bfd *abfd)
   ret->debug_strtab = _bfd_xcoff_stringtab_init ();
   ret->archive_info = htab_create (37, xcoff_archive_info_hash,
                                   xcoff_archive_info_eq, NULL);
+  if (!ret->debug_strtab || !ret->archive_info)
+    {
+      _bfd_xcoff_bfd_link_hash_table_free (abfd);
+      return NULL;
+    }
+  ret->root.hash_table_free = _bfd_xcoff_bfd_link_hash_table_free;
 
   /* The linker will always generate a full a.out header.  We need to
      record that fact now, before the sizeof_headers routine could be
index eaf81fdbc708f986f24ade5ab86e68eac8d88128..96ae31d19f77f6e938f0cdf9159084bc4cdc99ab 100644 (file)
@@ -1,3 +1,7 @@
+2014-06-13  Alan Modra  <amodra@gmail.com>
+
+       * bfdlink.h (struct bfd_link_hash_table): Add hash_table_free field.
+
 2014-06-13  Alan Modra  <amodra@gmail.com>
 
        * bfdlink.h: Update for bfd.link_next change.
index 391b3a981bfc9fbb147e9ff503237a6a824915d1..fc14a9fadb638660b70e8ee80705cc82bf388ee5 100644 (file)
@@ -167,6 +167,8 @@ struct bfd_link_hash_table
   struct bfd_link_hash_entry *undefs;
   /* Entries are added to the tail of the undefs list.  */
   struct bfd_link_hash_entry *undefs_tail;
+  /* Function to free the hash table on closing BFD.  */
+  void (*hash_table_free) (bfd *);
   /* The type of the link hash table.  */
   enum bfd_link_hash_table_type type;
 };