[binutils-gdb] Free bfds on the file_chain at linker exit.

Nick Clifton nickc@sourceware.org
Wed Feb 4 11:37:56 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=52fdc0531ea70c675561ff8d2e04b81028c500fc

commit 52fdc0531ea70c675561ff8d2e04b81028c500fc
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Feb 4 11:37:25 2026 +0000

    Free bfds on the file_chain at linker exit.

Diff:
---
 ld/ldlang.c | 31 +++++++++++++++++++++++++++++++
 ld/ldlang.h |  2 ++
 ld/ldmain.c |  9 +++------
 3 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/ld/ldlang.c b/ld/ldlang.c
index c0d729811ec..a8c7854b5f8 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1427,6 +1427,37 @@ lang_finish (void)
   ldfile_free ();
 }
 
+/* Called by ld_cleanup() at linker exit.  Frees any remaining memory used by
+   ldlang.c in order to pacify memory leak checkers.  */
+
+void
+lang_cleanup (void)
+{
+  lang_input_statement_type *search;
+
+  /* FIXME: Walking the file_chain list closes most of the open bfds but not
+     all of them.  We should find and close the others as well.
+
+     Note: the bfds closed here can also be found on the input_file_chain and
+     link_info.input_bfd lists.  A bfd can only be closed once however, so we
+     must not walk those other lists.  */
+
+  for (search = (void *) file_chain.head;
+       search != NULL;
+       search = search->next_real_file)
+    {
+      if (search->the_bfd == NULL)
+	continue;
+      
+      bfd_close_all_done (search->the_bfd);
+      search->the_bfd = NULL;
+    }
+
+  stat_free (NULL);
+
+  obstack_free (&pt_obstack, NULL);
+}
+
 /*----------------------------------------------------------------------
   A region is an area of memory declared with the
   MEMORY {  name:org=exp, len=exp ... }
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 36f3c03955d..c3ee40a980c 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -546,6 +546,8 @@ extern void lang_init
   (bool);
 extern void lang_finish
   (void);
+extern void lang_cleanup
+  (void);
 extern lang_memory_region_type * lang_memory_region_lookup
   (const char * const, bool);
 extern void lang_memory_region_alias
diff --git a/ld/ldmain.c b/ld/ldmain.c
index a2711d230ea..c73c228e59d 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -222,14 +222,11 @@ write_dependency_file (void)
 static void
 ld_cleanup (void)
 {
-  bfd *ibfd, *inext;
   if (link_info.output_bfd)
     bfd_close_all_done (link_info.output_bfd);
-  for (ibfd = link_info.input_bfds; ibfd; ibfd = inext)
-    {
-      inext = ibfd->link.next;
-      bfd_close_all_done (ibfd);
-    }
+
+  lang_cleanup ();
+
   /* Note - we do not call ld_plugin_start (PHASE_PLUGINS) here as this
      function is only called when the linker is exiting - ie after any
      stats may have been reported, and potentially in the middle of a


More information about the Binutils-cvs mailing list