[RFC 5/6] aarch64 gas: Record dynamic allocations during startup
Matthieu Longo
matthieu.longo@arm.com
Tue Mar 3 17:21:01 GMT 2026
On 03/03/2026 12:41, Alice Carlotti wrote:
> This allows them to be freed at exit, removing them from LeakSanitizer
> reports.
>
>
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index b580815bdfa20f358c818925b44f8bb2e2adba94..3dde65e3d91e346bd271189f11d119f78355a92d 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -10454,6 +10454,41 @@ aarch64_adjust_symtab (void)
> #endif
> }
>
> +struct aarch64_pointer_list
> +{
> + void *ptr;
> + struct aarch64_pointer_list *next;
> +};
> +
> +/* A linked list of dynamic memory allocations that are created once during
> + startup. These allocations can be freed when the assembler finishes, to
> + prevent them appearing in memory leak reports. */
> +
> +static struct
> +aarch64_pointer_list *aarch64_startup_allocations = NULL;
> +
> +static inline void
> +push_startup_allocation (void *ptr)
> +{
> + struct aarch64_pointer_list *head = XNEW (struct aarch64_pointer_list);
> + head->ptr = ptr;
> + head->next = aarch64_startup_allocations;
> + aarch64_startup_allocations = head;
> +}
> +
> +static void
> +free_startup_allocations (void)
> +{
> + struct aarch64_pointer_list *strings = aarch64_startup_allocations;
> + while (strings)
> + {
> + struct aarch64_pointer_list *next = strings->next;
> + free (strings->ptr);
> + free (strings);
> + strings = next;
> + }
> +}
> +
It might be preferable to use objalloc as discussed with Richard Earnshaw.
If you change the parameters of the htab as follows:
static struct objalloc *OBJ_ALLOC_HTABS = NULL;
/* at the top of md_begin() */
OBJ_ALLOC_HTABS = objalloc_create ();
/* helper for htab_malloc_parameter */
void *dyn_str_htab_alloc (unsigned long size)
{
return _objalloc_alloc (OBJ_ALLOC_HTABS, size);
}
/* Helper to create a htab */
static htab_t
dyn_str_htab_create (void)
{
return htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
NULL, dyn_str_hashtab_calloc, NULL);
}
Then, the freeing of the memory at md_end() can be simply summarized with:
objalloc_free (OBJ_ALLOC_HTABS);
This solution has the advantage of reusing available utilities.
The only drawback seems to be the replacement of all xstrdup() with your own implementation using _objalloc_alloc (). This cost seems acceptable.
> static void
> checked_hash_insert (htab_t table, const char *key, const void *value)
> {
> @@ -10478,6 +10513,7 @@ fill_instruction_hash_table (void)
> templ = str_hash_find (aarch64_ops_hsh, opcode->name);
>
> new_templ = XNEW (templates);
> + push_startup_allocation (new_templ);
> new_templ->opcode = opcode;
> new_templ->next = NULL;
>
> @@ -10503,7 +10539,7 @@ convert_to_upper (char *dst, const char *src, size_t num)
>
> /* Assume STR point to a lower-case string, allocate, convert and return
> the corresponding upper-case string. */
> -static inline const char*
> +static inline char*
> get_upper_str (const char *str)
> {
> char *ret;
> @@ -10513,6 +10549,20 @@ get_upper_str (const char *str)
> return ret;
> }
>
> +/* Some operands are recognised in either lower case or upper case forms.
> + Create entries for both versions. Record a pointer to the dynamically
> + allocated upper case string so that we can free it later. */
> +
> +static void
> +checked_hash_insert_with_upper (htab_t table, const char *key,
> + const void *value)
> +{
> + checked_hash_insert (table, key, value);
> + char *upper = get_upper_str (key);
> + checked_hash_insert (table, upper, value);
> + push_startup_allocation (upper);
> +}
> +
Ok for this refactoring.
> /* MD interface: Initialization. */
>
> void
> @@ -10608,11 +10658,8 @@ md_begin (void)
> for (i = 0; aarch64_operand_modifiers[i].name != NULL; i++)
> {
> const char *name = aarch64_operand_modifiers[i].name;
> - checked_hash_insert (aarch64_shift_hsh, name,
> - aarch64_operand_modifiers + i);
> - /* Also hash the name in the upper case. */
> - checked_hash_insert (aarch64_shift_hsh, get_upper_str (name),
> - aarch64_operand_modifiers + i);
> + checked_hash_insert_with_upper (aarch64_shift_hsh, name,
> + aarch64_operand_modifiers + i);
> }
>
> for (i = 0; i < ARRAY_SIZE (aarch64_conds); i++)
> @@ -10625,11 +10672,8 @@ md_begin (void)
> const char *name = aarch64_conds[i].names[j];
> if (name == NULL)
> break;
> - checked_hash_insert (aarch64_cond_hsh, name,
> - aarch64_conds + i);
> - /* Also hash the name in the upper case. */
> - checked_hash_insert (aarch64_cond_hsh, get_upper_str (name),
> - aarch64_conds + i);
> + checked_hash_insert_with_upper (aarch64_cond_hsh, name,
> + aarch64_conds + i);
> }
> }
>
> @@ -10639,21 +10683,15 @@ md_begin (void)
> /* Skip xx00 - the unallocated values of option. */
> if ((i & 0x3) == 0)
> continue;
> - checked_hash_insert (aarch64_barrier_opt_hsh, name,
> - aarch64_barrier_options + i);
> - /* Also hash the name in the upper case. */
> - checked_hash_insert (aarch64_barrier_opt_hsh, get_upper_str (name),
> - aarch64_barrier_options + i);
> + checked_hash_insert_with_upper (aarch64_barrier_opt_hsh, name,
> + aarch64_barrier_options + i);
> }
>
> for (i = 0; i < ARRAY_SIZE (aarch64_barrier_dsb_nxs_options); i++)
> {
> const char *name = aarch64_barrier_dsb_nxs_options[i].name;
> - checked_hash_insert (aarch64_barrier_opt_hsh, name,
> - aarch64_barrier_dsb_nxs_options + i);
> - /* Also hash the name in the upper case. */
> - checked_hash_insert (aarch64_barrier_opt_hsh, get_upper_str (name),
> - aarch64_barrier_dsb_nxs_options + i);
> + checked_hash_insert_with_upper (aarch64_barrier_opt_hsh, name,
> + aarch64_barrier_dsb_nxs_options + i);
> }
>
> for (i = 0; i < ARRAY_SIZE (aarch64_prfops); i++)
> @@ -10662,11 +10700,8 @@ md_begin (void)
> /* Skip the unallocated hint encodings. */
> if (name == NULL)
> continue;
> - checked_hash_insert (aarch64_pldop_hsh, name,
> - aarch64_prfops + i);
> - /* Also hash the name in the upper case. */
> - checked_hash_insert (aarch64_pldop_hsh, get_upper_str (name),
> - aarch64_prfops + i);
> + checked_hash_insert_with_upper (aarch64_pldop_hsh, name,
> + aarch64_prfops + i);
> }
>
> for (i = 0; aarch64_hint_options[i].name != NULL; i++)
> @@ -10676,11 +10711,8 @@ md_begin (void)
> up in the hash table. */
> if (*name == '\0')
> continue;
> - checked_hash_insert (aarch64_hint_opt_hsh, name,
> - aarch64_hint_options + i);
> - /* Also hash the name in the upper case. */
> - checked_hash_insert (aarch64_hint_opt_hsh, get_upper_str (name),
> - aarch64_hint_options + i);
> + checked_hash_insert_with_upper (aarch64_hint_opt_hsh, name,
> + aarch64_hint_options + i);
> }
>
> for (i = 0; aarch64_sys_ins_gic[i].name != NULL; i++)
> @@ -10745,6 +10777,8 @@ aarch64_md_end (void)
> htab_delete (aarch64_barrier_opt_hsh);
> htab_delete (aarch64_pldop_hsh);
> htab_delete (aarch64_hint_opt_hsh);
> +
> + free_startup_allocations();
> }
>
> /* Command line processing. */
Matthieu
More information about the Binutils
mailing list