[PATCH v4 1/1] malloc: aarch64: Add ifuncs for malloc functions

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed Jun 3 13:46:16 GMT 2026



On 01/06/26 07:30, Yury Khrustalev wrote:
> Introduce ifuncs and resolvers for functions pertinent to the
> malloc interface on the AArch64 target: malloc, calloc, free,
> realloc, memalign, valloc, pvalloc, posix_memalign, aligned_alloc,
> free_sized, free_aligned_sized, malloc_usable_size.
> 
> A target can define the USE_MULTIARCH_MALLOC macro. In this case
> it must provide alternative aliases for the malloc functions that
> point to the ifuncs.
> 
> This implementation respects the --disable-multi-arch configure
> flag. If multi-arch support is disabled, the generic aliases
> are used on aarch64.
> 
> This patch contains aarch64-specific resolvers. At this moment they
> return core implementations but in the future they can be changed
> to support for features, e.g. to handle memory tagging.

The patch looks ok, some comments below. I think the only missing piece 
is to check if external malloc-intercepting tools like valgrind, ASan/TSan, 
heap profilers, and gdb's inferior call malloc(...) handle the ifunc change
(as we discussed on the weekly call).

> ---
>  malloc/malloc-internal.h                  |  3 +
>  malloc/malloc.c                           | 42 +++++++++++--
>  sysdeps/aarch64/multiarch/Makefile        | 10 +++-
>  sysdeps/aarch64/multiarch/malloc-ifuncs.c | 73 +++++++++++++++++++++++
>  sysdeps/aarch64/multiarch/malloc-ifuncs.h | 61 +++++++++++++++++++
>  sysdeps/generic/malloc-ifuncs.h           | 37 ++++++++++++
>  6 files changed, 218 insertions(+), 8 deletions(-)
>  create mode 100644 sysdeps/aarch64/multiarch/malloc-ifuncs.c
>  create mode 100644 sysdeps/aarch64/multiarch/malloc-ifuncs.h
>  create mode 100644 sysdeps/generic/malloc-ifuncs.h
> 
> diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
> index a6340bfd88..04ebe93ad8 100644
> --- a/malloc/malloc-internal.h
> +++ b/malloc/malloc-internal.h
> @@ -24,6 +24,9 @@
>  #include <malloc-size.h>
>  #include <hugepages.h>
>  #include <calloc-clear-memory.h>
> +#if defined(USE_MULTIARCH)
> +# include <malloc-ifuncs.h>
> +#endif
>  
>  /* Called in the parent process before a fork.  */
>  void __malloc_fork_lock_parent (void) attribute_hidden;
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 18fe48e001..674daa1dd5 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -499,6 +499,7 @@ libc_hidden_proto (__libc_free)
>    set to zero.
>  */
>  void*  __libc_calloc(size_t, size_t);
> +libc_hidden_proto (__libc_calloc)
>  
>  /*
>    realloc(void* p, size_t n)
> @@ -551,6 +552,7 @@ libc_hidden_proto (__libc_memalign)
>    size of the system. If the pagesize is unknown, 4096 is used.
>  */
>  void*  __libc_valloc(size_t);
> +libc_hidden_proto (__libc_valloc)
>  
>  
>  
> @@ -585,6 +587,7 @@ struct mallinfo __libc_mallinfo(void);
>    round up n to nearest pagesize.
>   */
>  void*  __libc_pvalloc(size_t);
> +libc_hidden_proto (__libc_pvalloc)
>  
>  /*
>    malloc_trim(size_t pad);
> @@ -628,6 +631,7 @@ int      __malloc_trim(size_t);
>  
>  */
>  size_t   __malloc_usable_size(void*);
> +libc_hidden_proto (__malloc_usable_size)
>  
>  /*
>    malloc_stats();
> @@ -657,6 +661,7 @@ void     __malloc_stats(void);
>    POSIX wrapper like memalign(), checking for validity of size.
>  */
>  int      __posix_memalign(void **, size_t, size_t);
> +libc_hidden_proto (__posix_memalign)
>  #endif /* IS_IN (libc) */
>  
>  /*
> @@ -3320,8 +3325,11 @@ libc_hidden_def (__libc_memalign)
>  
>  /* For ISO C17.  */
>  void *
> -weak_function
> -aligned_alloc (size_t alignment, size_t bytes)
> +__aligned_alloc (size_t alignment, size_t bytes);
> +libc_hidden_proto (__aligned_alloc)
> +
> +void *
> +__aligned_alloc (size_t alignment, size_t bytes)
>  {
>  /* Starting with ISO C17 the standard requires an error for alignments
>     that are not supported.  Only integral powers of 2 are valid.  */
> @@ -3333,11 +3341,15 @@ aligned_alloc (size_t alignment, size_t bytes)
>  
>    return _mid_memalign (alignment, bytes);
>  }
> +libc_hidden_def (__aligned_alloc)
>  
>  /* For ISO C23.  */
>  void
> -weak_function
> -free_sized (void *ptr, __attribute_maybe_unused__ size_t size)
> +__free_sized (void *ptr, __attribute_maybe_unused__ size_t size);
> +libc_hidden_proto (__free_sized)
> +
> +void
> +__free_sized (void *ptr, __attribute_maybe_unused__ size_t size)
>  {
>    /* We do not perform validation that size is the same as the original
>       requested size at this time. We leave that to the sanitizers.  We
> @@ -3346,11 +3358,16 @@ free_sized (void *ptr, __attribute_maybe_unused__ size_t size)
>  
>    free (ptr);
>  }
> +libc_hidden_def (__free_sized)
>  
>  /* For ISO C23.  */
>  void
> -weak_function
> -free_aligned_sized (void *ptr, __attribute_maybe_unused__ size_t alignment,
> +__free_aligned_sized (void *ptr, __attribute_maybe_unused__ size_t alignment,
> +                    __attribute_maybe_unused__ size_t size);
> +libc_hidden_proto (__free_aligned_sized)
> +
> +void
> +__free_aligned_sized (void *ptr, __attribute_maybe_unused__ size_t alignment,
>                      __attribute_maybe_unused__ size_t size)
>  {
>    /* We do not perform validation that size and alignment is the same as
> @@ -3360,6 +3377,7 @@ free_aligned_sized (void *ptr, __attribute_maybe_unused__ size_t alignment,
>  
>    free (ptr);
>  }
> +libc_hidden_def (__free_aligned_sized)
>  
>  static void *
>  _mid_memalign (size_t alignment, size_t bytes)
> @@ -3408,6 +3426,7 @@ __libc_valloc (size_t bytes)
>  {
>    return _mid_memalign (GLRO (dl_pagesize), bytes);
>  }
> +libc_hidden_def (__libc_valloc)
>  
>  void *
>  __libc_pvalloc (size_t bytes)
> @@ -3425,6 +3444,7 @@ __libc_pvalloc (size_t bytes)
>  
>    return _mid_memalign (pagesize, rounded_bytes & -pagesize);
>  }
> +libc_hidden_def (__libc_pvalloc)
>  
>  static void * __attribute_noinline__
>  __libc_calloc2 (size_t sz)
> @@ -3551,6 +3571,7 @@ __libc_calloc (size_t n, size_t elem_size)
>  #endif
>    return __libc_calloc2 (bytes);
>  }
> +libc_hidden_def (__libc_calloc)
>  #endif /* IS_IN (libc) */
>  
>  /*
> @@ -4547,6 +4568,7 @@ __malloc_usable_size (void *m)
>      return 0;
>    return musable (m);
>  }
> +libc_hidden_def (__malloc_usable_size)
>  #endif /* IS_IN (libc) */
>  
>  /*
> @@ -5074,6 +5096,7 @@ __posix_memalign (void **memptr, size_t alignment, size_t size)
>    *memptr = mem;
>    return 0;
>  }
> +libc_hidden_def (__posix_memalign)
>  #endif /* IS_IN (libc) */
>  
>  
> @@ -5236,6 +5259,9 @@ __malloc_info (int options, FILE *fp)
>  }
>  
>  #if IS_IN (libc)
> +
> +/* See sysdeps/generic/malloc-ifuncs.h for details.  */
> +# if !defined (USE_MULTIARCH_MALLOC)
>  strong_alias (__libc_malloc, malloc)
>  strong_alias (__libc_realloc, realloc)
>  strong_alias (__libc_free, free)
> @@ -5245,6 +5271,10 @@ weak_alias (__posix_memalign, posix_memalign)
>  weak_alias (__libc_valloc, valloc)
>  weak_alias (__libc_pvalloc, pvalloc)
>  weak_alias (__malloc_usable_size, malloc_usable_size)
> +weak_alias (__aligned_alloc, aligned_alloc)
> +weak_alias (__free_sized, free_sized)
> +weak_alias (__free_aligned_sized, free_aligned_sized)
> +#endif /* !USE_MULTIARCH_MALLOC */
>  
>  weak_alias (__malloc_info, malloc_info)
>  weak_alias (__libc_mallinfo, mallinfo)

We discussed this privately; the cfree bypasses the redirect: compat_symbol (..., cfree, GLIBC_2_0)
is kept outside the USE_MULTIARCH_MALLOC guard.

It does not matter for this patch, because aarch64 does not support multiple, 
potentially incompatible malloc implementations.

But it might become an issue (though highly unlikely, since cfree will be present 
only in older binaries). Maybe add a route it through __libc_free_redirect too.

> diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
> index 38952655b1..a8a03a0491 100644
> --- a/sysdeps/aarch64/multiarch/Makefile
> +++ b/sysdeps/aarch64/multiarch/Makefile
> @@ -18,5 +18,11 @@ sysdep_routines += \
>    memset_zva64 \
>    strlen_asimd \
>    strlen_generic \
> -# sysdep_routines
> -endif
> +  # sysdep_routines
> +endif # ifeq ($(subdir),string)
> +
> +ifeq ($(subdir),malloc)
> +sysdep_routines += \
> +  malloc-ifuncs \
> +  # sysdep_routines
> +endif # ifeq ($(subdir),malloc)
> diff --git a/sysdeps/aarch64/multiarch/malloc-ifuncs.c b/sysdeps/aarch64/multiarch/malloc-ifuncs.c
> new file mode 100644
> index 0000000000..d3d093fe91
> --- /dev/null
> +++ b/sysdeps/aarch64/multiarch/malloc-ifuncs.c
> @@ -0,0 +1,73 @@
> +/* Code for ifunc resolvers for malloc: aarch64 version.
> +   Copyright (C) 2026 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#if IS_IN (libc)
> +
> +#include <stdint.h>
> +#include <init-arch.h>
> +#include <malloc-ifuncs.h>
> +
> +libc_ifunc_hidden (__libc_malloc, __libc_malloc_redirect,
> +		   __libc_malloc)
> +strong_alias (__libc_malloc_redirect, malloc)
> +
> +libc_ifunc_hidden (__libc_calloc, __libc_calloc_redirect,
> +		   __libc_calloc)
> +weak_alias (__libc_calloc_redirect, calloc)
> +
> +libc_ifunc_hidden (__libc_memalign, __libc_memalign_redirect,
> +		   __libc_memalign)
> +weak_alias (__libc_memalign_redirect, memalign)
> +
> +libc_ifunc_hidden (__libc_valloc, __libc_valloc_redirect,
> +		   __libc_valloc)
> +weak_alias (__libc_valloc_redirect, valloc)
> +
> +libc_ifunc_hidden (__libc_pvalloc, __libc_pvalloc_redirect,
> +		   __libc_pvalloc)
> +weak_alias (__libc_pvalloc_redirect, pvalloc)
> +
> +libc_ifunc_hidden (__libc_realloc, __libc_realloc_redirect,
> +		   __libc_realloc)
> +strong_alias (__libc_realloc_redirect, realloc)
> +
> +libc_ifunc_hidden (__libc_free, __libc_free_redirect,
> +		   __libc_free)
> +strong_alias (__libc_free_redirect, free)
> +
> +libc_ifunc_hidden (__malloc_usable_size, __malloc_usable_size_redirect,
> +		   __malloc_usable_size)
> +weak_alias (__malloc_usable_size_redirect, malloc_usable_size)
> +
> +libc_ifunc_hidden (__posix_memalign, __posix_memalign_redirect,
> +		   __posix_memalign)
> +weak_alias (__posix_memalign_redirect, posix_memalign)
> +
> +libc_ifunc_hidden (__aligned_alloc, __aligned_alloc_redirect,
> +		   __aligned_alloc)
> +weak_alias (__aligned_alloc_redirect, aligned_alloc)
> +
> +libc_ifunc_hidden (__free_sized, __free_sized_redirect,
> +		   __free_sized)
> +weak_alias (__free_sized_redirect, free_sized)
> +
> +libc_ifunc_hidden (__free_aligned_sized, __free_aligned_sized_redirect,
> +		   __free_aligned_sized)
> +weak_alias (__free_aligned_sized_redirect, free_aligned_sized)
> +
> +#endif /* IS_IN (libc) */
> diff --git a/sysdeps/aarch64/multiarch/malloc-ifuncs.h b/sysdeps/aarch64/multiarch/malloc-ifuncs.h
> new file mode 100644
> index 0000000000..98e913d49c
> --- /dev/null
> +++ b/sysdeps/aarch64/multiarch/malloc-ifuncs.h
> @@ -0,0 +1,61 @@
> +/* Definitions for ifunc resolvers for malloc: aarch64 version.
> +   Copyright (C) 2026 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _AARCH64_MALLOC_IFUNCS_H
> +#define _AARCH64_MALLOC_IFUNCS_H
> +
> +#define USE_MULTIARCH_MALLOC 1
> +
> +#include <stddef.h>
> +#include <sys/cdefs.h>
> +
> +/* Core implementations of malloc functions.  An ifunc resolver must
> +   use this implementations as a fallback option.  Other implementations

s/this/these

> +   may internally call these core function.  */

s/function/functions

> +void *__libc_malloc (size_t);
> +libc_hidden_proto (__libc_malloc)
> +void *__libc_calloc (size_t, size_t);
> +libc_hidden_proto (__libc_calloc)
> +void *__libc_memalign (size_t, size_t);
> +libc_hidden_proto (__libc_memalign)
> +void *__libc_valloc (size_t);
> +libc_hidden_proto (__libc_valloc)
> +void *__libc_pvalloc (size_t);
> +libc_hidden_proto (__libc_pvalloc)
> +void *__libc_realloc (void *, size_t);
> +libc_hidden_proto (__libc_realloc)
> +void __libc_free (void *);
> +libc_hidden_proto (__libc_free)
> +size_t __malloc_usable_size (void *);
> +libc_hidden_proto (__malloc_usable_size)
> +
> +/* For additions of POSIX.  */
> +int __posix_memalign (void **, size_t, size_t);
> +libc_hidden_proto (__posix_memalign)
> +
> +/* For ISO C17.  */
> +void *__aligned_alloc (size_t, size_t);
> +libc_hidden_proto (__aligned_alloc)
> +
> +/* For ISO C23.  */
> +void __free_sized (void *, size_t);
> +libc_hidden_proto (__free_sized)
> +void __free_aligned_sized (void *, size_t, size_t);
> +libc_hidden_proto (__free_aligned_sized)
> +
> +#endif /* _AARCH64_MALLOC_IFUNCS_H */
> diff --git a/sysdeps/generic/malloc-ifuncs.h b/sysdeps/generic/malloc-ifuncs.h
> new file mode 100644
> index 0000000000..aedc56ae33
> --- /dev/null
> +++ b/sysdeps/generic/malloc-ifuncs.h
> @@ -0,0 +1,37 @@
> +/* Definitions for ifunc resolvers for malloc: generic version.
> +   Copyright (C) 2026 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _GENERIC_MALLOC_IFUNCS_H
> +#define _GENERIC_MALLOC_IFUNCS_H
> +
> +/* Targets should define this macro if they provide ifuncs for
> +   malloc functions.  When USE_MULTIARCH_MALLOC is defined, the
> +   following functions should be implemented via ifuncs:
> +
> +     malloc, calloc, free, realloc
> +     memalign, valloc, pvalloc
> +     posix_memalign
> +     malloc_usable_size
> +     aligned_alloc, free_sized, free_aligned_sized
> +
> +*/
> +#if defined(USE_MULTIARCH_MALLOC) || !defined(USE_MULTIARCH)
> +# undef USE_MULTIARCH_MALLOC
> +#endif

This header is already included iff USE_MULTIARCH is defined:

 27 #if defined(USE_MULTIARCH)
 28 # include <malloc-ifuncs.h>
 29 #endif
 30

> +
> +#endif /* GENERIC_MALLOC_IFUNCS_H */



More information about the Libc-alpha mailing list