[binutils-gdb] gas: only free on exit when --enable-leak-check
Alan Modra via Binutils-cvs <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=eced22e46896200bd76d6ec95eb35a7a1396eb01 commit eced22e46896200bd76d6ec95eb35a7a1396eb01 Author: Alan Modra <[email protected]> Date: Thu Mar 5 09:15:04 2026 +1030 gas: only free on exit when --enable-leak-check 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. Diff: --- gas/as.c | 3 ++- gas/config.in | 3 +++ gas/config/obj-elf-attr.c | 3 ++- gas/config/obj-elf.c | 2 ++ gas/config/tc-arc.c | 2 ++ gas/config/tc-i386.c | 2 ++ gas/config/tc-loongarch.c | 3 ++- gas/config/tc-ppc.c | 2 ++ gas/config/tc-pru.c | 2 ++ gas/config/tc-riscv.c | 3 ++- gas/config/tc-tic54x.c | 2 ++ gas/configure | 20 ++++++++++++++++++-- gas/configure.ac | 9 +++++++++ gas/expr.c | 5 +++-- gas/macro.c | 3 ++- gas/output-file.c | 29 +++++++++++++++++------------ gas/read.c | 5 ++++- gas/stabs.c | 2 ++ gas/subsegs.c | 2 ++ gas/symbols.c | 3 ++- 20 files changed, 82 insertions(+), 23 deletions(-) diff --git a/gas/as.c b/gas/as.c index f08c7c71d73..f33f6ec85cd 100644 --- 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 (¬es, chunksize); - xatexit (free_notes); + if (ENABLE_LEAK_CHECK) + xatexit (free_notes); myname = **argvp; xmalloc_set_program_name (myname); diff --git a/gas/config.in b/gas/config.in index 1bfbee9a348..ae5f41f7058 100644 --- a/gas/config.in +++ b/gas/config.in @@ -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 diff --git a/gas/config/obj-elf-attr.c b/gas/config/obj-elf-attr.c index a731c1f1300..02e474a2c2c 100644 --- a/gas/config/obj-elf-attr.c +++ b/gas/config/obj-elf-attr.c @@ -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 diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index e09be292cd1..5c44aea0914 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -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; diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c index d1a5f7e40c6..4e08b563298 100644 --- a/gas/config/tc-arc.c +++ b/gas/config/tc-arc.c @@ -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); diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index ca4523fe2cd..edc44a37345 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -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; diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c index cce8725485a..716b2f15eea 100644 --- a/gas/config/tc-loongarch.c +++ b/gas/config/tc-loongarch.c @@ -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 diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index a5dbc73386a..78e5941484c 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -1892,6 +1892,8 @@ md_begin (void) void ppc_md_end (void) { + if (!ENABLE_LEAK_CHECK) + return; if (ppc_hash) { htab_delete (ppc_hash); diff --git a/gas/config/tc-pru.c b/gas/config/tc-pru.c index e55ce4790ba..ee86511fafc 100644 --- a/gas/config/tc-pru.c +++ b/gas/config/tc-pru.c @@ -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); } diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 6bcf53832a0..ef7c7e3a9a6 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -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. */ diff --git a/gas/config/tc-tic54x.c b/gas/config/tc-tic54x.c index c6af9bc1803..7b3b0738a1f 100644 --- a/gas/config/tc-tic54x.c +++ b/gas/config/tc-tic54x.c @@ -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) diff --git a/gas/configure b/gas/configure index e77c440d880..eeace90f375 100755 --- a/gas/configure +++ b/gas/configure @@ -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 diff --git a/gas/configure.ac b/gas/configure.ac index 7fb573f8b21..69547f5ffb9 100644 --- a/gas/configure.ac +++ b/gas/configure.ac @@ -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 diff --git a/gas/expr.c b/gas/expr.c index c965486bf04..5b6828d391a 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -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]); } /* Return the encoding for the operator at INPUT_LINE_POINTER, and diff --git a/gas/macro.c b/gas/macro.c index 76989259feb..65992a7cbbc 100644 --- a/gas/macro.c +++ b/gas/macro.c @@ -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. diff --git a/gas/output-file.c b/gas/output-file.c index 5d5634b1462..6b04e77a6a7 100644 --- a/gas/output-file.c +++ b/gas/output-file.c @@ -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 (¬es, NULL); - obs = obstack_finish (¬es); + 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 (¬es, NULL); + obs = obstack_finish (¬es); + } + else + obs = NULL; /* Close the bfd. */ if (!flag_always_generate_output && had_errors ()) diff --git a/gas/read.c b/gas/read.c index bac5bea544c..7a0c73abc5c 100644 --- a/gas/read.c +++ b/gas/read.c @@ -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); } #define HANDLE_CONDITIONAL_ASSEMBLY(num_read) \ diff --git a/gas/stabs.c b/gas/stabs.c index c7797bc01e4..0233cc5e018 100644 --- a/gas/stabs.c +++ b/gas/stabs.c @@ -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); diff --git a/gas/subsegs.c b/gas/subsegs.c index 199fd869f21..eebd1113c07 100644 --- a/gas/subsegs.c +++ b/gas/subsegs.c @@ -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); diff --git a/gas/symbols.c b/gas/symbols.c index 5ad5dbb2dd9..5844439fd34 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -3150,7 +3150,8 @@ symbol_begin (void) void symbol_end (void) { - htab_delete (sy_hash); + if (ENABLE_LEAK_CHECK) + htab_delete (sy_hash); } void