aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-06-13 19:11:39 +0930
committerAlan Modra <amodra@gmail.com>2014-06-13 19:11:39 +0930
commitd495ab0d843def702a6641fa4fc31708d7fc97b1 (patch)
treea16dc7d65d085eb532bcf044a358d737e252061e /bfd
parentcaa4096e844a000ff63c4fa9180d70ca2093fd2a (diff)
downloadgdb-d495ab0d843def702a6641fa4fc31708d7fc97b1.zip
gdb-d495ab0d843def702a6641fa4fc31708d7fc97b1.tar.gz
gdb-d495ab0d843def702a6641fa4fc31708d7fc97b1.tar.bz2
Free linker hash table from bfd_close.
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog38
-rw-r--r--bfd/archive.c4
-rw-r--r--bfd/bfd-in2.h3
-rw-r--r--bfd/bfd.c3
-rw-r--r--bfd/elf-bfd.h2
-rw-r--r--bfd/elf-m10300.c43
-rw-r--r--bfd/elf32-arm.c10
-rw-r--r--bfd/elf32-avr.c13
-rw-r--r--bfd/elf32-hppa.c13
-rw-r--r--bfd/elf32-i386.c10
-rw-r--r--bfd/elf32-m68hc1x.c17
-rw-r--r--bfd/elf32-m68hc1x.h1
-rw-r--r--bfd/elf32-m68k.c8
-rw-r--r--bfd/elf32-metag.c13
-rw-r--r--bfd/elf32-nios2.c13
-rw-r--r--bfd/elf32-xgate.c17
-rw-r--r--bfd/elf32-xgate.h1
-rw-r--r--bfd/elf64-ia64-vms.c10
-rw-r--r--bfd/elf64-ppc.c21
-rw-r--r--bfd/elf64-x86-64.c10
-rw-r--r--bfd/elflink.c9
-rw-r--r--bfd/elfnn-aarch64.c12
-rw-r--r--bfd/elfnn-ia64.c10
-rw-r--r--bfd/elfxx-sparc.c11
-rw-r--r--bfd/elfxx-sparc.h2
-rw-r--r--bfd/hash.c1
-rw-r--r--bfd/libbfd-in.h2
-rw-r--r--bfd/libbfd.h2
-rw-r--r--bfd/libcoff-in.h2
-rw-r--r--bfd/libcoff.h2
-rw-r--r--bfd/linker.c22
-rw-r--r--bfd/simple.c14
-rw-r--r--bfd/xcofflink.c21
33 files changed, 231 insertions, 129 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4cb3d06..0caff71 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,43 @@
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
* targets.c (BFD_JUMP_TABLE): Delete NAME##_bfd_link_hash_table_free.
(struct bfd_target <_bfd_link_hash_table_free>): Delete.
diff --git a/bfd/archive.c b/bfd/archive.c
index 157a3f7..1c3ad52 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -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;
}
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 07d94df..d9056ce 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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. */
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 2406319..e19bcf7 100644
--- 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. *}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 1bbe771..a06c54b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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 *);
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index 4cc879e..f29025d 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -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;
}
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 6358b58..ef8bfa6 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -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;
}
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index 5595384..b46a44c 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -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;
}
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 635ec42..0588ebb 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -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;
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb5b3d0..551d179 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -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;
}
diff --git a/bfd/elf32-m68hc1x.c b/bfd/elf32-m68hc1x.c
index 7c84517..c3a99df 100644
--- a/bfd/elf32-m68hc1x.c
+++ b/bfd/elf32-m68hc1x.c
@@ -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;
}
diff --git a/bfd/elf32-m68hc1x.h b/bfd/elf32-m68hc1x.h
index 1d1f288..89ccd7f 100644
--- a/bfd/elf32-m68hc1x.h
+++ b/bfd/elf32-m68hc1x.h
@@ -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*);
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index b857a0d..952d819 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -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;
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index fde454b..47ca5de 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -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;
}
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index ba6a371..9b3f436 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -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;
}
diff --git a/bfd/elf32-xgate.c b/bfd/elf32-xgate.c
index 588901b..01f39fa 100644
--- a/bfd/elf32-xgate.c
+++ b/bfd/elf32-xgate.c
@@ -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;
}
diff --git a/bfd/elf32-xgate.h b/bfd/elf32-xgate.h
index 8a178c2..f130001 100644
--- a/bfd/elf32-xgate.h
+++ b/bfd/elf32-xgate.h
@@ -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 *);
diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c
index 4beeca2..dd86e3c 100644
--- a/bfd/elf64-ia64-vms.c
+++ b/bfd/elf64-ia64-vms.c
@@ -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;
}
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 581ce55..46cba68 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -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
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 27f0a54..894ab98 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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;
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 2d953b5..ee80bcc 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4baa41b..a8578da 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -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;
}
diff --git a/bfd/elfnn-ia64.c b/bfd/elfnn-ia64.c
index c87dd99..a8d8d0b 100644
--- a/bfd/elfnn-ia64.c
+++ b/bfd/elfnn-ia64.c
@@ -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;
}
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 48ca02a..e8ebcb3 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -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;
}
diff --git a/bfd/elfxx-sparc.h b/bfd/elfxx-sparc.h
index 775c4d7..cf1991b 100644
--- a/bfd/elfxx-sparc.h
+++ b/bfd/elfxx-sparc.h
@@ -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
diff --git a/bfd/hash.c b/bfd/hash.c
index 3e6a172..4149474 100644
--- a/bfd/hash.c
+++ b/bfd/hash.c
@@ -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;
}
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index c17e508..03dbd0a 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -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
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 923eb93..3bb3726 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -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
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 367d3bc..8a45bf6 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -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
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 24b9b57..d2c794d 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -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
diff --git a/bfd/linker.c b/bfd/linker.c
index 1afe4ed..483a0d4 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -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
diff --git a/bfd/simple.c b/bfd/simple.c
index 7d256bf..ca64101 100644
--- a/bfd/simple.c
+++ b/bfd/simple.c
@@ -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;
}
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index f6c7fe6..67e1c52 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -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