[glibc] malloc: aarch64: Add ifuncs for malloc functions

Yury Khrustalev via Glibc-cvs <[email protected]> Mon, 15 Jun 2026 14:13:26 +0000 (GMT)
Newsgroups gmane.comp.lib.glibc.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9ed3576e61f7a87eb83d512531566f5e5d6bb032

commit 9ed3576e61f7a87eb83d512531566f5e5d6bb032
Author: Yury Khrustalev <[email protected]>
Date:   Tue May 26 11:19:53 2026 +0100

    malloc: aarch64: Add ifuncs for malloc functions
    
    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.

Diff:
---
 malloc/malloc-internal.h                  |   2 +
 malloc/malloc.c                           | 155 ++++------------------------
 sysdeps/aarch64/multiarch/Makefile        |  10 +-
 sysdeps/aarch64/multiarch/malloc-ifuncs.c |  77 ++++++++++++++
 sysdeps/aarch64/multiarch/malloc-ifuncs.h |  24 +++++
 sysdeps/generic/malloc-api.h              | 161 ++++++++++++++++++++++++++++++
 sysdeps/generic/malloc-ifuncs.h           |  36 +++++++
 7 files changed, 330 insertions(+), 135 deletions(-)

diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index a6340bfd88..29bc3734c6 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -24,6 +24,8 @@
 #include <malloc-size.h>
 #include <hugepages.h>
 #include <calloc-clear-memory.h>
+#include <malloc-api.h>
+#include <malloc-ifuncs.h>
 
 /* 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 297e365627..a354576aca 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -459,101 +459,10 @@ static int extra_mmap_prot = 0;
 /* ---------- description of public routines ------------ */
 
 #if IS_IN (libc)
-/*
-  malloc(size_t n)
-  Returns a pointer to a newly allocated chunk of at least n bytes, or null
-  if no space is available. Additionally, on failure, errno is
-  set to ENOMEM on ANSI C systems.
-
-  If n is zero, malloc returns a minimum-sized chunk. (The minimum
-  size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit
-  systems.)  On most systems, size_t is an unsigned type, so calls
-  with negative arguments are interpreted as requests for huge amounts
-  of space, which will often fail. The maximum supported value of n
-  differs across systems, but is in all cases less than the maximum
-  representable value of a size_t.
-*/
-void *__libc_malloc (size_t);
-libc_hidden_proto (__libc_malloc)
 
 static void *__libc_calloc2 (size_t);
 static void *__libc_malloc2 (size_t);
 
-/*
-  free(void* p)
-  Releases the chunk of memory pointed to by p, that had been previously
-  allocated using malloc or a related routine such as realloc.
-  It has no effect if p is null. It can have arbitrary (i.e., bad!)
-  effects if p has already been freed.
-
-  Unless disabled (using mallopt), freeing very large spaces will
-  when possible, automatically trigger operations that give
-  back unused memory to the system, thus reducing program footprint.
-*/
-void     __libc_free(void*);
-libc_hidden_proto (__libc_free)
-
-/*
-  calloc(size_t n_elements, size_t element_size);
-  Returns a pointer to n_elements * element_size bytes, with all locations
-  set to zero.
-*/
-void*  __libc_calloc(size_t, size_t);
-
-/*
-  realloc(void* p, size_t n)
-  Returns a pointer to a chunk of size n that contains the same data
-  as does chunk p up to the minimum of (n, p's size) bytes, or null
-  if no space is available.
-
-  The returned pointer may or may not be the same as p. The algorithm
-  prefers extending p when possible, otherwise it employs the
-  equivalent of a malloc-copy-free sequence.
-
-  If p is null, realloc is equivalent to malloc.
-
-  If space is not available, realloc returns null, errno is set (if on
-  ANSI) and p is NOT freed.
-
-  if n is for fewer bytes than already held by p, the newly unused
-  space is lopped off and freed if possible.  Unless the #define
-  REALLOC_ZERO_BYTES_FREES is set, realloc with a size argument of
-  zero (re)allocates a minimum-sized chunk.
-
-  Large chunks that were internally obtained via mmap will always be
-  grown using malloc-copy-free sequences unless the system supports
-  MREMAP (currently only linux).
-
-  The old unix realloc convention of allowing the last-free'd chunk
-  to be used as an argument to realloc is not supported.
-*/
-void*  __libc_realloc(void*, size_t);
-libc_hidden_proto (__libc_realloc)
-
-/*
-  memalign(size_t alignment, size_t n);
-  Returns a pointer to a newly allocated chunk of n bytes, aligned
-  in accord with the alignment argument.
-
-  The alignment argument should be a power of two. If the argument is
-  not a power of two, the nearest greater power is used.
-  8-byte alignment is guaranteed by normal malloc calls, so don't
-  bother calling memalign with an argument of 8 or less.
-
-  Overreliance on memalign is a sure way to fragment space.
-*/
-void*  __libc_memalign(size_t, size_t);
-libc_hidden_proto (__libc_memalign)
-
-/*
-  valloc(size_t n);
-  Equivalent to memalign(pagesize, n), where pagesize is the page
-  size of the system. If the pagesize is unknown, 4096 is used.
-*/
-void*  __libc_valloc(size_t);
-
-
-
 /*
   mallinfo()
   Returns (by copy) a struct containing various summary statistics:
@@ -578,14 +487,6 @@ libc_hidden_proto (__libc_mallinfo2)
 
 struct mallinfo __libc_mallinfo(void);
 
-
-/*
-  pvalloc(size_t n);
-  Equivalent to valloc(minimum-page-that-holds(n)), that is,
-  round up n to nearest pagesize.
- */
-void*  __libc_pvalloc(size_t);
-
 /*
   malloc_trim(size_t pad);
 
@@ -612,23 +513,6 @@ void*  __libc_pvalloc(size_t);
 */
 int      __malloc_trim(size_t);
 
-/*
-  malloc_usable_size(void* p);
-
-  Returns the number of bytes you can actually use in
-  an allocated chunk, which may be more than you requested (although
-  often not) due to alignment and minimum size constraints.
-  You can use this many bytes without worrying about
-  overwriting other allocated objects. This is not a particularly great
-  programming practice. malloc_usable_size can be more useful in
-  debugging and assertions, for example:
-
-  p = malloc(n);
-  assert(malloc_usable_size(p) >= 256);
-
-*/
-size_t   __malloc_usable_size(void*);
-
 /*
   malloc_stats();
   Prints on stderr the amount of space obtained from the system (both
@@ -651,12 +535,6 @@ size_t   __malloc_usable_size(void*);
 */
 void     __malloc_stats(void);
 
-/*
-  posix_memalign(void **memptr, size_t alignment, size_t size);
-
-  POSIX wrapper like memalign(), checking for validity of size.
-*/
-int      __posix_memalign(void **, size_t, size_t);
 #endif /* IS_IN (libc) */
 
 /*
@@ -3312,10 +3190,8 @@ __libc_memalign (size_t alignment, size_t bytes)
 }
 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)
 {
 /* Starting with ISO C17 the standard requires an error for alignments
    that are not supported.  Only integral powers of 2 are valid.  */
@@ -3327,11 +3203,10 @@ 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)
 {
   /* 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
@@ -3340,11 +3215,10 @@ 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)
 {
   /* We do not perform validation that size and alignment is the same as
@@ -3354,6 +3228,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)
@@ -3402,6 +3277,7 @@ __libc_valloc (size_t bytes)
 {
   return _mid_memalign (GLRO (dl_pagesize), bytes);
 }
+libc_hidden_def (__libc_valloc)
 
 void *
 __libc_pvalloc (size_t bytes)
@@ -3419,6 +3295,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)
@@ -3540,6 +3417,7 @@ __libc_calloc (size_t n, size_t elem_size)
 #endif
   return __libc_calloc2 (bytes);
 }
+libc_hidden_def (__libc_calloc)
 #endif /* IS_IN (libc) */
 
 /*
@@ -4532,6 +4410,7 @@ __malloc_usable_size (void *m)
     return 0;
   return musable (m);
 }
+libc_hidden_def (__malloc_usable_size)
 #endif /* IS_IN (libc) */
 
 /*
@@ -5059,6 +4938,7 @@ __posix_memalign (void **memptr, size_t alignment, size_t size)
   *memptr = mem;
   return 0;
 }
+libc_hidden_def (__posix_memalign)
 #endif /* IS_IN (libc) */
 
 
@@ -5221,6 +5101,9 @@ __malloc_info (int options, FILE *fp)
 }
 
 #if IS_IN (libc)
+
+/* See sysdeps/generic/malloc-ifuncs.h for details.  */
+# if !USE_MULTIARCH_MALLOC
 strong_alias (__libc_malloc, malloc)
 strong_alias (__libc_realloc, realloc)
 strong_alias (__libc_free, free)
@@ -5230,6 +5113,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)
@@ -5239,9 +5126,11 @@ weak_alias (__malloc_stats, malloc_stats)
 weak_alias (__malloc_trim, malloc_trim)
 #endif /* IS_IN (libc) */
 
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_26)
+#if !USE_MULTIARCH_MALLOC
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_26)
 compat_symbol (libc, __libc_free, cfree, GLIBC_2_0);
-#endif
+# endif
+#endif /* !USE_MULTIARCH_MALLOC */
 
 /* ------------------------------------------------------------
    History:
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..648fb617de
--- /dev/null
+++ b/sysdeps/aarch64/multiarch/malloc-ifuncs.c
@@ -0,0 +1,77 @@
+/* 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 <init-arch.h>
+#include <malloc-api.h>
+#include <shlib-compat.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) */
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_26)
+compat_symbol (libc, __libc_free_redirect, cfree, GLIBC_2_0);
+#endif
diff --git a/sysdeps/aarch64/multiarch/malloc-ifuncs.h b/sysdeps/aarch64/multiarch/malloc-ifuncs.h
new file mode 100644
index 0000000000..572c2f229e
--- /dev/null
+++ b/sysdeps/aarch64/multiarch/malloc-ifuncs.h
@@ -0,0 +1,24 @@
+/* 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
+
+#endif /* _AARCH64_MALLOC_IFUNCS_H */
diff --git a/sysdeps/generic/malloc-api.h b/sysdeps/generic/malloc-api.h
new file mode 100644
index 0000000000..2a243cc4af
--- /dev/null
+++ b/sysdeps/generic/malloc-api.h
@@ -0,0 +1,161 @@
+/* Malloc API functions.
+   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; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+#ifndef _MALLOC_API_H
+#define _MALLOC_API_H
+
+#include <stddef.h>
+#include <libc-symbols.h>
+
+/*
+  malloc(size_t n)
+  Returns a pointer to a newly allocated chunk of at least n bytes, or null
+  if no space is available. Additionally, on failure, errno is
+  set to ENOMEM on ANSI C systems.
+
+  If n is zero, malloc returns a minimum-sized chunk. (The minimum
+  size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit
+  systems.)  On most systems, size_t is an unsigned type, so calls
+  with negative arguments are interpreted as requests for huge amounts
+  of space, which will often fail. The maximum supported value of n
+  differs across systems, but is in all cases less than the maximum
+  representable value of a size_t.
+*/
+void *__libc_malloc (size_t);
+libc_hidden_proto (__libc_malloc)
+
+/*
+  calloc(size_t n_elements, size_t element_size);
+  Returns a pointer to n_elements * element_size bytes, with all locations
+  set to zero.
+*/
+void *__libc_calloc (size_t, size_t);
+libc_hidden_proto (__libc_calloc)
+
+/*
+  memalign(size_t alignment, size_t n);
+  Returns a pointer to a newly allocated chunk of n bytes, aligned
+  in accord with the alignment argument.
+
+  The alignment argument should be a power of two. If the argument is
+  not a power of two, the nearest greater power is used.
+  8-byte alignment is guaranteed by normal malloc calls, so don't
+  bother calling memalign with an argument of 8 or less.
+
+  Overreliance on memalign is a sure way to fragment space.
+*/
+void *__libc_memalign (size_t, size_t);
+libc_hidden_proto (__libc_memalign)
+
+/*
+  valloc(size_t n);
+  Equivalent to memalign(pagesize, n), where pagesize is the page
+  size of the system. If the pagesize is unknown, 4096 is used.
+*/
+void *__libc_valloc (size_t);
+libc_hidden_proto (__libc_valloc)
+
+/*
+  pvalloc(size_t n);
+  Equivalent to valloc(minimum-page-that-holds(n)), that is,
+  round up n to nearest pagesize.
+ */
+void *__libc_pvalloc (size_t);
+libc_hidden_proto (__libc_pvalloc)
+
+/*
+  realloc(void* p, size_t n)
+  Returns a pointer to a chunk of size n that contains the same data
+  as does chunk p up to the minimum of (n, p's size) bytes, or null
+  if no space is available.
+
+  The returned pointer may or may not be the same as p. The algorithm
+  prefers extending p when possible, otherwise it employs the
+  equivalent of a malloc-copy-free sequence.
+
+  If p is null, realloc is equivalent to malloc.
+
+  If space is not available, realloc returns null, errno is set (if on
+  ANSI) and p is NOT freed.
+
+  if n is for fewer bytes than already held by p, the newly unused
+  space is lopped off and freed if possible.  Unless the #define
+  REALLOC_ZERO_BYTES_FREES is set, realloc with a size argument of
+  zero (re)allocates a minimum-sized chunk.
+
+  Large chunks that were internally obtained via mmap will always be
+  grown using malloc-copy-free sequences unless the system supports
+  MREMAP (currently only linux).
+
+  The old unix realloc convention of allowing the last-free'd chunk
+  to be used as an argument to realloc is not supported.
+*/
+void *__libc_realloc (void *, size_t);
+libc_hidden_proto (__libc_realloc)
+
+/*
+  free(void* p)
+  Releases the chunk of memory pointed to by p, that had been previously
+  allocated using malloc or a related routine such as realloc.
+  It has no effect if p is null. It can have arbitrary (i.e., bad!)
+  effects if p has already been freed.
+
+  Unless disabled (using mallopt), freeing very large spaces will
+  when possible, automatically trigger operations that give
+  back unused memory to the system, thus reducing program footprint.
+*/
+void __libc_free (void *);
+libc_hidden_proto (__libc_free)
+
+/*
+  malloc_usable_size(void* p);
+
+  Returns the number of bytes you can actually use in
+  an allocated chunk, which may be more than you requested (although
+  often not) due to alignment and minimum size constraints.
+  You can use this many bytes without worrying about
+  overwriting other allocated objects. This is not a particularly great
+  programming practice. malloc_usable_size can be more useful in
+  debugging and assertions, for example:
+
+  p = malloc(n);
+  assert(malloc_usable_size(p) >= 256);
+
+*/
+size_t __malloc_usable_size (void *);
+libc_hidden_proto (__malloc_usable_size)
+
+/*
+  posix_memalign(void **memptr, size_t alignment, size_t size);
+
+  POSIX wrapper like memalign(), checking for validity of size.
+*/
+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 /* _MALLOC_API_H */
diff --git a/sysdeps/generic/malloc-ifuncs.h b/sysdeps/generic/malloc-ifuncs.h
new file mode 100644
index 0000000000..8fe88af95e
--- /dev/null
+++ b/sysdeps/generic/malloc-ifuncs.h
@@ -0,0 +1,36 @@
+/* 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 that support GNU ifuncs should define this macro
+   if they provide ifuncs for malloc functions.
+
+   When USE_MULTIARCH_MALLOC is defined as 1, 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
+*/
+#define USE_MULTIARCH_MALLOC 0
+
+#endif /* _GENERIC_MALLOC_IFUNCS_H */