ld plugin.c concat leaks

* ldlang.c: Whitespace.
	(stat_free, stat_concat): New functions.
	* ldlang.h (stat_free, stat_concat): Declare.
	* plugin.c (asymbol_from_plugin_symbol): Use stat_concat.
This commit is contained in:
Alan Modra
2025-01-23 10:22:58 +10:30
parent 40c7f80788
commit 90bea4932e
3 changed files with 74 additions and 38 deletions

View File

@@ -188,6 +188,12 @@ stat_alloc (size_t size)
return obstack_alloc (&stat_obstack, size); return obstack_alloc (&stat_obstack, size);
} }
void
stat_free (void *str)
{
obstack_free (&stat_obstack, str);
}
void * void *
stat_memdup (const void *src, size_t copy_size, size_t alloc_size) stat_memdup (const void *src, size_t copy_size, size_t alloc_size)
{ {
@@ -205,6 +211,31 @@ stat_strdup (const char *str)
return stat_memdup (str, len, len); return stat_memdup (str, len, len);
} }
char *
stat_concat (const char *first, ...)
{
va_list args;
va_start (args, first);
size_t length = 0;
for (const char *arg = first; arg; arg = va_arg (args, const char *))
length += strlen (arg);
va_end (args);
char *new_str = stat_alloc (length + 1);
va_start (args, first);
char *end = new_str;
for (const char *arg = first; arg; arg = va_arg (args, const char *))
{
length = strlen (arg);
memcpy (end, arg, length);
end += length;
}
*end = 0;
va_end (args);
return new_str;
}
/* Code for handling simple wildcards without going through fnmatch, /* Code for handling simple wildcards without going through fnmatch,
which can be expensive because of charset translations etc. */ which can be expensive because of charset translations etc. */
@@ -648,7 +679,7 @@ wild_sort (lang_wild_statement_type *wild,
|| sec->spec.sorted == by_none)) || sec->spec.sorted == by_none))
{ {
/* We might be called even if _this_ spec doesn't need sorting, /* We might be called even if _this_ spec doesn't need sorting,
in which case we simply append at the right end of tree. */ in which case we simply append at the right end of tree. */
return wild->rightmost; return wild->rightmost;
} }
@@ -703,7 +734,7 @@ wild_sort (lang_wild_statement_type *wild,
i = filename_cmp (ln, fn); i = filename_cmp (ln, fn);
else else
i = filename_cmp (fn, ln); i = filename_cmp (fn, ln);
if (i > 0) if (i > 0)
{ tree = &((*tree)->right); continue; } { tree = &((*tree)->right); continue; }
else if (i < 0) else if (i < 0)
@@ -1233,9 +1264,9 @@ new_afile (const char *name,
p->filename = name; p->filename = name;
p->local_sym_name = name; p->local_sym_name = name;
/* If name is a relative path, search the directory of the current linker /* If name is a relative path, search the directory of the current linker
script first. */ script first. */
if (from_filename && !IS_ABSOLUTE_PATH (name)) if (from_filename && !IS_ABSOLUTE_PATH (name))
p->extra_search_path = ldirname (from_filename); p->extra_search_path = ldirname (from_filename);
p->flags.real = true; p->flags.real = true;
p->flags.search_dirs = true; p->flags.search_dirs = true;
break; break;
@@ -2147,7 +2178,7 @@ lang_insert_orphan (asection *s,
else if (first_orphan_note) else if (first_orphan_note)
{ {
/* Don't place non-note sections in the middle of orphan /* Don't place non-note sections in the middle of orphan
note sections. */ note sections. */
after_sec_note = true; after_sec_note = true;
after_sec = as; after_sec = as;
for (sec = as->next; for (sec = as->next;
@@ -4959,18 +4990,18 @@ ld_is_local_symbol (asymbol * sym)
/* FIXME: This is intended to skip ARM mapping symbols, /* FIXME: This is intended to skip ARM mapping symbols,
which for some reason are not excluded by bfd_is_local_label, which for some reason are not excluded by bfd_is_local_label,
but maybe it is wrong for other architectures. but maybe it is wrong for other architectures.
It would be better to fix bfd_is_local_label. */ It would be better to fix bfd_is_local_label. */
if (*name == '$') if (*name == '$')
return false; return false;
/* Some local symbols, eg _GLOBAL_OFFSET_TABLE_, are present /* Some local symbols, eg _GLOBAL_OFFSET_TABLE_, are present
in the hash table, so do not print duplicates here. */ in the hash table, so do not print duplicates here. */
struct bfd_link_hash_entry * h; struct bfd_link_hash_entry * h;
h = bfd_link_hash_lookup (link_info.hash, name, false /* create */, h = bfd_link_hash_lookup (link_info.hash, name, false /* create */,
false /* copy */, true /* follow */); false /* copy */, true /* follow */);
if (h == NULL) if (h == NULL)
return true; return true;
/* Symbols from the plugin owned BFD will not get their own /* Symbols from the plugin owned BFD will not get their own
iteration of this function, but can be on the link_info iteration of this function, but can be on the link_info
list. So include them here. */ list. So include them here. */
@@ -5060,7 +5091,7 @@ print_input_section (asection *i, bool is_discarded)
{ {
asymbol * sym = symbol_table[j]; asymbol * sym = symbol_table[j];
bfd_vma sym_addr = sym->value + i->output_section->vma; bfd_vma sym_addr = sym->value + i->output_section->vma;
if (sym->section == i->output_section if (sym->section == i->output_section
&& (sym->flags & BSF_LOCAL) != 0 && (sym->flags & BSF_LOCAL) != 0
&& sym_addr >= addr && sym_addr >= addr
@@ -5536,9 +5567,9 @@ size_input_section
then to the output section's requirement. If this alignment then to the output section's requirement. If this alignment
is greater than any seen before, then record it too. Perform is greater than any seen before, then record it too. Perform
the alignment by inserting a magic 'padding' statement. the alignment by inserting a magic 'padding' statement.
We can force input section alignment within an output section We can force input section alignment within an output section
by using SUBALIGN. The value specified overrides any alignment by using SUBALIGN. The value specified overrides any alignment
given by input sections, whether larger or smaller. */ given by input sections, whether larger or smaller. */
if (output_section_statement->subsection_alignment != NULL) if (output_section_statement->subsection_alignment != NULL)
o->alignment_power = i->alignment_power = o->alignment_power = i->alignment_power =
@@ -8788,7 +8819,7 @@ lang_add_string (const char *s)
case 'n': c = '\n'; break; case 'n': c = '\n'; break;
case 'r': c = '\r'; break; case 'r': c = '\r'; break;
case 't': c = '\t'; break; case 't': c = '\t'; break;
case '0': case '0':
case '1': case '1':
case '2': case '2':
@@ -9898,30 +9929,30 @@ lang_do_memory_regions (bool update_regions_p)
if (r->origin_exp) if (r->origin_exp)
{ {
exp_fold_tree_no_dot (r->origin_exp, NULL); exp_fold_tree_no_dot (r->origin_exp, NULL);
if (update_regions_p) if (update_regions_p)
{ {
if (expld.result.valid_p) if (expld.result.valid_p)
{ {
r->origin = expld.result.value; r->origin = expld.result.value;
r->current = r->origin; r->current = r->origin;
} }
else else
einfo (_("%P: invalid origin for memory region %s\n"), einfo (_("%P: invalid origin for memory region %s\n"),
r->name_list.name); r->name_list.name);
} }
} }
if (r->length_exp) if (r->length_exp)
{ {
exp_fold_tree_no_dot (r->length_exp, NULL); exp_fold_tree_no_dot (r->length_exp, NULL);
if (update_regions_p) if (update_regions_p)
{ {
if (expld.result.valid_p) if (expld.result.valid_p)
r->length = expld.result.value; r->length = expld.result.value;
else else
einfo (_("%P: invalid length for memory region %s\n"), einfo (_("%P: invalid length for memory region %s\n"),
r->name_list.name); r->name_list.name);
} }
} }
} }
} }

View File

@@ -664,10 +664,14 @@ extern void lang_for_each_statement_worker
(void (*) (lang_statement_union_type *), lang_statement_union_type *); (void (*) (lang_statement_union_type *), lang_statement_union_type *);
extern void *stat_alloc extern void *stat_alloc
(size_t); (size_t);
extern void * stat_memdup extern void stat_free
(void *);
extern void *stat_memdup
(const void *, size_t, size_t); (const void *, size_t, size_t);
extern char *stat_strdup extern char *stat_strdup
(const char *); (const char *);
extern char *stat_concat
(const char *, ...);
extern void strip_excluded_output_sections extern void strip_excluded_output_sections
(void); (void);
extern void lang_clear_os_map extern void lang_clear_os_map

View File

@@ -366,7 +366,8 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
asym->the_bfd = abfd; asym->the_bfd = abfd;
asym->name = (ldsym->version asym->name = (ldsym->version
? concat (ldsym->name, "@", ldsym->version, (const char *) NULL) ? stat_concat (ldsym->name, "@", ldsym->version,
(const char *) NULL)
: ldsym->name); : ldsym->name);
asym->value = 0; asym->value = 0;
switch (ldsym->def) switch (ldsym->def)
@@ -378,11 +379,11 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
flags |= BSF_GLOBAL; flags |= BSF_GLOBAL;
if (ldsym->comdat_key) if (ldsym->comdat_key)
{ {
char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key, char *name = stat_concat (".gnu.linkonce.t.", ldsym->comdat_key,
(const char *) NULL); (const char *) NULL);
section = bfd_get_section_by_name (abfd, name); section = bfd_get_section_by_name (abfd, name);
if (section != NULL) if (section != NULL)
free (name); stat_free (name);
else else
{ {
flagword sflags; flagword sflags;