Fix freeing of link_info.hash
authorHans-Peter Nilsson <hp@bitrange.com>
Sat, 10 May 2014 00:50:01 +0000 (02:50 +0200)
committerHans-Peter Nilsson <hp@bitrange.com>
Sat, 10 May 2014 00:52:14 +0000 (02:52 +0200)
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.

14 files changed:
ld/ChangeLog
ld/ldlang.c
ld/ldlang.h
ld/ldmain.c
ld/testsuite/ChangeLog
ld/testsuite/ld-mmix/wrap1.d [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap1a.s [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap1b.s [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap1c.s [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap2.d [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap3.d [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap3a.s [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap3b.s [new file with mode: 0644]
ld/testsuite/ld-mmix/wrap4.d [new file with mode: 0644]

index 9decdaabb4448be23951d6cdea8d64b75fd34f32..92a1c6cf7794f657b659106b2ad94543449fca85 100644 (file)
@@ -1,3 +1,13 @@
+2014-05-10  Hans-Peter Nilsson  <hp@bitrange.com>
+
+       * 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  <amodra@gmail.com>
 
        * emultempl/metagelf.em: Update bfd target vector naming.
index d147ee0c81a4f53621d0a37e7dab0cfe40dd50f2..8d1e3f79049c05a35d2aa77d230e8f3b7ba97f66 100644 (file)
@@ -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);
 }
 
index aacd5dcaed53188974c69ff4aa96c693633794a6..47cc4df0f4e54a6ce102b23f19a3bae08b959df3 100644 (file)
@@ -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
index 4c7ea68f41e786a845beb737dd4d48318b869d01..2d987b827a7a893bdb3e78bc65054b02eb96857f 100644 (file)
@@ -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
index ed50efa1813088e01cd95776f3f40843eb7f6dc6..021d17cf0de5bcdc41afeb69fcf048bd77b57b01 100644 (file)
@@ -1,3 +1,10 @@
+2014-05-10  Hans-Peter Nilsson  <hp@bitrange.com>
+
+       * 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  <hongjiu.lu@intel.com>
 
        * 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 (file)
index 0000000..02d7bef
--- /dev/null
@@ -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 <deal>
+
+0+c <deal>:
+   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 (file)
index 0000000..88a5cd2
--- /dev/null
@@ -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 (file)
index 0000000..367aea0
--- /dev/null
@@ -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 (file)
index 0000000..a7678d4
--- /dev/null
@@ -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 (file)
index 0000000..49b4d3b
--- /dev/null
@@ -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 <deal>
+
+0+c <deal>:
+   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 (file)
index 0000000..80b20f1
--- /dev/null
@@ -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 <deal>
+
+0+c <deal>:
+   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 (file)
index 0000000..7192a93
--- /dev/null
@@ -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 (file)
index 0000000..6a8a606
--- /dev/null
@@ -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 (file)
index 0000000..a64578d
--- /dev/null
@@ -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 <deal>
+
+0+c <deal>:
+   c:  fd000000        swym 0,0,0