[PATCH 2/2] aarch64: Add workaround for GDB bug handling string literals

Florian Weimer fweimer@redhat.com
Mon Jun 29 21:07:13 GMT 2026


When GDB evaluates an expression in the inferior, it first
creates a copy of the string using malloc.  For this malloc
call, GDB was not tracking properly if the malloc symbol is
actually an IFUNC resolver.  This means that the IFUNC
resolver gets called like the real malloc function.

This change adds a kludge to detect this, which prevents GDB
from overwriting the __libc_malloc code with the user-supplied
string literal.
---
 sysdeps/aarch64/multiarch/malloc-ifuncs.c | 60 +++++++++++++++++------
 1 file changed, 46 insertions(+), 14 deletions(-)

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) */
-- 
2.54.0



More information about the Libc-alpha mailing list