diff --git a/sysdeps/aarch64/multiarch/malloc-ifuncs.c b/sysdeps/aarch64/multiarch/malloc-ifuncs.c
index 648fb617de..3552168ecd 100644
--- a/sysdeps/aarch64/multiarch/malloc-ifuncs.c
+++ b/sysdeps/aarch64/multiarch/malloc-ifuncs.c
@@ -19,55 +19,87 @@
 #if IS_IN (libc)
 
 #include <init-arch.h>
+#include <ldsodefs.h>
 #include <malloc-api.h>
 #include <shlib-compat.h>
-
-libc_ifunc_hidden (__libc_malloc, __libc_malloc_redirect,
-		   __libc_malloc)
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* Return true if the resolver function has been called through GDB.
+   This used below to determine if GDB incorrectly calls the malloc
+   IFUNC resolver instead of the resolver result.  The trampoline
+   address is either on the stack, or the kernel-provided entry point,
+   depending on architecture.
+
+   A fixed GDB will get the malloc address from the GOT.  Calling
+   malloc before relocation processing is complete should use the
+   ld.so malloc, which does not involve an IFUNC.  */
+static inline bool
+called_from_gdb (uintptr_t return_address, uintptr_t stack_frame)
+{
+#ifdef SHARED
+  /* Assume that the stack grows downwards.  */
+  if (stack_frame <= return_address && return_address <= stack_frame + 128)
+    return true;
+
+  /* GDB uses the kernel-provided entry point on some architectures
+     for the trampoline.  */
+  if (return_address == GLRO(dl_entry))
+    return true;
+#endif
+  return false;
+}
+
+__ifunc_hidden (__libc_malloc, __libc_malloc_redirect,
+                called_from_gdb ((uintptr_t) __builtin_return_address (0),
+                                 (uintptr_t) __builtin_frame_address (0))
+                ? __libc_malloc (size) : (void *) __libc_malloc,
+                size_t size, INIT_ARCH)
 strong_alias (__libc_malloc_redirect, malloc)
 
 libc_ifunc_hidden (__libc_calloc, __libc_calloc_redirect,
-		   __libc_calloc)
+                   __libc_calloc)
 weak_alias (__libc_calloc_redirect, calloc)
 
 libc_ifunc_hidden (__libc_memalign, __libc_memalign_redirect,
-		   __libc_memalign)
+                   __libc_memalign)
 weak_alias (__libc_memalign_redirect, memalign)
 
 libc_ifunc_hidden (__libc_valloc, __libc_valloc_redirect,
-		   __libc_valloc)
+                   __libc_valloc)
 weak_alias (__libc_valloc_redirect, valloc)
 
 libc_ifunc_hidden (__libc_pvalloc, __libc_pvalloc_redirect,
-		   __libc_pvalloc)
+                   __libc_pvalloc)
 weak_alias (__libc_pvalloc_redirect, pvalloc)
 
 libc_ifunc_hidden (__libc_realloc, __libc_realloc_redirect,
-		   __libc_realloc)
+                   __libc_realloc)
 strong_alias (__libc_realloc_redirect, realloc)
 
 libc_ifunc_hidden (__libc_free, __libc_free_redirect,
-		   __libc_free)
+                   __libc_free)
 strong_alias (__libc_free_redirect, free)
 
 libc_ifunc_hidden (__malloc_usable_size, __malloc_usable_size_redirect,
-		   __malloc_usable_size)
+                   __malloc_usable_size)
 weak_alias (__malloc_usable_size_redirect, malloc_usable_size)
 
 libc_ifunc_hidden (__posix_memalign, __posix_memalign_redirect,
-		   __posix_memalign)
+                   __posix_memalign)
 weak_alias (__posix_memalign_redirect, posix_memalign)
 
 libc_ifunc_hidden (__aligned_alloc, __aligned_alloc_redirect,
-		   __aligned_alloc)
+                   __aligned_alloc)
 weak_alias (__aligned_alloc_redirect, aligned_alloc)
 
 libc_ifunc_hidden (__free_sized, __free_sized_redirect,
-		   __free_sized)
+                   __free_sized)
 weak_alias (__free_sized_redirect, free_sized)
 
 libc_ifunc_hidden (__free_aligned_sized, __free_aligned_sized_redirect,
-		   __free_aligned_sized)
+                   __free_aligned_sized)
 weak_alias (__free_aligned_sized_redirect, free_aligned_sized)
 
 #endif /* IS_IN (libc) */
