diff mbox series

[v2,08/10] Remove malloc hooks

Message ID 20210630151921.2752628-9-siddhesh@sourceware.org
State New
Headers show
Series Remove malloc hooks | expand

Commit Message

Siddhesh Poyarekar June 30, 2021, 3:19 p.m. UTC
Make malloc hooks symbols compat-only so that new applications cannot
link against them and remove the declarations from the API.  The
existing hooks variables are not used in the library anymore.

Legacy applications that need hooks functionality need to preload a
new DSO libmalloc_compathooks.so, which interposes the libc malloc
functions to execute hooks if they exist.

Also remove all references to the malloc hooks in the manual.  Mention
the removal in NEWS and also warn that libmalloc_compathooks.so is a
temporary measure and may be removed in a future version of glibc.

memalign makes a comeback as a PLT reference since the initialization
hooks use them.  tst-mallocstate now needs libmalloc_compathooks.so
since it uses __malloc_initialize_hook to set up initial heap state to
emumate emacs.
---
 Makeconfig                                    |   2 +-
 NEWS                                          |   9 +
 malloc/Makefile                               |  15 +-
 malloc/arena.c                                |   5 -
 malloc/hooks.c                                | 114 ++++++-----
 malloc/malloc-compathooks.c                   | 166 +++++++++++++++
 malloc/malloc.c                               |  10 -
 malloc/malloc.h                               |  14 --
 manual/memory.texi                            | 191 +-----------------
 sysdeps/generic/localplt.data                 |   1 +
 sysdeps/mach/hurd/i386/localplt.data          |   1 +
 sysdeps/unix/sysv/linux/aarch64/localplt.data |   1 +
 sysdeps/unix/sysv/linux/alpha/localplt.data   |   1 +
 sysdeps/unix/sysv/linux/arc/localplt.data     |   1 +
 sysdeps/unix/sysv/linux/arm/localplt.data     |   1 +
 sysdeps/unix/sysv/linux/csky/localplt.data    |   1 +
 sysdeps/unix/sysv/linux/hppa/localplt.data    |   1 +
 sysdeps/unix/sysv/linux/i386/localplt.data    |   1 +
 sysdeps/unix/sysv/linux/ia64/localplt.data    |   1 +
 .../sysv/linux/m68k/coldfire/localplt.data    |   1 +
 .../unix/sysv/linux/m68k/m680x0/localplt.data |   1 +
 .../unix/sysv/linux/microblaze/localplt.data  |   1 +
 sysdeps/unix/sysv/linux/nios2/localplt.data   |   1 +
 .../linux/powerpc/powerpc32/fpu/localplt.data |   1 +
 .../powerpc/powerpc32/nofpu/localplt.data     |   1 +
 .../linux/powerpc/powerpc64/localplt.data     |   1 +
 sysdeps/unix/sysv/linux/riscv/localplt.data   |   1 +
 sysdeps/unix/sysv/linux/s390/localplt.data    |   1 +
 sysdeps/unix/sysv/linux/sh/localplt.data      |   1 +
 .../sysv/linux/sparc/sparc32/localplt.data    |   1 +
 .../sysv/linux/sparc/sparc64/localplt.data    |   1 +
 sysdeps/x86_64/localplt.data                  |   1 +
 32 files changed, 284 insertions(+), 265 deletions(-)
 create mode 100644 malloc/malloc-compathooks.c

Comments

DJ Delorie July 1, 2021, 10:47 p.m. UTC | #1
This is the same as v1, and with the answer to my question from that
one...

LGTM.
Reviewed-by: DJ Delorie <dj@redhat.com>
diff mbox series

Patch

diff --git a/Makeconfig b/Makeconfig
index 407df9e6a1..991d6d3e99 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -951,7 +951,7 @@  libio-include = -I$(..)libio
 built-modules = iconvprogs iconvdata ldconfig lddlibc4 libmemusage \
 		libSegFault libpcprofile librpcsvc locale-programs \
 		memusagestat nonlib nscd extramodules libnldbl libsupport \
-		testsuite
+		testsuite libmalloc_compathooks
 
 in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
 				    $(libof-$(<F)) \
diff --git a/NEWS b/NEWS
index 8e72946c3f..cebe8384bf 100644
--- a/NEWS
+++ b/NEWS
@@ -97,6 +97,15 @@  Deprecated and removed features, and other changes affecting compatibility:
   mtrace.  Similar functionality can be achieved by using conditional
   breakpoints within mtrace functions from within gdb.
 
+* The deprecated memory allocation hooks __malloc_hook, __realloc_hook,
+  __memalign_hook and __free_hook are now removed from the API.  Compatibility
+  symbols are present to support legacy programs but new applications can no
+  longer link to these symbols.  Further, the hooks no longer have any effect
+  on glibc functionality.  A compatibility DSO libmalloc_compathooks.so has
+  been provided as a transitional measure to get hook functionality back for
+  legacy programs until they are updated to remove references to the memory
+  allocation hooks.
+
 Changes to build and runtime requirements:
 
 * On Linux, the shm_open, sem_open, and related functions now expect the
diff --git a/malloc/Makefile b/malloc/Makefile
index 62cc1bf2f5..0c6827203e 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -42,6 +42,7 @@  tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-malloc-stats-cancellation \
 	 tst-tcfree1 tst-tcfree2 tst-tcfree3 \
 	 tst-safe-linking \
+	 tst-compathooks-off tst-compathooks-on
 
 tests-static := \
 	 tst-interpose-static-nothread \
@@ -113,8 +114,8 @@  routines = malloc morecore mcheck mtrace obstack reallocarray \
 install-lib := libmcheck.a
 non-lib.a := libmcheck.a
 
-# Additional library.
-extra-libs = libmemusage
+# Additional libraries.
+extra-libs = libmemusage libmalloc_compathooks
 extra-libs-others = $(extra-libs)
 
 # Helper objects for some tests.
@@ -129,6 +130,9 @@  test-extras = \
 libmemusage-routines = memusage
 libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
 
+libmalloc_compathooks-routines = malloc-compathooks
+libmalloc_compathooks-inhibit-o = $(filter-out .os,$(object-suffixes))
+
 $(objpfx)tst-malloc-backtrace: $(shared-thread-library)
 $(objpfx)tst-malloc-thread-exit: $(shared-thread-library)
 $(objpfx)tst-malloc-thread-fail: $(shared-thread-library)
@@ -317,3 +321,10 @@  $(objpfx)tst-mallocfork2-mcheck: $(shared-thread-library)
 $(objpfx)tst-malloc-tcache-leak-malloc-check: $(shared-thread-library)
 $(objpfx)tst-malloc_info-malloc-check: $(shared-thread-library)
 $(objpfx)tst-mallocfork2-malloc-check: $(shared-thread-library)
+
+tst-compathooks-on-ENV = LD_PRELOAD=$(objpfx)libmalloc_compathooks.so
+tst-compathooks-on-mcheck-ENV = LD_PRELOAD=$(objpfx)libmalloc_compathooks.so
+tst-compathooks-on-malloc-check-ENV = \
+	LD_PRELOAD=$(objpfx)libmalloc_compathooks.so
+tst-mallocstate-ENV = LD_PRELOAD=$(objpfx)libmalloc_compathooks.so
+tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libmalloc_compathooks.so
diff --git a/malloc/arena.c b/malloc/arena.c
index a8500a25c9..8591c8ea56 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -408,11 +408,6 @@  ptmalloc_init (void)
     __mcheck_initialize (NULL, false);
 #endif
 
-#if HAVE_MALLOC_INIT_HOOK
-  void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook);
-  if (hook != NULL)
-    (*hook)();
-#endif
   __malloc_initialized = 1;
 }
 
diff --git a/malloc/hooks.c b/malloc/hooks.c
index 7f3b07ca44..397220aaba 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -42,23 +42,84 @@  enum malloc_debug_hooks
 static unsigned __malloc_debugging_hooks;
 
 /* Forward declarations.  */
+static void ptmalloc_init (void);
 
-#if HAVE_MALLOC_INIT_HOOK
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24)
 void (*__malloc_initialize_hook) (void) __attribute__ ((nocommon));
 compat_symbol (libc, __malloc_initialize_hook,
 	       __malloc_initialize_hook, GLIBC_2_0);
+
+# define MALLOC_INIT_HOOK() ({ \
+  void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook);	      \
+  if (hook != NULL)							      \
+    (*hook)();								      \
+})
+#else
+# define MALLOC_INIT_HOOK()
 #endif
 
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
+
+static void *malloc_hook_ini (size_t, const void *) __THROW;
+static void *realloc_hook_ini (void *, size_t, const void *) __THROW;
+static void *memalign_hook_ini (size_t, size_t, const void *) __THROW;
+
 void weak_variable (*__free_hook) (void *__ptr,
                                    const void *) = NULL;
 void *weak_variable (*__malloc_hook)
-  (size_t __size, const void *) = NULL;
+  (size_t __size, const void *) = malloc_hook_ini;
 void *weak_variable (*__realloc_hook)
-  (void *__ptr, size_t __size, const void *) = NULL;
+  (void *__ptr, size_t __size, const void *) = realloc_hook_ini;
 void *weak_variable (*__memalign_hook)
-  (size_t __alignment, size_t __size, const void *) = NULL;
+  (size_t __alignment, size_t __size, const void *) = memalign_hook_ini;
 
-static void ptmalloc_init (void);
+compat_symbol (libc, __free_hook, __free_hook, GLIBC_2_0);
+compat_symbol (libc, __malloc_hook, __malloc_hook, GLIBC_2_0);
+compat_symbol (libc, __realloc_hook, __realloc_hook, GLIBC_2_0);
+compat_symbol (libc, __memalign_hook, __memalign_hook, GLIBC_2_0);
+
+/* These hooks will get executed only through the interposed allocator
+   functions in libmalloc_compathooks.  This means that the calls to malloc,
+   realloc, etc. will lead back into the interposed functions, which is what we
+   want.
+
+   These initial hooks are assumed to be called in a single-threaded context,
+   so it is safe to reset all hooks at once upon initialization.  */
+
+static void
+generic_hook_ini (void)
+{
+  __malloc_hook = NULL;
+  __realloc_hook = NULL;
+  __memalign_hook = NULL;
+  if (__malloc_initialized < 0)
+    {
+      ptmalloc_init ();
+      MALLOC_INIT_HOOK ();
+    }
+}
+
+static void *
+malloc_hook_ini (size_t sz, const void *caller)
+{
+  generic_hook_ini ();
+  return malloc (sz);
+}
+
+static void *
+realloc_hook_ini (void *ptr, size_t sz, const void *caller)
+{
+  generic_hook_ini ();
+  return realloc (ptr, sz);
+}
+
+static void *
+memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
+{
+  generic_hook_ini ();
+  return memalign (alignment, sz);
+}
+#endif
 
 static __always_inline bool
 __is_malloc_debug_enabled (enum malloc_debug_hooks flag)
@@ -88,14 +149,6 @@  _malloc_debug_before (size_t *bytesp, void **victimp, const void *address)
   _Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
 		  "PTRDIFF_MAX is not more than half of SIZE_MAX");
 
-  void *(*hook) (size_t, const void *)
-    = atomic_forced_read (__malloc_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    {
-      *victimp = (*hook)(*bytesp, address);
-      return true;
-    }
-
   if (__glibc_unlikely (__malloc_debugging_hooks))
     {
       if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
@@ -126,14 +179,6 @@  _malloc_debug_after (void *mem, size_t bytes, const void *address)
 static __always_inline bool
 _free_debug_before (void **mem, const void *address)
 {
-  void (*hook) (void *, const void *)
-    = atomic_forced_read (__free_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    {
-      (*hook)(*mem, address);
-      return true;
-    }
-
   if (__glibc_unlikely (__malloc_debugging_hooks))
     {
       if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
@@ -153,14 +198,6 @@  static __always_inline bool
 _realloc_debug_before (void **oldmem, size_t *bytesp, size_t *oldsize,
 		       void **victimp, const void *address)
 {
-  void *(*hook) (void *, size_t, const void *) =
-    atomic_forced_read (__realloc_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    {
-      *victimp = (*hook)(*oldmem, *bytesp, address);
-      return true;
-    }
-
   if (__glibc_unlikely (__malloc_debugging_hooks))
     {
       if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
@@ -194,13 +231,6 @@  static __always_inline bool
 _memalign_debug_before (size_t alignment, size_t *bytesp, void **victimp,
 			const void *address)
 {
-  void *(*hook) (size_t, size_t, const void *) =
-    atomic_forced_read (__memalign_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    {
-      *victimp = (*hook)(alignment, *bytesp, address);
-      return true;
-    }
   if (__glibc_unlikely (__malloc_debugging_hooks))
     {
       if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
@@ -233,18 +263,6 @@  _memalign_debug_after (void *mem, size_t alignment, size_t bytes,
 static __always_inline bool
 _calloc_debug_before (size_t *bytesp, void **victimp, const void *address)
 {
-  void *(*hook) (size_t, const void *) =
-    atomic_forced_read (__malloc_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    {
-      *victimp = (*hook)(*bytesp, address);
-
-      if (*victimp != NULL)
-	memset (*victimp, 0, *bytesp);
-
-      return true;
-    }
-
   /* Memory is zeroed out in the AFTER hook.  */
   if (__glibc_unlikely (__malloc_debugging_hooks))
     {
diff --git a/malloc/malloc-compathooks.c b/malloc/malloc-compathooks.c
new file mode 100644
index 0000000000..6d1eaab774
--- /dev/null
+++ b/malloc/malloc-compathooks.c
@@ -0,0 +1,166 @@ 
+/* Malloc hooks compatibility DSO.
+   Copyright (C) 2021 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/>.  */
+
+#include <atomic.h>
+#include <libc-symbols.h>
+#include <shlib-compat.h>
+#include <string.h>
+#include <unistd.h>
+
+extern void (*__free_hook) (void *__ptr, const void *);
+compat_symbol_reference (libc, __free_hook, __free_hook, GLIBC_2_0);
+extern void * (*__malloc_hook) (size_t __size, const void *);
+compat_symbol_reference (libc, __malloc_hook, __malloc_hook, GLIBC_2_0);
+extern void * (*__realloc_hook)
+     (void *__ptr, size_t __size, const void *);
+compat_symbol_reference (libc, __realloc_hook, __realloc_hook, GLIBC_2_0);
+extern void * (*__memalign_hook)
+  (size_t __alignment, size_t __size, const void *);
+compat_symbol_reference (libc, __memalign_hook, __memalign_hook, GLIBC_2_0);
+
+/* Support only the glibc allocators.  */
+extern void *__libc_malloc (size_t);
+extern void __libc_free (void *);
+extern void *__libc_realloc (void *, size_t);
+extern void *__libc_memalign (size_t, size_t);
+extern void *__libc_valloc (size_t);
+extern void *__libc_pvalloc (size_t);
+extern void *__libc_calloc (size_t, size_t);
+
+static size_t pagesize;
+
+/* The allocator functions.  */
+
+static void *
+__compathook_malloc (size_t bytes)
+{
+  void *(*hook) (size_t, const void *) = atomic_forced_read (__malloc_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    return (*hook)(bytes, RETURN_ADDRESS (0));
+
+  return __libc_malloc (bytes);
+}
+strong_alias (__compathook_malloc, malloc)
+
+static void
+__compathook_free (void *mem)
+{
+  void (*hook) (void *, const void *) = atomic_forced_read (__free_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    {
+      (*hook)(mem, RETURN_ADDRESS (0));
+      return;
+    }
+  __libc_free (mem);
+}
+strong_alias (__compathook_free, free)
+
+static void *
+__compathook_realloc (void *oldmem, size_t bytes)
+{
+  void *(*hook) (void *, size_t, const void *) =
+    atomic_forced_read (__realloc_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    return (*hook)(oldmem, bytes, RETURN_ADDRESS (0));
+
+  return __libc_realloc (oldmem, bytes);
+}
+strong_alias (__compathook_realloc, realloc)
+
+static void *
+__compathook_memalign (size_t alignment, size_t bytes)
+{
+  void *(*hook) (size_t, size_t, const void *) =
+    atomic_forced_read (__memalign_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    return (*hook)(alignment, bytes, RETURN_ADDRESS (0));
+
+  return __libc_memalign (alignment, bytes);
+}
+strong_alias (__compathook_memalign, memalign)
+
+static void *
+__compathook_pvalloc (size_t bytes)
+{
+  void *(*hook) (size_t, size_t, const void *) =
+    atomic_forced_read (__memalign_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    {
+      size_t rounded_bytes;
+
+      if (!pagesize)
+	pagesize = sysconf (_SC_PAGESIZE);
+
+      /* ALIGN_UP with overflow check.  */
+      if (__glibc_unlikely (__builtin_add_overflow (bytes,
+						    pagesize - 1,
+						    &rounded_bytes)))
+	{
+	  errno = ENOMEM;
+	  return NULL;
+	}
+      rounded_bytes = rounded_bytes & -(pagesize - 1);
+      return (*hook)(pagesize, rounded_bytes, RETURN_ADDRESS (0));
+    }
+
+  return __libc_pvalloc (bytes);
+}
+strong_alias (__compathook_pvalloc, pvalloc)
+
+static void *
+__compathook_valloc (size_t bytes)
+{
+  void *(*hook) (size_t, size_t, const void *) =
+    atomic_forced_read (__memalign_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    {
+      if (!pagesize)
+	pagesize = sysconf (_SC_PAGESIZE);
+
+      return (*hook)(pagesize, bytes, RETURN_ADDRESS (0));
+    }
+
+  return __libc_valloc (bytes);
+}
+strong_alias (__compathook_valloc, valloc)
+
+static void *
+__compathook_calloc (size_t nmemb, size_t size)
+{
+  void *(*hook) (size_t, const void *) = atomic_forced_read (__malloc_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    {
+      size_t bytes;
+
+      if (__glibc_unlikely (__builtin_mul_overflow (nmemb, size, &bytes)))
+	{
+	  errno = ENOMEM;
+	  return NULL;
+	}
+
+      void *mem = (*hook)(bytes, RETURN_ADDRESS (0));
+
+      if (mem != NULL)
+	memset (mem, 0, bytes);
+
+      return mem;
+    }
+
+  return __libc_calloc (nmemb, size);
+}
+strong_alias (__compathook_calloc, calloc)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index c899619e50..f6d7309721 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -570,16 +570,6 @@  tag_at (void *ptr)
 #define HAVE_MREMAP 0
 #endif
 
-/* We may need to support __malloc_initialize_hook for backwards
-   compatibility.  */
-
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24)
-# define HAVE_MALLOC_INIT_HOOK 1
-#else
-# define HAVE_MALLOC_INIT_HOOK 0
-#endif
-
-
 /*
   This version of malloc supports the standard SVID/XPG mallinfo
   routine that returns a struct containing usage properties and
diff --git a/malloc/malloc.h b/malloc/malloc.h
index c1c0896d29..709fa454b5 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -165,20 +165,6 @@  extern void malloc_stats (void) __THROW;
 extern int malloc_info (int __options, FILE *__fp) __THROW;
 
 /* Hooks for debugging and user-defined versions. */
-extern void (*__MALLOC_HOOK_VOLATILE __free_hook) (void *__ptr,
-                                                   const void *)
-__MALLOC_DEPRECATED;
-extern void *(*__MALLOC_HOOK_VOLATILE __malloc_hook)(size_t __size,
-                                                     const void *)
-__MALLOC_DEPRECATED;
-extern void *(*__MALLOC_HOOK_VOLATILE __realloc_hook)(void *__ptr,
-                                                      size_t __size,
-                                                      const void *)
-__MALLOC_DEPRECATED;
-extern void *(*__MALLOC_HOOK_VOLATILE __memalign_hook)(size_t __alignment,
-                                                       size_t __size,
-                                                       const void *)
-__MALLOC_DEPRECATED;
 extern void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void)
   __MALLOC_DEPRECATED;
 
diff --git a/manual/memory.texi b/manual/memory.texi
index 28ec2e4e63..e66ecd582d 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -328,8 +328,6 @@  any time (or never).
 * Malloc Tunable Parameters::   Use @code{mallopt} to adjust allocation
                                  parameters.
 * Heap Consistency Checking::   Automatic checking for errors.
-* Hooks for Malloc::            You can use these hooks for debugging
-				 programs that use @code{malloc}.
 * Statistics of Malloc::        Getting information about how much
 				 memory your program is using.
 * Summary of Malloc::           Summary of @code{malloc} and related functions.
@@ -1388,170 +1386,6 @@  compatibility.  Both @code{MALLOC_CHECK_} and @samp{-lmcheck} should
 uncover the same bugs - but using @code{MALLOC_CHECK_} you don't need to
 recompile your application.
 
-@node Hooks for Malloc
-@subsubsection Memory Allocation Hooks
-@cindex allocation hooks, for @code{malloc}
-
-@Theglibc{} lets you modify the behavior of @code{malloc},
-@code{realloc}, and @code{free} by specifying appropriate hook
-functions.  You can use these hooks to help you debug programs that use
-dynamic memory allocation, for example.
-
-The hook variables are declared in @file{malloc.h}.
-@pindex malloc.h
-
-@defvar __malloc_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to the function that
-@code{malloc} uses whenever it is called.  You should define this
-function to look like @code{malloc}; that is, like:
-
-@smallexample
-void *@var{function} (size_t @var{size}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{malloc} function was called.  This value allows you to trace
-the memory consumption of the program.
-@end defvar
-
-@defvar __realloc_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to function that @code{realloc}
-uses whenever it is called.  You should define this function to look
-like @code{realloc}; that is, like:
-
-@smallexample
-void *@var{function} (void *@var{ptr}, size_t @var{size}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{realloc} function was called.  This value allows you to trace the
-memory consumption of the program.
-@end defvar
-
-@defvar __free_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to function that @code{free}
-uses whenever it is called.  You should define this function to look
-like @code{free}; that is, like:
-
-@smallexample
-void @var{function} (void *@var{ptr}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{free} function was called.  This value allows you to trace the
-memory consumption of the program.
-@end defvar
-
-@defvar __memalign_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to function that @code{aligned_alloc},
-@code{memalign}, @code{posix_memalign} and @code{valloc} use whenever they
-are called.  You should define this function to look like @code{aligned_alloc};
-that is, like:
-
-@smallexample
-void *@var{function} (size_t @var{alignment}, size_t @var{size}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{aligned_alloc}, @code{memalign}, @code{posix_memalign} or
-@code{valloc} functions are called.  This value allows you to trace the
-memory consumption of the program.
-@end defvar
-
-You must make sure that the function you install as a hook for one of
-these functions does not call that function recursively without restoring
-the old value of the hook first!  Otherwise, your program will get stuck
-in an infinite recursion.  Before calling the function recursively, one
-should make sure to restore all the hooks to their previous value.  When
-coming back from the recursive call, all the hooks should be resaved
-since a hook might modify itself.
-
-An issue to look out for is the time at which the hook functions
-can be safely installed.  If the hook functions call the @code{malloc}-related
-functions recursively, it is necessary that @code{malloc} has already properly
-initialized itself at the time when @code{__malloc_hook} etc. is
-assigned to.  On the other hand, if the hook functions provide a
-complete @code{malloc} implementation of their own, it is vital that the hooks
-are assigned to @emph{before} the very first @code{malloc} call has
-completed, because otherwise a chunk obtained from the ordinary,
-un-hooked @code{malloc} may later be handed to @code{__free_hook}, for example.
-
-Here is an example showing how to use @code{__malloc_hook} and
-@code{__free_hook} properly.  It installs a function that prints out
-information every time @code{malloc} or @code{free} is called.  We just
-assume here that @code{realloc} and @code{memalign} are not used in our
-program.
-
-@smallexample
-/* Prototypes for __malloc_hook, __free_hook */
-#include <malloc.h>
-
-/* Prototypes for our hooks.  */
-static void my_init_hook (void);
-static void *my_malloc_hook (size_t, const void *);
-static void my_free_hook (void*, const void *);
-
-static void
-my_init (void)
-@{
-  old_malloc_hook = __malloc_hook;
-  old_free_hook = __free_hook;
-  __malloc_hook = my_malloc_hook;
-  __free_hook = my_free_hook;
-@}
-
-static void *
-my_malloc_hook (size_t size, const void *caller)
-@{
-  void *result;
-  /* Restore all old hooks */
-  __malloc_hook = old_malloc_hook;
-  __free_hook = old_free_hook;
-  /* Call recursively */
-  result = malloc (size);
-  /* Save underlying hooks */
-  old_malloc_hook = __malloc_hook;
-  old_free_hook = __free_hook;
-  /* @r{@code{printf} might call @code{malloc}, so protect it too.} */
-  printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
-  /* Restore our own hooks */
-  __malloc_hook = my_malloc_hook;
-  __free_hook = my_free_hook;
-  return result;
-@}
-
-static void
-my_free_hook (void *ptr, const void *caller)
-@{
-  /* Restore all old hooks */
-  __malloc_hook = old_malloc_hook;
-  __free_hook = old_free_hook;
-  /* Call recursively */
-  free (ptr);
-  /* Save underlying hooks */
-  old_malloc_hook = __malloc_hook;
-  old_free_hook = __free_hook;
-  /* @r{@code{printf} might call @code{free}, so protect it too.} */
-  printf ("freed pointer %p\n", ptr);
-  /* Restore our own hooks */
-  __malloc_hook = my_malloc_hook;
-  __free_hook = my_free_hook;
-@}
-
-main ()
-@{
-  my_init ();
-  @dots{}
-@}
-@end smallexample
-
-The @code{mcheck} function (@pxref{Heap Consistency Checking}) works by
-installing such hooks.
-
 @c __morecore, __after_morecore_hook are undocumented
 @c It's not clear whether to document them.
 
@@ -1686,19 +1520,6 @@  Tell @code{malloc} to perform occasional consistency checks on
 dynamically allocated memory, and to call @var{abortfn} when an
 inconsistency is found.  @xref{Heap Consistency Checking}.
 
-@item void *(*__malloc_hook) (size_t @var{size}, const void *@var{caller})
-A pointer to a function that @code{malloc} uses whenever it is called.
-
-@item void *(*__realloc_hook) (void *@var{ptr}, size_t @var{size}, const void *@var{caller})
-A pointer to a function that @code{realloc} uses whenever it is called.
-
-@item void (*__free_hook) (void *@var{ptr}, const void *@var{caller})
-A pointer to a function that @code{free} uses whenever it is called.
-
-@item void (*__memalign_hook) (size_t @var{size}, size_t @var{alignment}, const void *@var{caller})
-A pointer to a function that @code{aligned_alloc}, @code{memalign},
-@code{posix_memalign} and @code{valloc} use whenever they are called.
-
 @item struct mallinfo2 mallinfo2 (void)
 Return information about the current dynamic memory usage.
 @xref{Statistics of Malloc}.
@@ -1733,7 +1554,7 @@  penalties for the program if the debugging mode is not enabled.
 
 @deftypefun void mtrace (void)
 @standards{GNU, mcheck.h}
-@safety{@prelim{}@mtunsafe{@mtsenv{} @mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtuinit{}}@asunsafe{@asuinit{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsfd{} @acsmem{}}}
+@safety{@prelim{}@mtunsafe{@mtsenv{} @mtasurace{:mtrace} @mtuinit{}}@asunsafe{@asuinit{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsfd{} @acsmem{}}}
 @c Like the mcheck hooks, these are not designed with thread safety in
 @c mind, because the hook pointers are temporarily modified without
 @c regard to other threads, signals or cancellation.
@@ -1758,10 +1579,10 @@  with the SUID or SGID bit set.
 
 If the named file is successfully opened, @code{mtrace} installs special
 handlers for the functions @code{malloc}, @code{realloc}, and
-@code{free} (@pxref{Hooks for Malloc}).  From then on, all uses of these
-functions are traced and protocolled into the file.  There is now of
-course a speed penalty for all calls to the traced functions so tracing
-should not be enabled during normal use.
+@code{free}.  From then on, all uses of these functions are traced and
+protocolled into the file.  There is now of course a speed penalty for all
+calls to the traced functions so tracing should not be enabled during normal
+use.
 
 This function is a GNU extension and generally not available on other
 systems.  The prototype can be found in @file{mcheck.h}.
@@ -1769,7 +1590,7 @@  systems.  The prototype can be found in @file{mcheck.h}.
 
 @deftypefun void muntrace (void)
 @standards{GNU, mcheck.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{} @aculock{} @acsfd{}}}
+@safety{@prelim{}@mtunsafe{@mtasurace{:mtrace} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{} @aculock{} @acsfd{}}}
 
 @c muntrace @mtasurace:mtrace @mtslocale @asucorrupt @ascuheap @acucorrupt @acsmem @aculock @acsfd
 @c  fprintf (fputs) dup @mtslocale @asucorrupt @ascuheap @acsmem @aculock @acucorrupt
diff --git a/sysdeps/generic/localplt.data b/sysdeps/generic/localplt.data
index 9b4f35786a..e2083c0ce6 100644
--- a/sysdeps/generic/localplt.data
+++ b/sysdeps/generic/localplt.data
@@ -4,6 +4,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/mach/hurd/i386/localplt.data b/sysdeps/mach/hurd/i386/localplt.data
index 47fbe1e2a7..94064ecbc5 100644
--- a/sysdeps/mach/hurd/i386/localplt.data
+++ b/sysdeps/mach/hurd/i386/localplt.data
@@ -6,6 +6,7 @@ 
 libc.so: calloc + REL R_386_GLOB_DAT
 libc.so: free + REL R_386_GLOB_DAT
 libc.so: malloc + REL R_386_GLOB_DAT
+libc.so: memalign + REL R_386_GLOB_DAT
 libc.so: realloc + REL R_386_GLOB_DAT
 libm.so: matherr + REL R_386_GLOB_DAT
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data
index 348b3f3793..2c14b652ef 100644
--- a/sysdeps/unix/sysv/linux/aarch64/localplt.data
+++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data
@@ -4,6 +4,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # If outline atomics are used, libgcc (built outside of glibc) may
diff --git a/sysdeps/unix/sysv/linux/alpha/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data
index 44bf36f4f1..43f6fdaea1 100644
--- a/sysdeps/unix/sysv/linux/alpha/localplt.data
+++ b/sysdeps/unix/sysv/linux/alpha/localplt.data
@@ -18,6 +18,7 @@  libc.so: _Unwind_Find_FDE
 libc.so: calloc + RELA R_ALPHA_GLOB_DAT
 libc.so: free + RELA R_ALPHA_GLOB_DAT
 libc.so: malloc + RELA R_ALPHA_GLOB_DAT
+libc.so: memalign + RELA R_ALPHA_GLOB_DAT
 libc.so: realloc + RELA R_ALPHA_GLOB_DAT
 libm.so: matherr + RELA R_ALPHA_GLOB_DAT
 # We used to offer inline functions that used this, so it must be exported.
diff --git a/sysdeps/unix/sysv/linux/arc/localplt.data b/sysdeps/unix/sysv/linux/arc/localplt.data
index ac5332caf7..4479e8ee8a 100644
--- a/sysdeps/unix/sysv/linux/arc/localplt.data
+++ b/sysdeps/unix/sysv/linux/arc/localplt.data
@@ -1,5 +1,6 @@ 
 libc.so: realloc
 libc.so: malloc
+libc.so: memalign
 libc.so: calloc
 libc.so: free
 # At -Os, a struct assignment in libgcc-static pulls this in
diff --git a/sysdeps/unix/sysv/linux/arm/localplt.data b/sysdeps/unix/sysv/linux/arm/localplt.data
index 78896444c6..eb315da2f1 100644
--- a/sysdeps/unix/sysv/linux/arm/localplt.data
+++ b/sysdeps/unix/sysv/linux/arm/localplt.data
@@ -1,6 +1,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: raise
 libc.so: realloc
 libm.so: matherr
diff --git a/sysdeps/unix/sysv/linux/csky/localplt.data b/sysdeps/unix/sysv/linux/csky/localplt.data
index 817ab2659a..0ed8650b65 100644
--- a/sysdeps/unix/sysv/linux/csky/localplt.data
+++ b/sysdeps/unix/sysv/linux/csky/localplt.data
@@ -4,6 +4,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
diff --git a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data
index baf857a750..09893d4dcf 100644
--- a/sysdeps/unix/sysv/linux/hppa/localplt.data
+++ b/sysdeps/unix/sysv/linux/hppa/localplt.data
@@ -4,6 +4,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libc.so: __sigsetjmp
 libc.so: _IO_funlockfile
diff --git a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data
index f9bf7fb410..5334875b4b 100644
--- a/sysdeps/unix/sysv/linux/i386/localplt.data
+++ b/sysdeps/unix/sysv/linux/i386/localplt.data
@@ -4,6 +4,7 @@  libc.so: _Unwind_Find_FDE + REL R_386_GLOB_DAT
 libc.so: calloc + REL R_386_GLOB_DAT
 libc.so: free + REL R_386_GLOB_DAT
 libc.so: malloc + REL R_386_GLOB_DAT
+libc.so: memalign + REL R_386_GLOB_DAT
 libc.so: realloc + REL R_386_GLOB_DAT
 libm.so: matherr + REL R_386_GLOB_DAT
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/ia64/localplt.data b/sysdeps/unix/sysv/linux/ia64/localplt.data
index 174fb88128..1c566a503e 100644
--- a/sysdeps/unix/sysv/linux/ia64/localplt.data
+++ b/sysdeps/unix/sysv/linux/ia64/localplt.data
@@ -1,6 +1,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 libm.so: matherrf
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data
index 42fa90508c..3c5efb7204 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data
@@ -2,6 +2,7 @@  libc.so: __m68k_read_tp
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data
index 34bd4c1aca..843f4e25f2 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data
@@ -3,6 +3,7 @@  libc.so: __m68k_read_tp
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/microblaze/localplt.data b/sysdeps/unix/sysv/linux/microblaze/localplt.data
index c3801314c9..0e98d5251e 100644
--- a/sysdeps/unix/sysv/linux/microblaze/localplt.data
+++ b/sysdeps/unix/sysv/linux/microblaze/localplt.data
@@ -2,6 +2,7 @@  libc.so: __errno_location
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The dynamic loader needs __tls_get_addr for TLS.
diff --git a/sysdeps/unix/sysv/linux/nios2/localplt.data b/sysdeps/unix/sysv/linux/nios2/localplt.data
index 17fcfdd4db..b37987c7c0 100644
--- a/sysdeps/unix/sysv/linux/nios2/localplt.data
+++ b/sysdeps/unix/sysv/linux/nios2/localplt.data
@@ -6,6 +6,7 @@  libc.so: __gedf2
 libc.so: malloc
 libc.so: __gtsf2 ?
 libc.so: __nesf2
+libc.so: memalign
 libc.so: __mulsf3
 libc.so: __floatunsisf
 libc.so: __addsf3
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
index c0af84eef7..a02dd5cc24 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
@@ -2,6 +2,7 @@  libc.so: _Unwind_Find_FDE
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
index 581e54b95c..d8072597b7 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
@@ -30,6 +30,7 @@  libc.so: abort ?
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: memset ?
 libc.so: realloc
 libm.so: copysignl ?
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data
index d69b7ae646..bb498fbe3a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data
@@ -1,6 +1,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/riscv/localplt.data b/sysdeps/unix/sysv/linux/riscv/localplt.data
index e6d5330d5b..0a235592c3 100644
--- a/sysdeps/unix/sysv/linux/riscv/localplt.data
+++ b/sysdeps/unix/sysv/linux/riscv/localplt.data
@@ -4,6 +4,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: memset ?
 libc.so: realloc
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/s390/localplt.data b/sysdeps/unix/sysv/linux/s390/localplt.data
index c0af84eef7..a02dd5cc24 100644
--- a/sysdeps/unix/sysv/linux/s390/localplt.data
+++ b/sysdeps/unix/sysv/linux/s390/localplt.data
@@ -2,6 +2,7 @@  libc.so: _Unwind_Find_FDE
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/sh/localplt.data b/sysdeps/unix/sysv/linux/sh/localplt.data
index 6491b9e37b..3225177c50 100644
--- a/sysdeps/unix/sysv/linux/sh/localplt.data
+++ b/sysdeps/unix/sysv/linux/sh/localplt.data
@@ -4,6 +4,7 @@ 
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libc.so: _Unwind_Find_FDE
 libc.so: _exit
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data
index 38309a1393..be51efd566 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data
@@ -16,6 +16,7 @@  libc.so: _Unwind_Find_FDE
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data
index 6a216f3a5a..809062d46c 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data
@@ -15,6 +15,7 @@  libc.so: _Unwind_Find_FDE
 libc.so: calloc
 libc.so: free
 libc.so: malloc
+libc.so: memalign
 libc.so: realloc
 libm.so: matherr
 # The TLS-enabled version of these functions is interposed from libc.so.
diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data
index d1f2e26612..8f41e92870 100644
--- a/sysdeps/x86_64/localplt.data
+++ b/sysdeps/x86_64/localplt.data
@@ -6,6 +6,7 @@ 
 libc.so: calloc + RELA R_X86_64_GLOB_DAT
 libc.so: free + RELA R_X86_64_GLOB_DAT
 libc.so: malloc + RELA R_X86_64_GLOB_DAT
+libc.so: memalign + RELA R_X86_64_GLOB_DAT
 libc.so: realloc + RELA R_X86_64_GLOB_DAT
 libm.so: matherr + RELA R_X86_64_GLOB_DAT
 # The TLS-enabled version of these functions is interposed from libc.so.