Commit: Free more bfds on linker exit
Nick Clifton
nickc@redhat.com
Wed Feb 4 11:38:04 GMT 2026
Hi Guys,
I am applying the patch below to close on the big memory leaks in the
linker. After applying the patch the largest lost block of memory
went from 311 megabytes to 227 kilobytes. (This information was
obtained by using valgrind to the monitor the linker whilst it linked
LLVM's llc binary. LLC is a 2 gigabyte executable so this makes for a
nice big test).
The patch does not actually help with my ultimate goal of reducing the
linker's overall memory usage. But it does feel good to close such a
big leak and maybe it will be possible to call the new cleanup
function earlier on in the link process.
Cheers
Nick
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
mailing list