aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2025-02-13 08:25:01 +1030
committerAlan Modra <amodra@gmail.com>2025-02-14 08:26:42 +1030
commitd1c34b3c05760afac3fbf6b1dd7c7b7a0732275c (patch)
treecbbaf0e6bd04ff66db191269316abe060845246c
parent27c6f1271bacc44552f612ce8a801d725dabb6cf (diff)
downloadbinutils-d1c34b3c05760afac3fbf6b1dd7c7b7a0732275c.zip
binutils-d1c34b3c05760afac3fbf6b1dd7c7b7a0732275c.tar.gz
binutils-d1c34b3c05760afac3fbf6b1dd7c7b7a0732275c.tar.bz2
gas obj-coff memory leaks
This patch addresses memory leaks in gas that show up when running the testsuite on x86_64-w64-mingw32. The seh_ctx_cur, and weak sym naming leaks can occur many times during assembly. The symbol hook and section leaks are not so important since this memory needs to persist until closing the output bfd. * config/obj-coff-seh.c (do_seh_endproc): Free seh_ctx_cur and its fields. * config/obj-coff-seh.h (struct seh_context): Remove unused "next" field. * config/obj-coff.c (coff_obj_symbol_new_hook): Use notes_alloc for aux entries. (coff_obj_symbol_clone_hook): Likewise. (obj_coff_def): Don't strdup name unless we need to do so for tc_canonicalize_symbol_name. Free after making symbol. (weak_name2altname, weak_altname2name): Return a char*. (weak_uniquify): Use notes_concat. (pecoff_obj_set_weak_hook, pecoff_obj_clear_weak_hook): Free name returned by weak_name2altname. (coff_frob_symbol): Similarly for weak_altname2name. (obj_coff_section): Use notes_memdup0. * symbols.h: Add include guard. (notes_memdup0): New inline function.
-rw-r--r--gas/config/obj-coff-seh.c3
-rw-r--r--gas/config/obj-coff-seh.h2
-rw-r--r--gas/config/obj-coff.c49
-rw-r--r--gas/symbols.h11
4 files changed, 40 insertions, 25 deletions
diff --git a/gas/config/obj-coff-seh.c b/gas/config/obj-coff-seh.c
index adb2f97..70cb4e4 100644
--- a/gas/config/obj-coff-seh.c
+++ b/gas/config/obj-coff-seh.c
@@ -417,6 +417,9 @@ do_seh_endproc (void)
write_function_xdata (seh_ctx_cur);
write_function_pdata (seh_ctx_cur);
+ free (seh_ctx_cur->elems);
+ free (seh_ctx_cur->func_name);
+ free (seh_ctx_cur);
seh_ctx_cur = NULL;
}
diff --git a/gas/config/obj-coff-seh.h b/gas/config/obj-coff-seh.h
index e1f7bb6..598870a 100644
--- a/gas/config/obj-coff-seh.h
+++ b/gas/config/obj-coff-seh.h
@@ -89,8 +89,6 @@ typedef struct seh_prologue_element
typedef struct seh_context
{
- struct seh_context *next;
-
/* Initial code-segment. */
segT code_seg;
/* Function name. */
diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
index 941e80d..6072af6 100644
--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -368,8 +368,8 @@ static symbolS *line_fsym;
void
coff_obj_symbol_new_hook (symbolS *symbolP)
{
- long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
- char * s = XNEWVEC (char, sz);
+ size_t sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
+ char *s = notes_alloc (sz);
memset (s, 0, sz);
coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s;
@@ -389,11 +389,10 @@ coff_obj_symbol_new_hook (symbolS *symbolP)
void
coff_obj_symbol_clone_hook (symbolS *newsymP, symbolS *orgsymP)
{
- long elts = OBJ_COFF_MAX_AUXENTRIES + 1;
- combined_entry_type * s = XNEWVEC (combined_entry_type, elts);
+ size_t sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
+ combined_entry_type *s = notes_alloc (sz);
- memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native,
- elts * sizeof (combined_entry_type));
+ memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native, sz);
coffsymbol (symbol_get_bfdsym (newsymP))->native = s;
SF_SET (newsymP, SF_GET (orgsymP));
@@ -573,10 +572,6 @@ obj_coff_ident (int ignore ATTRIBUTE_UNUSED)
static void
obj_coff_def (int what ATTRIBUTE_UNUSED)
{
- char name_end; /* Char after the end of name. */
- char *symbol_name; /* Name of the debug symbol. */
- char *symbol_name_copy; /* Temporary copy of the name. */
-
if (def_symbol_in_progress != NULL)
{
as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
@@ -586,14 +581,18 @@ obj_coff_def (int what ATTRIBUTE_UNUSED)
SKIP_WHITESPACES ();
- name_end = get_symbol_name (&symbol_name);
- symbol_name_copy = xstrdup (symbol_name);
+ char *symbol_name;
+ char name_end = get_symbol_name (&symbol_name);
+ char *symbol_name_copy = NULL;
+ char *canon_name = symbol_name;
#ifdef tc_canonicalize_symbol_name
- symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
+ symbol_name_copy = xstrdup (symbol_name);
+ canon_name = tc_canonicalize_symbol_name (symbol_name_copy);
#endif
/* Initialize the new symbol. */
- def_symbol_in_progress = symbol_make (symbol_name_copy);
+ def_symbol_in_progress = symbol_make (canon_name);
+ free (symbol_name_copy);
symbol_set_frag (def_symbol_in_progress, &zero_address_frag);
S_SET_VALUE (def_symbol_in_progress, 0);
@@ -1060,7 +1059,7 @@ weak_is_altname (const char * name)
/* Return the name of the alternate symbol
name corresponding to a weak symbol's name. */
-static const char *
+static char *
weak_name2altname (const char * name)
{
return concat (weak_altprefix, name, (char *) NULL);
@@ -1069,7 +1068,7 @@ weak_name2altname (const char * name)
/* Return the name of the weak symbol corresponding to an
alternate symbol. */
-static const char *
+static char *
weak_altname2name (const char * name)
{
gas_assert (weak_is_altname (name));
@@ -1090,7 +1089,7 @@ weak_uniquify (const char * name)
#endif
gas_assert (weak_is_altname (name));
- return concat (name, ".", unique, (char *) NULL);
+ return notes_concat (name, ".", unique, (char *) NULL);
}
void
@@ -1107,7 +1106,9 @@ pecoff_obj_set_weak_hook (symbolS *symbolP)
S_SET_NUMBER_AUXILIARY (symbolP, 1);
SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY);
- alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP)));
+ char *altname = weak_name2altname (S_GET_NAME (symbolP));
+ alternateP = symbol_find_or_make (altname);
+ free (altname);
S_SET_EXTERNAL (alternateP);
S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
@@ -1122,7 +1123,9 @@ pecoff_obj_clear_weak_hook (symbolS *symbolP)
S_SET_STORAGE_CLASS (symbolP, 0);
SA_SET_SYM_FSIZE (symbolP, 0);
- alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP)));
+ char *altname = weak_name2altname (S_GET_NAME (symbolP));
+ alternateP = symbol_find (altname);
+ free (altname);
S_CLEAR_EXTERNAL (alternateP);
}
@@ -1216,9 +1219,9 @@ coff_frob_symbol (symbolS *symp, int *punt)
{
/* This is a weak alternate symbol. All processing of
PECOFFweak symbols is done here, through the alternate. */
- symbolS *weakp = symbol_find_noref (weak_altname2name
- (S_GET_NAME (symp)), 1);
-
+ char *weakname = weak_altname2name (S_GET_NAME (symp));
+ symbolS *weakp = symbol_find_noref (weakname, 1);
+ free (weakname);
gas_assert (weakp);
gas_assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
@@ -1554,7 +1557,7 @@ obj_coff_section (int ignore ATTRIBUTE_UNUSED)
}
c = get_symbol_name (&section_name);
- name = xmemdup0 (section_name, input_line_pointer - section_name);
+ name = notes_memdup0 (section_name, input_line_pointer - section_name);
restore_line_pointer (c);
SKIP_WHITESPACE ();
diff --git a/gas/symbols.h b/gas/symbols.h
index 465a1ab..7524e2f 100644
--- a/gas/symbols.h
+++ b/gas/symbols.h
@@ -18,6 +18,9 @@
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
+#ifndef GAS_SYMBOLS_H
+#define GAS_SYMBOLS_H
+
extern struct obstack notes; /* eg FixS live here. */
extern struct obstack cond_obstack; /* this is where we track .ifdef/.endif
@@ -42,6 +45,12 @@ extern char *notes_strdup (const char *);
extern char *notes_concat (const char *, ...);
extern void notes_free (void *);
+static inline char *
+notes_memdup0 (const char *in, size_t len)
+{
+ return notes_memdup (in, len, len + 1);
+}
+
char * symbol_relc_make_expr (expressionS *);
char * symbol_relc_make_sym (symbolS *);
char * symbol_relc_make_value (offsetT);
@@ -228,3 +237,5 @@ void symbol_set_obj (symbolS *, OBJ_SYMFIELD_TYPE *);
TC_SYMFIELD_TYPE *symbol_get_tc (symbolS *);
void symbol_set_tc (symbolS *, TC_SYMFIELD_TYPE *);
#endif
+
+#endif /* GAS_SYMBOLS_H */