[v4,1/1] malloc: aarch64: Add ifuncs for malloc functions
Checks
| Context |
Check |
Description |
| redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
| linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
| redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
| linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Test passed
|
Commit Message
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.
---
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
Comments
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 */
On Wed, Jun 03, 2026 at 10:46:16AM -0300, Adhemerval Zanella Netto wrote:
>
> 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).
I've checked it with gdb and lldb as well as with valgrind memcheck and
massif tools, address, hwadderess, thread and leak sanitizers and also
using the heaptrack heap profiler. The output before and after looks the
same except for 2 things I describe below. The heap usage, memory leaks,
and out of buffer accesses are reported in the same way before and after
the change.
One difference in the valgrind output is that it detects that the malloc
functions are ifuncs now and you see
REDIR: 0x4958810 (libc.so.6:aligned_alloc) redirected to 0x48507cc (_vgnU_ifunc_wrapper)
REDIR: 0x4956c84 (libc.so.6:__aligned_alloc) redirected to 0x488d708 (aligned_alloc)
instead of
REDIR: 0x4956c84 (libc.so.6:aligned_alloc) redirected to 0x488d708 (aligned_alloc)
This is expected I guess, and it doesn't affect valgrind's operation.
The second thing in the debuggers and in thread stacks in sanitizers the
malloc functions appear as "__lib_malloc" instead of "malloc" (for example)
which is also expected as a tool would show the symbol that the corresponding
ifunc resolves to. When we have "__libc_malloc" and "__libc_malloc_mte", it
would show the appropriate symbol which is how it should be, I think.
So, I think that this patch should not introduce any issues for sanitizers,
profiling and debugging tools.
>
> ...
>
> > +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.
Yes, I will fix it in the next version of the patch.
>
> ...
>
> > 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
> > +
>
> ...
>
> > +#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
>
OK
> ...
>
> > 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
>
> ...
>
> This header is already included iff USE_MULTIARCH is defined:
>
> 27 #if defined(USE_MULTIARCH)
> 28 # include <malloc-ifuncs.h>
> 29 #endif
> 30
>
OK
> > +
> > +#endif /* GENERIC_MALLOC_IFUNCS_H */
>
Thanks,
Yury
On 04/06/26 08:21, Yury Khrustalev wrote:
> On Wed, Jun 03, 2026 at 10:46:16AM -0300, Adhemerval Zanella Netto wrote:
>>
>> 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).
>
> I've checked it with gdb and lldb as well as with valgrind memcheck and
> massif tools, address, hwadderess, thread and leak sanitizers and also
> using the heaptrack heap profiler. The output before and after looks the
> same except for 2 things I describe below. The heap usage, memory leaks,
> and out of buffer accesses are reported in the same way before and after
> the change.
>
> One difference in the valgrind output is that it detects that the malloc
> functions are ifuncs now and you see
>
> REDIR: 0x4958810 (libc.so.6:aligned_alloc) redirected to 0x48507cc (_vgnU_ifunc_wrapper)
> REDIR: 0x4956c84 (libc.so.6:__aligned_alloc) redirected to 0x488d708 (aligned_alloc)
>
> instead of
>
> REDIR: 0x4956c84 (libc.so.6:aligned_alloc) redirected to 0x488d708 (aligned_alloc)
>
> This is expected I guess, and it doesn't affect valgrind's operation.
>
> The second thing in the debuggers and in thread stacks in sanitizers the
> malloc functions appear as "__lib_malloc" instead of "malloc" (for example)
> which is also expected as a tool would show the symbol that the corresponding
> ifunc resolves to. When we have "__libc_malloc" and "__libc_malloc_mte", it
> would show the appropriate symbol which is how it should be, I think.
>
> So, I think that this patch should not introduce any issues for sanitizers,
> profiling and debugging tools.
Sounds good, thanks for checking this.
>
>>
>> ...
>>
>>> +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.
>
> Yes, I will fix it in the next version of the patch.
>
>>
>> ...
>>
>>> 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
>>> +
>>
>> ...
>>
>>> +#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
>>
>
> OK
>
>> ...
>>
>>> 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
>>
>> ...
>>
>> This header is already included iff USE_MULTIARCH is defined:
>>
>> 27 #if defined(USE_MULTIARCH)
>> 28 # include <malloc-ifuncs.h>
>> 29 #endif
>> 30
>>
>
> OK
>
>>> +
>>> +#endif /* GENERIC_MALLOC_IFUNCS_H */
>>
>
> Thanks,
> Yury
>
@@ -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;
@@ -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)
@@ -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)
new file mode 100644
@@ -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) */
new file mode 100644
@@ -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
+ may internally call these core function. */
+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 */
new file mode 100644
@@ -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
+
+#endif /* GENERIC_MALLOC_IFUNCS_H */