aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
authorHans-Peter Nilsson <hp@bitrange.com>2014-05-10 02:50:01 +0200
committerHans-Peter Nilsson <hp@bitrange.com>2014-05-10 02:52:14 +0200
commiteae25ec5773e12af107e65fcf0c94a54bc5180ae (patch)
tree584bbe1178f76697d0cea1e843819b9027d8c0f3 /ld/ldlang.c
parentb1f02b89ed9e9c68eab6f645e19634315a6525c4 (diff)
downloadgdb-eae25ec5773e12af107e65fcf0c94a54bc5180ae.zip
gdb-eae25ec5773e12af107e65fcf0c94a54bc5180ae.tar.gz
gdb-eae25ec5773e12af107e65fcf0c94a54bc5180ae.tar.bz2
Fix freeing of link_info.hash
ld: * ldlang.c (lang_finish): Don't call bfd_link_hash_table_free here. (output_bfd_hash_table_free_fn): New variable. (open_output): Save the _bfd_link_hash_table_free function for the output_bfd into output_bfd_hash_table_free_fn. * ldmain.c (ld_cleanup): If set, call output_bfd_hash_table_free_fn on link_info.hash. * ldlang.h (output_bfd_hash_table_free_fn): Declare. ld/testsuite: * ld-mmix/wrap1.d, ld-mmix/wrap1a.s, ld-mmix/wrap1b.s, ld-mmix/wrap1c.s, ld-mmix/wrap2.d, ld-mmix/wrap3.d, ld-mmix/wrap3a.s, ld-mmix/wrap3b.s, ld-mmix/wrap4.d: New tests.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r--ld/ldlang.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c
index d147ee0..8d1e3f7 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1237,7 +1237,6 @@ lang_init (void)
void
lang_finish (void)
{
- bfd_link_hash_table_free (link_info.output_bfd, link_info.hash);
bfd_hash_table_free (&lang_definedness_table);
output_section_statement_table_free ();
}
@@ -3073,6 +3072,9 @@ lang_get_output_target (void)
return default_target;
}
+/* Stashed function to free link_info.hash; see open_output. */
+void (*output_bfd_hash_table_free_fn) (struct bfd_link_hash_table *);
+
/* Open the output file. */
static void
@@ -3152,6 +3154,18 @@ open_output (const char *name)
if (link_info.hash == NULL)
einfo (_("%P%F: can not create hash table: %E\n"));
+ /* We want to please memory leak checkers by deleting link_info.hash.
+ We can't do it in lang_finish, as a bfd target may hold references to
+ symbols in this table and use them when their _bfd_write_contents
+ function is invoked, as part of bfd_close on the output_bfd. But,
+ output_bfd is deallocated at bfd_close, so we can't refer to
+ output_bfd after that time, and dereferencing it is needed to call
+ "bfd_link_hash_table_free". Smash this dependency deadlock and grab
+ the function pointer; arrange to call it on link_info.hash in
+ ld_cleanup. */
+ output_bfd_hash_table_free_fn
+ = link_info.output_bfd->xvec->_bfd_link_hash_table_free;
+
bfd_set_gp_size (link_info.output_bfd, g_switch_value);
}