]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: only free on exit when --enable-leak-check
authorAlan Modra <amodra@gmail.com>
Wed, 4 Mar 2026 22:45:04 +0000 (09:15 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 4 Mar 2026 22:45:04 +0000 (09:15 +1030)
Adds a new --enable-leak-check option, controlling whether memory is
freed before exit in order to find memory leaks.  The default is to
free memory if BFD_ASAN is non-zero.

* configure.ac: Add new --enable-leak-check..
(ENABLE_LEAK_CHECK): ..defining this.
* as.c (gas_early_init): free_notes on exit only if ENABLE_LEAK_CHECK.
* expr.c (expr_end): Nothing to do when !ENABLE_LEAK_CHECK.
* macro.c (macro_end): Likewise.
* output-file.c (output_file_close): Don't stash frchain obstacks
when !ENABLE_LEAK_CHECK.
* read.c (read_end): Nothing to do when !ENABLE_LEAK_CHECK.
(poend): Likewise.
* stabs.c (stabs_end): Likewise.
* subsegs.c (subsegs_end): Likewise.
* symbols.c (symbol_end): Likewise.
* config/obj-elf-attr.c (oav1_attr_info_exit): Likewise.
* config/obj-elf.c (elf_end): Likewise.
* config/tc-arc.c (arc_md_end): Likewise.
* config/tc-i386.c (i386_md_end): Likewise.
* config/tc-loongarch.c (loongarch_md_end): Likewise.
* config/tc-ppc.c (ppc_md_end): Likewise.
* config/tc-pru.c (pru_md_end): Likewise.
* config/tc-riscv.c (riscv_md_end): Likewise.
* config/tc-tic54x.c (tic54x_md_end): Likewise.
* configure: Regenerate.
* config.in: Regenerate.

20 files changed:
gas/as.c
gas/config.in
gas/config/obj-elf-attr.c
gas/config/obj-elf.c
gas/config/tc-arc.c
gas/config/tc-i386.c
gas/config/tc-loongarch.c
gas/config/tc-ppc.c
gas/config/tc-pru.c
gas/config/tc-riscv.c
gas/config/tc-tic54x.c
gas/configure
gas/configure.ac
gas/expr.c
gas/macro.c
gas/output-file.c
gas/read.c
gas/stabs.c
gas/subsegs.c
gas/symbols.c

index f08c7c71d73d7ff322f9254714291f0953fdfcca..f33f6ec85cd7414b2c91096a0f34dd41a8b2c07d 100644 (file)
--- a/gas/as.c
+++ b/gas/as.c
@@ -1330,7 +1330,8 @@ gas_early_init (int *argcp, char ***argvp)
     as_fatal (_("libbfd ABI mismatch"));
 
   obstack_begin (&notes, chunksize);
-  xatexit (free_notes);
+  if (ENABLE_LEAK_CHECK)
+    xatexit (free_notes);
 
   myname = **argvp;
   xmalloc_set_program_name (myname);
index 1bfbee9a348e0182ba6ee642a213e2a9e884fdf8..ae5f41f7058c911d10b7e47f359ba8e271242d40 100644 (file)
@@ -73,6 +73,9 @@
 /* Define if you want run-time sanity checks. */
 #undef ENABLE_CHECKING
 
+/* Define if you want memory to be freed before exit. */
+#undef ENABLE_LEAK_CHECK
+
 /* Define to 1 if translation of program messages to the user's native
    language is requested. */
 #undef ENABLE_NLS
index a731c1f13007f06e9165c792f2a2ff52be4bb70a..02e474a2c2c25de2330a0316cbd7455e21c3f85a 100644 (file)
@@ -129,7 +129,8 @@ oav1_attr_info_init (void)
 void
 oav1_attr_info_exit (void)
 {
-  oav1_attr_info_free (recorded_attributes);
+  if (ENABLE_LEAK_CHECK)
+    oav1_attr_info_free (recorded_attributes);
 }
 
 /* Record that we have seen an explicit specification of attribute TAG
index e09be292cd1157f66d31832abfbec103ab1672eb..5c44aea0914831736560e28cc8a94f05910d1435 100644 (file)
@@ -3005,6 +3005,8 @@ elf_begin (void)
 void
 elf_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   while (section_stack)
     {
       struct section_stack *top = section_stack;
index d1a5f7e40c6a79a045fb2c894ff442c6c232b8e2..4e08b56329890d653a7eddeb161b5fd4ba89ede2 100644 (file)
@@ -2722,6 +2722,8 @@ md_begin (void)
 void
 arc_md_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   htab_delete (arc_opcode_hash);
   htab_delete (arc_reg_hash);
   htab_delete (arc_aux_hash);
index ca4523fe2cd00a23dcb889324f9c72d9979c3b54..edc44a37345af48ace57e4944c8f2e0d4de5b0a2 100644 (file)
@@ -3773,6 +3773,8 @@ i386_print_statistics (FILE *file)
 void
 i386_md_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   htab_delete (op_hash);
   htab_delete (reg_hash);
   GOT_symbol = NULL;
index cce8725485a092dbc1e229efb5c75181550f6626..716b2f15eea9ff86734ba1244e5ae13531481959 100644 (file)
@@ -529,7 +529,8 @@ md_begin ()
 void
 loongarch_md_end (void)
 {
-  htab_delete (align_hash);
+  if (ENABLE_LEAK_CHECK)
+    htab_delete (align_hash);
 }
 
 unsigned long
index a5dbc73386a4badd418ec8bc01024d610900a408..78e5941484cbcf6fc2d06026733e6005e08863e3 100644 (file)
@@ -1892,6 +1892,8 @@ md_begin (void)
 void
 ppc_md_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   if (ppc_hash)
     {
       htab_delete (ppc_hash);
index e55ce4790ba4d0f5feea282f206c35ee38336f0e..ee86511fafcdc54555375cb61333476b8a99e14c 100644 (file)
@@ -1796,6 +1796,8 @@ md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
 void
 pru_md_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   htab_delete (pru_opcode_hash);
   htab_delete (pru_reg_hash);
 }
index 6bcf53832a07bb0500bfb9a5571e1b9ed4ad0775..ef7c7e3a9a6e087ddeb9a89563a85feb9568fc61 100644 (file)
@@ -5782,7 +5782,8 @@ riscv_md_finish (void)
 void
 riscv_md_end (void)
 {
-  htab_delete (riscv_pcrel_hi_fixup_hash);
+  if (ENABLE_LEAK_CHECK)
+    htab_delete (riscv_pcrel_hi_fixup_hash);
 }
 
 /* Adjust the symbol table.  */
index c6af9bc1803f320eee28b0b6f87580f26dbeb739..7b3b0738a1f476aa180dca71a62248457b69303b 100644 (file)
@@ -3061,6 +3061,8 @@ md_begin (void)
 void
 tic54x_md_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   htab_delete (stag_hash);
   htab_delete (subsym_recurse_hash);
   while (macro_level != -1)
index e77c440d88035196bf55412e7b835ba42ebe1a86..eeace90f37548988da29d03a5fcb520295a995e3 100755 (executable)
@@ -816,6 +816,7 @@ enable_plugins
 enable_largefile
 enable_targets
 enable_checking
+enable_leak_check
 enable_compressed_debug_sections
 enable_default_compressed_debug_sections_algorithm
 enable_x86_tls_check
@@ -1488,6 +1489,7 @@ Optional Features:
   --disable-largefile     omit support for large files
   --enable-targets        alternative target configurations besides the primary
   --enable-checking       enable run-time checks
+  --enable-leak-check     enable freeing memory before exit
   --enable-compressed-debug-sections={all,gas,none}
                           compress debug sections by default
   --enable-default-compressed-debug-sections-algorithm={zlib,zstd}
@@ -11150,7 +11152,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11153 "configure"
+#line 11155 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11256,7 +11258,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11259 "configure"
+#line 11261 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11917,6 +11919,20 @@ $as_echo "#define ENABLE_CHECKING 1" >>confdefs.h
 
 fi
 
+ac_leak_check=BFD_ASAN
+# Check whether --enable-leak_check was given.
+if test "${enable_leak_check+set}" = set; then :
+  enableval=$enable_leak_check; case "${enableval}" in
+  no)  ac_leak_check=0 ;;
+  *)   ac_leak_check=1 ;;
+esac
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_LEAK_CHECK ${ac_leak_check}
+_ACEOF
+
+
 # PR gas/19109
 # Decide the default method for compressing debug sections.
 ac_default_compressed_debug_sections=unset
index 7fb573f8b219f62b8fb8ed8dc55e6c2bd09a4f28..69547f5ffb9b802568caf6850263c672696cd258 100644 (file)
@@ -62,6 +62,15 @@ if test x$ac_checking != x ; then
   AC_DEFINE(ENABLE_CHECKING, 1, [Define if you want run-time sanity checks.])
 fi
 
+ac_leak_check=BFD_ASAN
+AC_ARG_ENABLE(leak_check,
+[  --enable-leak-check     enable freeing memory before exit],
+[case "${enableval}" in
+  no)  ac_leak_check=0 ;;
+  *)   ac_leak_check=1 ;;
+esac])dnl
+AC_DEFINE_UNQUOTED(ENABLE_LEAK_CHECK, ${ac_leak_check}, [Define if you want memory to be freed before exit.])
+
 # PR gas/19109
 # Decide the default method for compressing debug sections.
 ac_default_compressed_debug_sections=unset
index c965486bf048d2bc0e78069ab25dc7dc26e81ae6..5b6828d391a7df2b2fab288a5173d3bdf2db3cca 100644 (file)
@@ -1640,8 +1640,9 @@ expr_begin (void)
 void
 expr_end (void)
 {
-  for (size_t i = 0; i < ARRAY_SIZE (seen); i++)
-    free (seen[i]);
+  if (ENABLE_LEAK_CHECK)
+    for (size_t i = 0; i < ARRAY_SIZE (seen); i++)
+      free (seen[i]);
 }
 \f
 /* Return the encoding for the operator at INPUT_LINE_POINTER, and
index 76989259feb61d333cbaa46afe87ff491a203a51..65992a7cbbc5ac00862ae8e5af8b489aa5f51420 100644 (file)
@@ -67,7 +67,8 @@ macro_init (void)
 void
 macro_end (void)
 {
-  htab_delete (macro_hash);
+  if (ENABLE_LEAK_CHECK)
+    htab_delete (macro_hash);
 }
 
 /* Read input lines till we get to a TO string.
index 5d5634b14624fc392975d5cc7c6ef6201413d3c3..6b04e77a6a7087e83b6ffa1f534c451422fc3b16 100644 (file)
@@ -81,18 +81,23 @@ output_file_close (void)
      which will call xexit() which may call this function again...  */
   stdoutput = NULL;
 
-  /* We can't free obstacks attached to the output bfd sections before
-     closing the output bfd since data in those obstacks may need to
-     be accessed, but we can't access anything in the output bfd after
-     it is closed..  */
-  for (sec = obfd->sections; sec; sec = sec->next)
-    stash_frchain_obs (sec);
-  stash_frchain_obs (reg_section);
-  stash_frchain_obs (expr_section);
-  stash_frchain_obs (bfd_abs_section_ptr);
-  stash_frchain_obs (bfd_und_section_ptr);
-  obstack_ptr_grow (&notes, NULL);
-  obs = obstack_finish (&notes);
+  if (ENABLE_LEAK_CHECK)
+    {
+      /* We can't free obstacks attached to the output bfd sections before
+        closing the output bfd since data in those obstacks may need to
+        be accessed, but we can't access anything in the output bfd after
+        it is closed..  */
+      for (sec = obfd->sections; sec; sec = sec->next)
+       stash_frchain_obs (sec);
+      stash_frchain_obs (reg_section);
+      stash_frchain_obs (expr_section);
+      stash_frchain_obs (bfd_abs_section_ptr);
+      stash_frchain_obs (bfd_und_section_ptr);
+      obstack_ptr_grow (&notes, NULL);
+      obs = obstack_finish (&notes);
+    }
+  else
+    obs = NULL;
 
   /* Close the bfd.  */
   if (!flag_always_generate_output && had_errors ())
index bac5bea544c00fb06343d50d9bc5d473175a35b3..7a0c73abc5c2a341c2da1f4ecb8c24a2b39399ca 100644 (file)
@@ -304,6 +304,8 @@ read_begin (void)
 void
 read_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   stabs_end ();
   poend ();
   _obstack_free (&cond_obstack, NULL);
@@ -621,7 +623,8 @@ pobegin (void)
 static void
 poend (void)
 {
-  htab_delete (po_hash);
+  if (ENABLE_LEAK_CHECK)
+    htab_delete (po_hash);
 }
 \f
 #define HANDLE_CONDITIONAL_ASSEMBLY(num_read)                          \
index c7797bc01e49b1afecfa451ce54d6ab0f781dc14..0233cc5e0185bc92202231cf40c0458ecee1524b 100644 (file)
@@ -673,6 +673,8 @@ stabs_begin (void)
 void
 stabs_end (void)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   free ((char *) current_function_label);
   free (last_asm_file);
   free (prev_line_file);
index 199fd869f219a2645ed56e8237f2e60eef18775a..eebd1113c07f98852ff80b1c68df461c3a8afd4e 100644 (file)
@@ -47,6 +47,8 @@ subsegs_begin (void)
 void
 subsegs_end (struct obstack **obs)
 {
+  if (!ENABLE_LEAK_CHECK)
+    return;
   for (; *obs; obs++)
     _obstack_free (*obs, NULL);
   _obstack_free (&frchains, NULL);
index 5ad5dbb2dd96bb6986322329e23e95a3775b2a37..5844439fd34a375696890f6717c1d5578a544499 100644 (file)
@@ -3150,7 +3150,8 @@ symbol_begin (void)
 void
 symbol_end (void)
 {
-  htab_delete (sy_hash);
+  if (ENABLE_LEAK_CHECK)
+    htab_delete (sy_hash);
 }
 
 void