From: Hans-Peter Nilsson Date: Sat, 10 May 2014 00:50:01 +0000 (+0200) Subject: Fix freeing of link_info.hash X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=eae25ec5773e12af107e65fcf0c94a54bc5180ae;p=binutils-gdb.git 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. --- diff --git a/ld/ChangeLog b/ld/ChangeLog index 9decdaabb44..92a1c6cf779 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,13 @@ +2014-05-10 Hans-Peter Nilsson + + * 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. + 2014-05-02 Alan Modra * emultempl/metagelf.em: Update bfd target vector naming. diff --git a/ld/ldlang.c b/ld/ldlang.c index d147ee0c81a..8d1e3f79049 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); } diff --git a/ld/ldlang.h b/ld/ldlang.h index aacd5dcaed5..47cc4df0f4e 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -518,6 +518,8 @@ extern lang_statement_list_type input_file_chain; extern int lang_statement_iteration; extern struct asneeded_minfo **asneeded_list_tail; +extern void (*output_bfd_hash_table_free_fn) (struct bfd_link_hash_table *); + extern void lang_init (void); extern void lang_finish diff --git a/ld/ldmain.c b/ld/ldmain.c index 4c7ea68f41e..2d987b827a7 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -171,6 +171,10 @@ ld_cleanup (void) #endif if (output_filename && delete_output_file_on_failure) unlink_if_ordinary (output_filename); + + /* See open_output in ldlang.c. */ + if (output_bfd_hash_table_free_fn != NULL) + (*output_bfd_hash_table_free_fn) (link_info.hash); } /* If there's a BFD assertion, we'll notice and exit with an error diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index ed50efa1813..021d17cf0de 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-05-10 Hans-Peter Nilsson + + * 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. + 2014-05-09 H.J. Lu * ld-x86-64/tlsbin.dd: Replace data32 with data16. diff --git a/ld/testsuite/ld-mmix/wrap1.d b/ld/testsuite/ld-mmix/wrap1.d new file mode 100644 index 00000000000..02d7bef2a09 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap1.d @@ -0,0 +1,21 @@ +#source: start.s +#source: wrap1a.s +#source: wrap1b.s +#source: wrap1c.s +#ld: -m mmo --wrap deal +#as: -no-expand +#objdump: -d + +.*: file format mmo + +Disassembly of section \.text: + +0+ <(_start|Main)>: + 0: e3fd0001 setl \$253,0x1 + 4: f2000001 pushj \$0,8 <__wrap_deal> + +0+8 <__wrap_deal>: + 8: f0000001 jmp c + +0+c : + c: fd000000 swym 0,0,0 diff --git a/ld/testsuite/ld-mmix/wrap1a.s b/ld/testsuite/ld-mmix/wrap1a.s new file mode 100644 index 00000000000..88a5cd216e9 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap1a.s @@ -0,0 +1,2 @@ + .text + pushj $0,deal diff --git a/ld/testsuite/ld-mmix/wrap1b.s b/ld/testsuite/ld-mmix/wrap1b.s new file mode 100644 index 00000000000..367aea02124 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap1b.s @@ -0,0 +1,4 @@ + .text + .globl __wrap_deal +__wrap_deal: + jmp __real_deal diff --git a/ld/testsuite/ld-mmix/wrap1c.s b/ld/testsuite/ld-mmix/wrap1c.s new file mode 100644 index 00000000000..a7678d4f215 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap1c.s @@ -0,0 +1,4 @@ + .text + .globl deal +deal: + swym 0 diff --git a/ld/testsuite/ld-mmix/wrap2.d b/ld/testsuite/ld-mmix/wrap2.d new file mode 100644 index 00000000000..49b4d3b4f59 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap2.d @@ -0,0 +1,21 @@ +#source: start.s +#source: wrap1a.s +#source: wrap1b.s +#source: wrap1c.s +#ld: -m elf64mmix --wrap deal +#as: -no-expand +#objdump: -d + +.*: file format elf64-mmix + +Disassembly of section \.text: + +0+ <(_start|Main)>: + 0: e3fd0001 setl \$253,0x1 + 4: f2000001 pushj \$0,8 <__wrap_deal> + +0+8 <__wrap_deal>: + 8: f0000001 jmp c + +0+c : + c: fd000000 swym 0,0,0 diff --git a/ld/testsuite/ld-mmix/wrap3.d b/ld/testsuite/ld-mmix/wrap3.d new file mode 100644 index 00000000000..80b20f1f3bc --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap3.d @@ -0,0 +1,21 @@ +#source: start.s +#source: wrap3a.s +#source: wrap3b.s +#source: wrap1c.s +#ld: -m mmo +#as: -no-expand +#objdump: -d + +.*: file format mmo + +Disassembly of section \.text: + +0+ <(_start|Main)>: + 0: e3fd0001 setl \$253,0x1 + 4: f2000001 pushj \$0,8 <__wrap_deal> + +0+8 <__wrap_deal>: + 8: f0000001 jmp c + +0+c : + c: fd000000 swym 0,0,0 diff --git a/ld/testsuite/ld-mmix/wrap3a.s b/ld/testsuite/ld-mmix/wrap3a.s new file mode 100644 index 00000000000..7192a932445 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap3a.s @@ -0,0 +1,2 @@ + .text + pushj $0,__wrap_deal diff --git a/ld/testsuite/ld-mmix/wrap3b.s b/ld/testsuite/ld-mmix/wrap3b.s new file mode 100644 index 00000000000..6a8a6067c12 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap3b.s @@ -0,0 +1,4 @@ + .text + .globl __wrap_deal +__wrap_deal: + jmp deal diff --git a/ld/testsuite/ld-mmix/wrap4.d b/ld/testsuite/ld-mmix/wrap4.d new file mode 100644 index 00000000000..a64578d1304 --- /dev/null +++ b/ld/testsuite/ld-mmix/wrap4.d @@ -0,0 +1,21 @@ +#source: start.s +#source: wrap3a.s +#source: wrap3b.s +#source: wrap1c.s +#ld: -m elf64mmix +#as: -no-expand +#objdump: -d + +.*: file format elf64-mmix + +Disassembly of section \.text: + +0+ <(_start|Main)>: + 0: e3fd0001 setl \$253,0x1 + 4: f2000001 pushj \$0,8 <__wrap_deal> + +0+8 <__wrap_deal>: + 8: f0000001 jmp c + +0+c : + c: fd000000 swym 0,0,0