diff --git a/Makeconfig b/Makeconfig
index 1afe86475c..2c83ee252b 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -929,7 +929,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-extras
 
 in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
 				    $(libof-$(<F)) \
diff --git a/catgets/Makefile b/catgets/Makefile
index 36f6a226c3..941e5cb4ea 100644
--- a/catgets/Makefile
+++ b/catgets/Makefile
@@ -56,7 +56,8 @@ generated += tst-catgets.mtrace tst-catgets-mem.out
 
 generated-dirs += de
 
-tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace
+tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 ifeq ($(run-built-tests),yes)
 # This test just checks whether the program produces any error or not.
diff --git a/elf/Makefile b/elf/Makefile
index 9bdb9220c7..f29f2b1e11 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -204,7 +204,7 @@ endif
 endif
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-leaks1-mem.out \
-		 $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \
+		 $(objpfx)noload-mem.out \
 		 $(objpfx)tst-ldconfig-X.out
 endif
 tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@@ -802,7 +802,8 @@ $(objpfx)noload.out: $(objpfx)testobj5.so
 $(objpfx)noload-mem.out: $(objpfx)noload.out
 	$(common-objpfx)malloc/mtrace $(objpfx)noload.mtrace > $@; \
 	$(evaluate-test)
-noload-ENV = MALLOC_TRACE=$(objpfx)noload.mtrace
+noload-ENV = MALLOC_TRACE=$(objpfx)noload.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 LDFLAGS-nodelete = -rdynamic
 LDFLAGS-nodelmod1.so = -Wl,--enable-new-dtags,-z,nodelete
@@ -1206,8 +1207,10 @@ $(objpfx)tst-leaks1-static-mem.out: $(objpfx)tst-leaks1-static.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1-static.mtrace > $@; \
 	$(evaluate-test)
 
-tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace
-tst-leaks1-static-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1-static.mtrace
+tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
+tst-leaks1-static-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1-static.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)tst-addr1: $(libdl)
 
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index 06e161d9b8..3930890903 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -292,7 +292,8 @@ cpp-srcs-left := $(modules) $(generated-modules) $(libJIS-routines) \
 lib := iconvdata
 include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
 
-tst-loading-ENV = MALLOC_TRACE=$(objpfx)tst-loading.mtrace
+tst-loading-ENV = MALLOC_TRACE=$(objpfx)tst-loading.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 $(objpfx)mtrace-tst-loading.out: $(objpfx)tst-loading.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-loading.mtrace > $@; \
 	$(evaluate-test)
diff --git a/intl/tst-gettext.sh b/intl/tst-gettext.sh
index 0c65583149..c49f61586c 100755
--- a/intl/tst-gettext.sh
+++ b/intl/tst-gettext.sh
@@ -50,6 +50,7 @@ msgfmt -o ${objpfx}domaindir/existing-locale/LC_TIME/existing-time-domain.mo \
 ${test_program_prefix_before_env} \
 ${run_program_env} \
 MALLOC_TRACE=$malloc_trace \
+LD_PRELOAD=${common_objpfx}/malloc/libmalloc-extras.so \
 LOCPATH=${objpfx}localedir:${common_objpfx}localedata \
 ${test_program_prefix_after_env} \
 ${objpfx}tst-gettext > ${objpfx}tst-gettext.out ${objpfx}domaindir
diff --git a/libio/Makefile b/libio/Makefile
index cbe14a8e25..f99138dd48 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -152,9 +152,12 @@ CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
 
 tst_wprintf2-ARGS = "Some Text"
 
-test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
-tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
-tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
+test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
+tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
+tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 generated += test-fmemopen.mtrace test-fmemopen.check
 generated += tst-fopenloc.mtrace tst-fopenloc.check
diff --git a/localedata/Makefile b/localedata/Makefile
index d51064adec..71e87c88d6 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -385,7 +385,8 @@ $(INSTALL-SUPPORTED-LOCALES): install-locales-dir
 tst-setlocale-ENV = LC_ALL=ja_JP.EUC-JP
 tst-wctype-ENV = LC_ALL=ja_JP.EUC-JP
 
-tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace
+tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace \
+	LD_PRELOAD=$(objpfx)/../malloc/libmalloc-extras.so
 $(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@; \
 	$(evaluate-test)
diff --git a/malloc/Makefile b/malloc/Makefile
index 7d54bad866..dc5dd40815 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -41,8 +41,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 
 tests-static := \
 	 tst-interpose-static-nothread \
-	 tst-interpose-static-thread \
-	 tst-malloc-usable-static \
+	 tst-interpose-static-thread
 
 tests-internal := tst-mallocstate tst-scratch_buffer
 
@@ -53,8 +52,8 @@ tests-internal += \
 	 tst-dynarray-at-fail \
 
 ifneq (no,$(have-tunables))
-tests += tst-malloc-usable-tunables
-tests-static += tst-malloc-usable-static-tunables
+# tests += tst-malloc-usable-tunables
+# tests-static += tst-malloc-usable-static-tunables
 endif
 
 tests += $(tests-static)
@@ -78,7 +77,7 @@ install-lib := libmcheck.a
 non-lib.a := libmcheck.a
 
 # Additional library.
-extra-libs = libmemusage
+extra-libs = libmemusage libmalloc-extras
 extra-libs-others = $(extra-libs)
 
 # Helper objects for some tests.
@@ -143,6 +142,11 @@ $(objpfx)memusagestat.o: sysincludes = # nothing
 endif
 endif
 
+libmalloc-extras-routines = malloc-extras
+LDLIBS-libmalloc-extras.so = $(shared-thread-library)
+LDFLAGS-malloc-extras.so = -Wl,-z,nodelete
+$(objpfx)libmalloc-extras.so: $(libdl)
+
 # Another goal which can be used to override the configure decision.
 .PHONY: do-memusagestat
 do-memusagestat: $(objpfx)memusagestat
@@ -189,10 +193,12 @@ endif
 endif
 endif
 
+tst-mtrace-ENV = LD_PRELOAD=$(objpfx)libmalloc-extras.so
 tst-mcheck-ENV = MALLOC_CHECK_=3
-tst-malloc-usable-ENV = MALLOC_CHECK_=3
+tst-malloc-usable-ENV = MALLOC_CHECK_=3 LD_PRELOAD=$(objpfx)libmalloc-extras.so
 tst-malloc-usable-static-ENV = $(tst-malloc-usable-ENV)
-tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3
+tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 \
+	LD_PRELOAD=$(objdir)libmalloc-extras.so
 tst-malloc-usable-static-tunables-ENV = $(tst-malloc-usable-tunables-ENV)
 
 ifeq ($(experimental-malloc),yes)
@@ -239,12 +245,14 @@ $(objpfx)tst-interpose-static-nothread: $(objpfx)tst-interpose-aux-nothread.o
 $(objpfx)tst-interpose-static-thread: \
   $(objpfx)tst-interpose-aux-thread.o $(static-thread-library)
 
-tst-dynarray-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace
+tst-dynarray-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 $(objpfx)tst-dynarray-mem.out: $(objpfx)tst-dynarray.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray.mtrace > $@; \
 	$(evaluate-test)
 
-tst-dynarray-fail-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace
+tst-dynarray-fail-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 $(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray-fail.mtrace > $@; \
 	$(evaluate-test)
diff --git a/malloc/Versions b/malloc/Versions
index 2357cff3da..883a6a56b8 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -92,5 +92,8 @@ libc {
     __libc_alloc_buffer_copy_bytes;
     __libc_alloc_buffer_copy_string;
     __libc_alloc_buffer_create_failure;
+
+    __glibc_mtrace_hook;
+    __glibc_mtrace_hook_enabled;
   }
 }
diff --git a/malloc/hooks.c b/malloc/hooks.c
index 95aefd0bfc..b35f5bf9cf 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -29,7 +29,11 @@ malloc_hook_ini (size_t sz, const void *caller)
 {
   __malloc_hook = NULL;
   ptmalloc_init ();
-  return __libc_malloc (sz);
+  /* We can't call __libc_malloc because it doesn't support hooks; we
+     have to re-call the interposed malloc which does, if it's present
+     (which it should be, else we wouldn't get here in the first
+     place.  */
+  return malloc (sz);
 }
 
 static void *
@@ -38,7 +42,7 @@ realloc_hook_ini (void *ptr, size_t sz, const void *caller)
   __malloc_hook = NULL;
   __realloc_hook = NULL;
   ptmalloc_init ();
-  return __libc_realloc (ptr, sz);
+  return realloc (ptr, sz);
 }
 
 static void *
@@ -46,7 +50,7 @@ memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
 {
   __memalign_hook = NULL;
   ptmalloc_init ();
-  return __libc_memalign (alignment, sz);
+  return memalign (alignment, sz);
 }
 
 /* Whether we are using malloc checking.  */
diff --git a/malloc/malloc-extras.c b/malloc/malloc-extras.c
new file mode 100644
index 0000000000..ccffaaac97
--- /dev/null
+++ b/malloc/malloc-extras.c
@@ -0,0 +1,814 @@
+/* Provide malloc hook functionality outside of libc.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <malloc.h>
+#include <errno.h>
+#include <libintl.h>
+#include <shlib-compat.h>
+#include <libc-internal.h>
+#include <stdarg.h>
+
+#include "malloc-internal.h"
+#include "mcheck.h"
+
+static void *(*next_malloc) (size_t) = NULL;
+static void (*next_free) (void *) = NULL;
+static void *(*next_realloc) (void *, size_t) = NULL;
+static void *(*next_calloc) (size_t, size_t) = NULL;
+static void *(*next_memalign) (size_t, size_t) = NULL;
+static size_t (*next_malloc_usable_size) (void *) = NULL;
+
+#define TRACE_BUFFER_SIZE 512
+
+static FILE *mallstream;
+static const char mallenv[] = "MALLOC_TRACE";
+static char *malloc_trace_buffer;
+
+__libc_lock_define_initialized (static, lock);
+
+#define TRACE_LOCK(caller, info)		\
+  caller = RETURN_ADDRESS (0);			\
+  dladdr (caller, &info);			\
+  __libc_lock_lock (lock);
+
+#define TRACE_LOCK_N(caller, info)		\
+  dladdr (caller, &info);			\
+  __libc_lock_lock (lock);
+
+#define TRACE_UNLOCK() \
+  __libc_lock_unlock (lock);
+
+
+/*======================================================================*/
+/* mtrace support.  */
+
+static void
+tr_where (const void *caller, Dl_info *info)
+{
+  if (caller != NULL)
+    {
+      if (info != NULL)
+        {
+	  fprintf (mallstream, "@ %s%s",
+		   info->dli_fname ? : "", info->dli_fname ? ":" : "");
+
+          if (info->dli_sname != NULL)
+            {
+	      if (caller > (const void *) info->dli_saddr)
+		fprintf (mallstream, "(%s+0x%lx)", info->dli_sname,
+			 (long unsigned)(caller - (const void *) info->dli_saddr));
+	      else
+		fprintf (mallstream, "(%s-0x%lx)", info->dli_sname,
+			 (long unsigned)((const void *) info->dli_saddr - caller));
+            }
+
+          fprintf (mallstream, "[%p] ", caller);
+        }
+      else
+        fprintf (mallstream, "@ [%p] ", caller);
+    }
+}
+
+
+/*======================================================================*/
+/* mcheck support. */
+
+/* Function to call when something awful happens.  */
+static void (*abortfunc) (enum mcheck_status);
+
+static int __malloc_extras_initialized = 0;
+
+/* Arbitrary magical numbers.  */
+#define MAGICWORD       0xfedabeeb
+#define MAGICFREE       0xd8675309
+#define MAGICBYTE       ((char) 0xd7)
+#define MALLOCFLOOD     ((char) 0x93)
+#define FREEFLOOD       ((char) 0x95)
+
+struct hdr
+{
+  size_t size;                  /* Exact size requested by user.  */
+  unsigned long int magic;      /* Magic number to check header integrity.  */
+  struct hdr *prev;
+  struct hdr *next;
+  void *block;                  /* Real block allocated, for memalign.  */
+  unsigned long int magic2;     /* Extra, keeps us doubleword aligned.  */
+};
+
+/* This is the beginning of the list of all memory blocks allocated.
+   It is only constructed if the pedantic testing is requested.  */
+static struct hdr *root;
+
+static int mcheck_used;
+
+/* Nonzero if pedentic checking of all blocks is requested.  */
+static int pedantic;
+
+//#if defined _LIBC || defined STDC_HEADERS || defined USG
+//# include <string.h>
+//# define flood memset
+//#else
+static void flood (void *, int, size_t);
+static void
+flood (void *ptr, int val, size_t size)
+{
+  char *cp = ptr;
+  while (size--)
+    *cp++ = val;
+}
+//#endif
+
+static enum mcheck_status
+checkhdr (const struct hdr *hdr)
+{
+  enum mcheck_status status;
+
+  if (!mcheck_used)
+    /* Maybe the mcheck used is disabled?  This happens when we find
+       an error and report it.  */
+    return MCHECK_OK;
+
+  switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
+    {
+    default:
+      status = MCHECK_HEAD;
+      break;
+    case MAGICFREE:
+      status = MCHECK_FREE;
+      break;
+    case MAGICWORD:
+      if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+        status = MCHECK_TAIL;
+      else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
+        status = MCHECK_HEAD;
+      else
+        status = MCHECK_OK;
+      break;
+    }
+  if (status != MCHECK_OK)
+    {
+      mcheck_used = 0;
+      (*abortfunc) (status);
+      mcheck_used = 1;
+    }
+  return status;
+}
+
+void
+mcheck_check_all (void)
+{
+  /* Walk through all the active blocks and test whether they were tampered
+     with.  */
+  struct hdr *runp = root;
+
+  /* Temporarily turn off the checks.  */
+  pedantic = 0;
+
+  while (runp != NULL)
+    {
+      (void) checkhdr (runp);
+
+      runp = runp->next;
+    }
+
+  /* Turn checks on again.  */
+  pedantic = 1;
+}
+#ifdef _LIBC
+libc_hidden_def (mcheck_check_all)
+#endif
+
+static void
+unlink_blk (struct hdr *ptr)
+{
+  if (ptr->next != NULL)
+    {
+      ptr->next->prev = ptr->prev;
+      ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
+                                      + (uintptr_t) ptr->next->next);
+    }
+  if (ptr->prev != NULL)
+    {
+      ptr->prev->next = ptr->next;
+      ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
+                                      + (uintptr_t) ptr->prev->next);
+    }
+  else
+    root = ptr->next;
+}
+
+static void
+link_blk (struct hdr *hdr)
+{
+  hdr->prev = NULL;
+  hdr->next = root;
+  root = hdr;
+  hdr->magic = MAGICWORD ^ (uintptr_t) hdr->next;
+
+  /* And the next block.  */
+  if (hdr->next != NULL)
+    {
+      hdr->next->prev = hdr;
+      hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
+                                      + (uintptr_t) hdr->next->next);
+    }
+}
+
+__attribute__ ((noreturn))
+static void
+mabort (enum mcheck_status status)
+{
+  const char *msg;
+  switch (status)
+    {
+    case MCHECK_OK:
+      msg = _ ("memory is consistent, library is buggy\n");
+      break;
+    case MCHECK_HEAD:
+      msg = _ ("memory clobbered before allocated block\n");
+      break;
+    case MCHECK_TAIL:
+      msg = _ ("memory clobbered past end of allocated block\n");
+      break;
+    case MCHECK_FREE:
+      msg = _ ("block freed twice\n");
+      break;
+    default:
+      msg = _ ("bogus mcheck_status, library is buggy\n");
+      break;
+    }
+#ifdef _LIBC
+  __libc_fatal (msg);
+#else
+  fprintf (stderr, "mcheck: %s", msg);
+  fflush (stderr);
+  abort ();
+#endif
+}
+
+/* Memory barrier so that GCC does not optimize out the argument.  */
+#define malloc_opt_barrier(x) \
+  ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
+
+int
+mcheck (void (*func) (enum mcheck_status))
+{
+  abortfunc = (func != NULL) ? func : &mabort;
+  setbuf (stdout, NULL);
+
+  /* These hooks may not be safely inserted if malloc is already in use.  */
+  if (__malloc_extras_initialized <= 0 && !mcheck_used)
+    {
+      /* We call malloc () once here to ensure it is initialized.  */
+      void *p = malloc (0);
+      p = realloc (p, 16);
+      void *p2 = memalign (4, 0);
+      /* GCC might optimize out the malloc/free pair without a barrier.  */
+      p = malloc_opt_barrier (p);
+      p2 = malloc_opt_barrier (p2);
+      free (p);
+      free (p2);
+
+      mcheck_used = 1;
+    }
+
+  return mcheck_used ? 0 : -1;
+}
+#ifdef _LIBC
+libc_hidden_def (mcheck)
+#endif
+
+int
+mcheck_pedantic (void (*func) (enum mcheck_status))
+{
+  int res = mcheck (func);
+  if (res == 0)
+    pedantic = 1;
+  return res;
+}
+
+enum mcheck_status
+mprobe (void *ptr)
+{
+  return mcheck_used ? checkhdr (((struct hdr *) ptr) - 1) : MCHECK_DISABLED;
+}
+
+/* For these, a round/align of zero means "don't".  */
+
+#define cfa() __builtin_return_address (0)
+
+#define MCHECK_PRE(size, align_ptr_to)			\
+  if (mcheck_used)							\
+    {									\
+      if (size > ~((size_t) 0) - (sizeof (struct hdr) + 1) - align_ptr_to) \
+	{								\
+	  __set_errno (ENOMEM);						\
+	  return NULL;							\
+	}								\
+      size += align_ptr_to;						\
+      size += sizeof (struct hdr) + 1;					\
+    }
+
+
+#define MCHECK_POST_NOFLOOD(ptr, original_size, align_to)	\
+  if (mcheck_used)						\
+    {								\
+      void *block = (void *) ptr;				\
+      struct hdr *hdr = (struct hdr *) block;			\
+      ptr = (void *) (hdr + 1);					\
+      if (align_to)						\
+        {							\
+          ptr = PTR_ALIGN_UP (ptr, align_to);			\
+          hdr = (struct hdr *)ptr - 1;				\
+        }							\
+      hdr->size = original_size;				\
+      link_blk (hdr);						\
+      hdr->block = (void *) block;				\
+      hdr->magic2 = (uintptr_t) block ^ MAGICWORD;		\
+      ((char *) &hdr[1])[original_size] = MAGICBYTE;		\
+    }
+    
+
+#define MCHECK_POST(ptr, original_size, align_to)		\
+  if (mcheck_used)						\
+    {								\
+      MCHECK_POST_NOFLOOD (ptr, original_size, align_to);	\
+      flood (ptr, MALLOCFLOOD, original_size);			\
+    }
+
+#define MCHECK_PREFREE(ptr)			  \
+  if (mcheck_used && ptr != NULL)		  \
+    {						  \
+      struct hdr *hdr = ((struct hdr *) ptr) - 1; \
+      checkhdr (hdr);				  \
+      hdr->magic = MAGICFREE;			  \
+      hdr->magic2 = MAGICFREE;			  \
+      unlink_blk (hdr);				  \
+      hdr->prev = hdr->next = NULL;		  \
+      flood (ptr, FREEFLOOD, hdr->size);	  \
+      ptr = hdr->block;				  \
+    }
+
+/*======================================================================*/
+/* mallwatch, hooks */
+
+/* Address to breakpoint on accesses to... */
+void *mallwatch = (void *) (-1);
+
+/* This function is called when the block being alloc'd, realloc'd, or
+   freed has an address matching the variable "mallwatch".  In a debugger,
+   set "mallwatch" to the address of interest, then put a breakpoint on
+   tr_break.  */
+
+extern void tr_break (void) __THROW;
+libc_hidden_proto (tr_break)
+void __attribute__ ((noinline))
+tr_break (void)
+{
+  /* Never optimize it away either.  */
+  asm ("");
+}
+libc_hidden_def (tr_break)
+
+static int recursing = 0;
+
+#define HOOK(func, erv)						\
+  if (next_##func == NULL)					\
+    {								\
+      int r;							\
+      r = atomic_load_acquire (&recursing);			\
+      if (r)							\
+	return erv;						\
+      __typeof__ (next_##func) tmp;				\
+      atomic_add (&recursing, 1);				\
+      tmp = dlsym (RTLD_NEXT, #func);				\
+      atomic_store_relaxed (&next_##func, tmp);			\
+      if (tmp == NULL)						\
+	abort ();						\
+      atomic_add (&recursing, -1);				\
+      atomic_store_relaxed (&__malloc_extras_initialized, 1);	\
+    }
+
+void *
+malloc (size_t sz)
+{
+  void *rv;
+  size_t original_size = sz;
+  void *caller;
+  Dl_info info;
+
+  void *(*hook) (size_t, const void *)
+    = atomic_forced_read (__malloc_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    return (*hook) (sz, RETURN_ADDRESS (0));
+
+  HOOK (malloc, NULL);
+
+  MCHECK_PRE (sz, 0);
+
+  rv =  next_malloc (sz);
+
+  MCHECK_POST (rv, original_size, 0);
+
+  if (mallstream)
+    {
+      TRACE_LOCK (caller, info);
+      tr_where (caller, &info);
+      /* We could be printing a NULL here; that's OK.  */
+      fprintf (mallstream, "+ %p %#lx\n", rv, (unsigned long int) original_size);
+      TRACE_UNLOCK ();
+   }
+
+  if (rv == mallwatch)
+    tr_break ();
+
+  return rv;
+}
+
+void 
+free (void *ptr)
+{
+  void *caller;
+  Dl_info info;
+
+  if (ptr == NULL)
+    return;
+
+  void (*hook) (void *, const void *)
+    = atomic_forced_read (__free_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    {
+      (*hook)(ptr, RETURN_ADDRESS (0));
+      return;
+    }
+
+  HOOK (free, );
+
+  if (mallstream && ptr)
+    {
+      TRACE_LOCK (caller, info);
+      tr_where (caller, &info);
+      /* We could be printing a NULL here; that's OK.  */
+      fprintf (mallstream, "- %p\n", ptr);
+      TRACE_UNLOCK ();
+   }
+
+  if (ptr == mallwatch)
+    tr_break ();
+
+  MCHECK_PREFREE (ptr);
+
+  next_free (ptr);
+
+  return;
+}
+
+void *
+realloc (void *ptr, size_t sz)
+{
+  void *rv;
+  size_t original_size = sz;
+  void *caller;
+  Dl_info info;
+
+  void *(*hook) (void *, size_t, const void *) =
+    atomic_forced_read (__realloc_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    return (*hook)(ptr, sz, RETURN_ADDRESS (0));
+
+  HOOK (realloc, NULL);
+
+  if (ptr == mallwatch)
+    tr_break ();
+
+  MCHECK_PREFREE (ptr);
+  MCHECK_PRE (sz, 0);
+
+  rv = next_realloc (ptr, sz);
+
+  MCHECK_POST (ptr, original_size, 0);
+
+  if (mallstream)
+    {
+      TRACE_LOCK (caller, info);
+      tr_where (caller, &info);
+
+      if (rv == NULL)
+	{
+	  if (original_size != 0)
+	    /* Failed realloc.  */
+	    fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) original_size);
+	  else
+	    fprintf (mallstream, "- %p\n", ptr);
+	}
+      else if (ptr == NULL)
+	fprintf (mallstream, "+ %p %#lx\n", rv, (unsigned long int) original_size);
+      else
+	{
+	  fprintf (mallstream, "< %p\n", ptr);
+	  tr_where (caller, &info);
+	  fprintf (mallstream, "> %p %#lx\n", rv, (unsigned long int) original_size);
+	}
+
+      TRACE_UNLOCK ();
+    }
+
+  if (rv == mallwatch)
+    tr_break ();
+
+  return rv;
+}
+
+void *
+calloc (size_t sz1, size_t sz2)
+{
+  void *rv;
+  size_t original_size;
+  size_t sz = sz1 * sz2;
+  void *caller;
+  Dl_info info;
+
+#define HALF_INTERNAL_SIZE_T \
+  (((size_t) 1) << (8 * sizeof (size_t) / 2))
+  if (__builtin_expect ((sz1 | sz2) >= HALF_INTERNAL_SIZE_T, 0))
+    {
+      if (sz1 != 0 && sz / sz1 != sz2)
+        {
+          __set_errno (ENOMEM);
+          return 0;
+        }
+    }
+
+  original_size = sz;
+
+  void *(*hook) (size_t, const void *) =
+    atomic_forced_read (__malloc_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    {
+      rv = (*hook)(sz, RETURN_ADDRESS (0));
+      if (rv == 0)
+	return 0;
+
+      memset (rv, 0, sz);
+
+      if (rv == mallwatch)
+	tr_break ();
+
+      return rv;
+    }
+
+  HOOK (calloc, NULL);
+
+  MCHECK_PRE (sz, 0);
+
+  rv = next_calloc (sz, 1);
+
+  MCHECK_POST_NOFLOOD (rv, sz, 0);
+
+  if (mallstream)
+    {
+      TRACE_LOCK (caller, info);
+      tr_where (caller, &info);
+      /* We could be printing a NULL here; that's OK.  */
+      fprintf (mallstream, "+ %p %#lx\n", rv, (unsigned long int) original_size);
+      TRACE_UNLOCK ();
+   }
+
+  if (rv == mallwatch)
+    tr_break ();
+
+  return rv;
+}
+
+static void *
+memalign_common (size_t sz1, size_t sz2, void *caller)
+{
+  void *rv;
+  size_t original_size = sz2;
+  Dl_info info;
+
+  void *(*hook) (size_t, size_t, const void *) =
+    atomic_forced_read (__memalign_hook);
+  if (__builtin_expect (hook != NULL, 0))
+    return (*hook)(sz1, sz2, RETURN_ADDRESS (0));
+
+  HOOK (memalign, NULL);
+
+  MCHECK_PRE (sz2, sz1);
+
+  rv =  next_memalign (sz1, sz2);
+
+  MCHECK_POST (rv, original_size, sz1);
+
+  if (mallstream)
+    {
+      TRACE_LOCK_N (caller, info);
+      tr_where (caller, &info);
+      /* We could be printing a NULL here; that's OK.  */
+      fprintf (mallstream, "+ %p %#lx\n", rv, (unsigned long int) original_size);
+      TRACE_UNLOCK ();
+   }
+
+  if (rv == mallwatch)
+    tr_break ();
+
+  return rv;
+}
+
+void *
+memalign (size_t sz1, size_t sz2)
+{
+  return memalign_common (sz1, sz2, RETURN_ADDRESS (0));
+}
+
+int
+posix_memalign (void **memptr, size_t alignment, size_t size)
+{
+  void *rvptr;
+
+  /* Test whether the SIZE argument is valid.  It must be a power of
+     two multiple of sizeof (void *).  */
+  if (alignment % sizeof (void *) != 0
+      || !powerof2 (alignment / sizeof (void *))
+      || alignment == 0)
+    return EINVAL;
+
+  rvptr = memalign_common (alignment, size, RETURN_ADDRESS (0));
+
+  if (rvptr)
+    {
+      *memptr = rvptr;
+      return 0;
+    }
+
+  return ENOMEM;
+}
+
+static size_t remembered_pagesize = 0;
+
+static inline size_t
+pagesize (void)
+{
+  size_t rv = atomic_load_relaxed (&remembered_pagesize);
+  if (remembered_pagesize == 0)
+    {
+      rv = sysconf (_SC_PAGESIZE);
+      atomic_store_relaxed (&remembered_pagesize, rv);
+    }
+  return rv;
+}
+
+void *
+valloc (size_t sz)
+{
+  return memalign_common (sysconf (_SC_PAGESIZE), sz, RETURN_ADDRESS (0));
+}
+
+void *
+pvalloc (size_t sz)
+{
+  size_t rounded_bytes = ALIGN_UP (sz, pagesize ());
+  return memalign_common (pagesize (), rounded_bytes, RETURN_ADDRESS (0));
+}
+
+size_t
+malloc_usable_size (void *ptr)
+{
+  size_t rv;
+
+  HOOK (malloc_usable_size, 0);
+
+  if (!mcheck_used)
+    rv = next_malloc_usable_size (ptr);
+  else
+    {
+      struct hdr *hdr = (struct hdr *) ptr;
+      -- hdr;
+      rv = hdr->size;
+    }
+
+  return rv;
+}
+
+/*======================================================================*/
+
+/* This function gets called to make sure all memory the library
+   allocates get freed and so does not irritate the user when studying
+   the mtrace output.  */
+static void
+release_libc_mem (void)
+{
+  /* Only call the free function if we still are running in mtrace mode.  */
+  if (mallstream != NULL)
+    __libc_freeres ();
+}
+
+
+static void
+local_mtrace (void)
+{
+  char *mallfile;
+  static int added_atexit_handler = 0;
+
+  /* Don't panic if we're called more than once.  */
+  if (mallstream != NULL)
+    {
+      fprintf (mallstream, "= Restart?\n");
+      return;
+    }
+
+  mallfile = getenv (mallenv);
+  if (mallfile != NULL || mallwatch != NULL)
+    {
+      char *mtb = malloc (TRACE_BUFFER_SIZE);
+      if (mtb == NULL)
+        return;
+
+      mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
+      if (mallstream != NULL)
+        {
+          /* Be sure it doesn't malloc its buffer!  */
+          malloc_trace_buffer = mtb;
+          setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
+          fprintf (mallstream, "= Start\n");
+
+	  if (!added_atexit_handler)
+            {
+              added_atexit_handler = 1;
+              atexit ((void (*)(void))release_libc_mem);
+            }
+
+        }
+      else
+        free (mtb);
+    }
+}
+
+static void
+local_muntrace (void)
+{
+  if (mallstream == NULL)
+    return;
+
+  /* Do the reverse of what done in mtrace: first reset the hooks and
+     MALLSTREAM, and only after that write the trailer and close the
+     file.  */
+  FILE *f = mallstream;
+  mallstream = NULL;
+
+  fprintf (f, "= End\n");
+  fclose (f);
+}
+
+/*======================================================================*/
+/* user interface */
+
+extern void (*__glibc_mtrace_hook)(int);
+extern int __glibc_mtrace_hook_enabled;
+
+void
+__glibc_mtrace_hook_func (int enable_it)
+{
+  if (enable_it)
+    local_mtrace ();
+  else
+    local_muntrace ();
+}
+
+void __attribute__ ((constructor))
+mtrace_extras_ctor (void)
+{
+  __glibc_mtrace_hook = __glibc_mtrace_hook_func;
+  if (__glibc_mtrace_hook_enabled)
+    __glibc_mtrace_hook (1);
+}
+
+void __attribute__ ((destructor))
+mtrace_extras_dtor (void)
+{
+  if (mallstream)
+    {
+      __libc_freeres ();
+      fprintf (mallstream, "= Unload?\n");
+    }
+}
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 9614954975..e01703681f 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -463,6 +463,12 @@ void *(*__morecore)(ptrdiff_t) = __default_morecore;
 # define HAVE_MALLOC_INIT_HOOK 0
 #endif
 
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24)
+# define HAVE_MALLOC_HOOKS 1
+#else
+# define HAVE_MALLOC_HOOKS 0
+#endif
+
 
 /*
   This version of malloc supports the standard SVID/XPG mallinfo
@@ -1014,8 +1020,6 @@ static void*  _mid_memalign(size_t, size_t, void *);
 
 static void malloc_printerr(const char *str) __attribute__ ((noreturn));
 
-static void* mem2mem_check(void *p, size_t sz);
-static void top_check(void);
 static void munmap_chunk(mchunkptr p);
 #if HAVE_MREMAP
 static mchunkptr mremap_chunk(mchunkptr p, size_t new_size);
@@ -1847,6 +1851,12 @@ static void     malloc_consolidate (mstate);
 # define weak_variable weak_function
 #endif
 
+#if HAVE_MALLOC_INIT_HOOK
+void weak_variable (*__malloc_initialize_hook) (void) = NULL;
+compat_symbol (libc, __malloc_initialize_hook,
+	       __malloc_initialize_hook, GLIBC_2_0);
+#endif
+
 /* Forward declarations.  */
 static void *malloc_hook_ini (size_t sz,
                               const void *caller) __THROW;
@@ -1855,11 +1865,6 @@ static void *realloc_hook_ini (void *ptr, size_t sz,
 static void *memalign_hook_ini (size_t alignment, size_t sz,
                                 const void *caller) __THROW;
 
-#if HAVE_MALLOC_INIT_HOOK
-void weak_variable (*__malloc_initialize_hook) (void) = NULL;
-compat_symbol (libc, __malloc_initialize_hook,
-	       __malloc_initialize_hook, GLIBC_2_0);
-#endif
 
 void weak_variable (*__free_hook) (void *__ptr,
                                    const void *) = NULL;
@@ -2490,14 +2495,7 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
           LIBC_PROBE (memory_sbrk_more, 2, brk, size);
         }
 
-      if (brk != (char *) (MORECORE_FAILURE))
-        {
-          /* Call the `morecore' hook if necessary.  */
-          void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
-          if (__builtin_expect (hook != NULL, 0))
-            (*hook)();
-        }
-      else
+      if (brk == (char *) (MORECORE_FAILURE))
         {
           /*
              If have mmap, try using it as a backup when MORECORE fails or
@@ -2634,13 +2632,6 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
                       correction = 0;
                       snd_brk = (char *) (MORECORE (0));
                     }
-                  else
-                    {
-                      /* Call the `morecore' hook if necessary.  */
-                      void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
-                      if (__builtin_expect (hook != NULL, 0))
-                        (*hook)();
-                    }
                 }
 
               /* handle non-contiguous cases */
@@ -2798,10 +2789,6 @@ systrim (size_t pad, mstate av)
        */
 
       MORECORE (-extra);
-      /* Call the `morecore' hook if necessary.  */
-      void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
-      if (__builtin_expect (hook != NULL, 0))
-        (*hook)();
       new_brk = (char *) (MORECORE (0));
 
       LIBC_PROBE (memory_sbrk_less, 2, new_brk, extra);
@@ -3029,10 +3016,8 @@ __libc_malloc (size_t bytes)
   mstate ar_ptr;
   void *victim;
 
-  void *(*hook) (size_t, const void *)
-    = atomic_forced_read (__malloc_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    return (*hook)(bytes, RETURN_ADDRESS (0));
+  if (__malloc_initialized < 0)
+    ptmalloc_init ();
 #if USE_TCACHE
   /* int_free also calls request2size, be careful to not pad twice.  */
   size_t tbytes;
@@ -3087,13 +3072,8 @@ __libc_free (void *mem)
   mstate ar_ptr;
   mchunkptr p;                          /* chunk corresponding to mem */
 
-  void (*hook) (void *, const void *)
-    = atomic_forced_read (__free_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    {
-      (*hook)(mem, RETURN_ADDRESS (0));
-      return;
-    }
+  if (__malloc_initialized < 0)
+    ptmalloc_init ();
 
   if (mem == 0)                              /* free(0) has no effect */
     return;
@@ -3133,10 +3113,8 @@ __libc_realloc (void *oldmem, size_t bytes)
 
   void *newp;             /* chunk to return */
 
-  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));
+  if (__malloc_initialized < 0)
+    ptmalloc_init ();
 
 #if REALLOC_ZERO_BYTES_FREES
   if (bytes == 0 && oldmem != NULL)
@@ -3262,11 +3240,6 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
   mstate ar_ptr;
   void *p;
 
-  void *(*hook) (size_t, size_t, const void *) =
-    atomic_forced_read (__memalign_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    return (*hook)(alignment, bytes, address);
-
   /* If we need less alignment than we give anyway, just relay to malloc.  */
   if (alignment <= MALLOC_ALIGNMENT)
     return __libc_malloc (bytes);
@@ -3385,17 +3358,8 @@ __libc_calloc (size_t n, size_t elem_size)
         }
     }
 
-  void *(*hook) (size_t, const void *) =
-    atomic_forced_read (__malloc_hook);
-  if (__builtin_expect (hook != NULL, 0))
-    {
-      sz = bytes;
-      mem = (*hook)(sz, RETURN_ADDRESS (0));
-      if (mem == 0)
-        return 0;
-
-      return memset (mem, 0, sz);
-    }
+  if (__malloc_initialized < 0)
+    ptmalloc_init ();
 
   sz = bytes;
 
diff --git a/malloc/mcheck.c b/malloc/mcheck.c
index dc04a6391a..a0006c560a 100644
--- a/malloc/mcheck.c
+++ b/malloc/mcheck.c
@@ -27,374 +27,19 @@
 # include <errno.h>
 #endif
 
-/* Old hook values.  */
-static void (*old_free_hook)(void *ptr, const void *);
-static void *(*old_malloc_hook) (size_t size, const void *);
-static void *(*old_memalign_hook) (size_t alignment, size_t size,
-				   const void *);
-static void *(*old_realloc_hook) (void *ptr, size_t size,
-				  const void *);
-
-/* Function to call when something awful happens.  */
-static void (*abortfunc) (enum mcheck_status);
-
-/* Arbitrary magical numbers.  */
-#define MAGICWORD       0xfedabeeb
-#define MAGICFREE       0xd8675309
-#define MAGICBYTE       ((char) 0xd7)
-#define MALLOCFLOOD     ((char) 0x93)
-#define FREEFLOOD       ((char) 0x95)
-
-struct hdr
-{
-  size_t size;                  /* Exact size requested by user.  */
-  unsigned long int magic;      /* Magic number to check header integrity.  */
-  struct hdr *prev;
-  struct hdr *next;
-  void *block;                  /* Real block allocated, for memalign.  */
-  unsigned long int magic2;     /* Extra, keeps us doubleword aligned.  */
-};
-
-/* This is the beginning of the list of all memory blocks allocated.
-   It is only constructed if the pedantic testing is requested.  */
-static struct hdr *root;
-
-static int mcheck_used;
-
-/* Nonzero if pedentic checking of all blocks is requested.  */
-static int pedantic;
-
-#if defined _LIBC || defined STDC_HEADERS || defined USG
-# include <string.h>
-# define flood memset
-#else
-static void flood (void *, int, size_t);
-static void
-flood (void *ptr, int val, size_t size)
-{
-  char *cp = ptr;
-  while (size--)
-    *cp++ = val;
-}
-#endif
-
-static enum mcheck_status
-checkhdr (const struct hdr *hdr)
-{
-  enum mcheck_status status;
-
-  if (!mcheck_used)
-    /* Maybe the mcheck used is disabled?  This happens when we find
-       an error and report it.  */
-    return MCHECK_OK;
-
-  switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
-    {
-    default:
-      status = MCHECK_HEAD;
-      break;
-    case MAGICFREE:
-      status = MCHECK_FREE;
-      break;
-    case MAGICWORD:
-      if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
-        status = MCHECK_TAIL;
-      else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
-        status = MCHECK_HEAD;
-      else
-        status = MCHECK_OK;
-      break;
-    }
-  if (status != MCHECK_OK)
-    {
-      mcheck_used = 0;
-      (*abortfunc) (status);
-      mcheck_used = 1;
-    }
-  return status;
-}
-
 void
 mcheck_check_all (void)
 {
-  /* Walk through all the active blocks and test whether they were tampered
-     with.  */
-  struct hdr *runp = root;
-
-  /* Temporarily turn off the checks.  */
-  pedantic = 0;
-
-  while (runp != NULL)
-    {
-      (void) checkhdr (runp);
-
-      runp = runp->next;
-    }
-
-  /* Turn checks on again.  */
-  pedantic = 1;
 }
 #ifdef _LIBC
 libc_hidden_def (mcheck_check_all)
 #endif
 
-static void
-unlink_blk (struct hdr *ptr)
-{
-  if (ptr->next != NULL)
-    {
-      ptr->next->prev = ptr->prev;
-      ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
-                                      + (uintptr_t) ptr->next->next);
-    }
-  if (ptr->prev != NULL)
-    {
-      ptr->prev->next = ptr->next;
-      ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
-                                      + (uintptr_t) ptr->prev->next);
-    }
-  else
-    root = ptr->next;
-}
-
-static void
-link_blk (struct hdr *hdr)
-{
-  hdr->prev = NULL;
-  hdr->next = root;
-  root = hdr;
-  hdr->magic = MAGICWORD ^ (uintptr_t) hdr->next;
-
-  /* And the next block.  */
-  if (hdr->next != NULL)
-    {
-      hdr->next->prev = hdr;
-      hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
-                                      + (uintptr_t) hdr->next->next);
-    }
-}
-static void
-freehook (void *ptr, const void *caller)
-{
-  if (pedantic)
-    mcheck_check_all ();
-  if (ptr)
-    {
-      struct hdr *hdr = ((struct hdr *) ptr) - 1;
-      checkhdr (hdr);
-      hdr->magic = MAGICFREE;
-      hdr->magic2 = MAGICFREE;
-      unlink_blk (hdr);
-      hdr->prev = hdr->next = NULL;
-      flood (ptr, FREEFLOOD, hdr->size);
-      ptr = hdr->block;
-    }
-  __free_hook = old_free_hook;
-  if (old_free_hook != NULL)
-    (*old_free_hook)(ptr, caller);
-  else
-    free (ptr);
-  __free_hook = freehook;
-}
-
-static void *
-mallochook (size_t size, const void *caller)
-{
-  struct hdr *hdr;
-
-  if (pedantic)
-    mcheck_check_all ();
-
-  if (size > ~((size_t) 0) - (sizeof (struct hdr) + 1))
-    {
-      __set_errno (ENOMEM);
-      return NULL;
-    }
-
-  __malloc_hook = old_malloc_hook;
-  if (old_malloc_hook != NULL)
-    hdr = (struct hdr *) (*old_malloc_hook)(sizeof (struct hdr) + size + 1,
-                                            caller);
-  else
-    hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
-  __malloc_hook = mallochook;
-  if (hdr == NULL)
-    return NULL;
-
-  hdr->size = size;
-  link_blk (hdr);
-  hdr->block = hdr;
-  hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
-  ((char *) &hdr[1])[size] = MAGICBYTE;
-  flood ((void *) (hdr + 1), MALLOCFLOOD, size);
-  return (void *) (hdr + 1);
-}
-
-static void *
-memalignhook (size_t alignment, size_t size,
-              const void *caller)
-{
-  struct hdr *hdr;
-  size_t slop;
-  char *block;
-
-  if (pedantic)
-    mcheck_check_all ();
-
-  slop = (sizeof *hdr + alignment - 1) & - alignment;
-
-  if (size > ~((size_t) 0) - (slop + 1))
-    {
-      __set_errno (ENOMEM);
-      return NULL;
-    }
-
-  __memalign_hook = old_memalign_hook;
-  if (old_memalign_hook != NULL)
-    block = (*old_memalign_hook)(alignment, slop + size + 1, caller);
-  else
-    block = memalign (alignment, slop + size + 1);
-  __memalign_hook = memalignhook;
-  if (block == NULL)
-    return NULL;
-
-  hdr = ((struct hdr *) (block + slop)) - 1;
-
-  hdr->size = size;
-  link_blk (hdr);
-  hdr->block = (void *) block;
-  hdr->magic2 = (uintptr_t) block ^ MAGICWORD;
-  ((char *) &hdr[1])[size] = MAGICBYTE;
-  flood ((void *) (hdr + 1), MALLOCFLOOD, size);
-  return (void *) (hdr + 1);
-}
-
-static void *
-reallochook (void *ptr, size_t size, const void *caller)
-{
-  if (size == 0)
-    {
-      freehook (ptr, caller);
-      return NULL;
-    }
-
-  struct hdr *hdr;
-  size_t osize;
-
-  if (pedantic)
-    mcheck_check_all ();
-
-  if (size > ~((size_t) 0) - (sizeof (struct hdr) + 1))
-    {
-      __set_errno (ENOMEM);
-      return NULL;
-    }
-
-  if (ptr)
-    {
-      hdr = ((struct hdr *) ptr) - 1;
-      osize = hdr->size;
-
-      checkhdr (hdr);
-      unlink_blk (hdr);
-      if (size < osize)
-        flood ((char *) ptr + size, FREEFLOOD, osize - size);
-    }
-  else
-    {
-      osize = 0;
-      hdr = NULL;
-    }
-  __free_hook = old_free_hook;
-  __malloc_hook = old_malloc_hook;
-  __memalign_hook = old_memalign_hook;
-  __realloc_hook = old_realloc_hook;
-  if (old_realloc_hook != NULL)
-    hdr = (struct hdr *) (*old_realloc_hook)((void *) hdr,
-                                             sizeof (struct hdr) + size + 1,
-                                             caller);
-  else
-    hdr = (struct hdr *) realloc ((void *) hdr,
-                                  sizeof (struct hdr) + size + 1);
-  __free_hook = freehook;
-  __malloc_hook = mallochook;
-  __memalign_hook = memalignhook;
-  __realloc_hook = reallochook;
-  if (hdr == NULL)
-    return NULL;
-
-  hdr->size = size;
-  link_blk (hdr);
-  hdr->block = hdr;
-  hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
-  ((char *) &hdr[1])[size] = MAGICBYTE;
-  if (size > osize)
-    flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
-  return (void *) (hdr + 1);
-}
-
-__attribute__ ((noreturn))
-static void
-mabort (enum mcheck_status status)
-{
-  const char *msg;
-  switch (status)
-    {
-    case MCHECK_OK:
-      msg = _ ("memory is consistent, library is buggy\n");
-      break;
-    case MCHECK_HEAD:
-      msg = _ ("memory clobbered before allocated block\n");
-      break;
-    case MCHECK_TAIL:
-      msg = _ ("memory clobbered past end of allocated block\n");
-      break;
-    case MCHECK_FREE:
-      msg = _ ("block freed twice\n");
-      break;
-    default:
-      msg = _ ("bogus mcheck_status, library is buggy\n");
-      break;
-    }
-#ifdef _LIBC
-  __libc_fatal (msg);
-#else
-  fprintf (stderr, "mcheck: %s", msg);
-  fflush (stderr);
-  abort ();
-#endif
-}
-
-/* Memory barrier so that GCC does not optimize out the argument.  */
-#define malloc_opt_barrier(x) \
-  ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
 
 int
 mcheck (void (*func) (enum mcheck_status))
 {
-  abortfunc = (func != NULL) ? func : &mabort;
-
-  /* These hooks may not be safely inserted if malloc is already in use.  */
-  if (__malloc_initialized <= 0 && !mcheck_used)
-    {
-      /* We call malloc() once here to ensure it is initialized.  */
-      void *p = malloc (0);
-      /* GCC might optimize out the malloc/free pair without a barrier.  */
-      p = malloc_opt_barrier (p);
-      free (p);
-
-      old_free_hook = __free_hook;
-      __free_hook = freehook;
-      old_malloc_hook = __malloc_hook;
-      __malloc_hook = mallochook;
-      old_memalign_hook = __memalign_hook;
-      __memalign_hook = memalignhook;
-      old_realloc_hook = __realloc_hook;
-      __realloc_hook = reallochook;
-      mcheck_used = 1;
-    }
-
-  return mcheck_used ? 0 : -1;
+  return 0;
 }
 #ifdef _LIBC
 libc_hidden_def (mcheck)
@@ -403,14 +48,11 @@ libc_hidden_def (mcheck)
 int
 mcheck_pedantic (void (*func) (enum mcheck_status))
 {
-  int res = mcheck (func);
-  if (res == 0)
-    pedantic = 1;
-  return res;
+  return 0;
 }
 
 enum mcheck_status
 mprobe (void *ptr)
 {
-  return mcheck_used ? checkhdr (((struct hdr *) ptr) - 1) : MCHECK_DISABLED;
+  return MCHECK_DISABLED;
 }
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
index 9064f209ec..2e3ac66d9c 100644
--- a/malloc/mtrace.c
+++ b/malloc/mtrace.c
@@ -37,30 +37,12 @@
 #include <dso_handle.h>
 
 #include <libio/iolibio.h>
-#define setvbuf(s, b, f, l) _IO_setvbuf (s, b, f, l)
-#define fwrite(buf, size, count, fp) _IO_fwrite (buf, size, count, fp)
 
 #include <kernel-features.h>
 
-#define TRACE_BUFFER_SIZE 512
-
-static FILE *mallstream;
-static const char mallenv[] = "MALLOC_TRACE";
-static char *malloc_trace_buffer;
-
-__libc_lock_define_initialized (static, lock);
-
 /* Address to breakpoint on accesses to... */
 void *mallwatch;
 
-/* Old hook values.  */
-static void (*tr_old_free_hook) (void *ptr, const void *);
-static void *(*tr_old_malloc_hook) (size_t size, const void *);
-static void *(*tr_old_realloc_hook) (void *ptr, size_t size,
-				     const void *);
-static void *(*tr_old_memalign_hook) (size_t __alignment, size_t __size,
-				      const void *);
-
 /* This function is called when the block being alloc'd, realloc'd, or
    freed has an address matching the variable "mallwatch".  In a debugger,
    set "mallwatch" to the address of interest, then put a breakpoint on
@@ -74,275 +56,26 @@ tr_break (void)
 }
 libc_hidden_def (tr_break)
 
-static void
-tr_where (const void *caller, Dl_info *info)
-{
-  if (caller != NULL)
-    {
-      if (info != NULL)
-        {
-          char *buf = (char *) "";
-          if (info->dli_sname != NULL)
-            {
-              size_t len = strlen (info->dli_sname);
-              buf = alloca (len + 6 + 2 * sizeof (void *));
-
-              buf[0] = '(';
-              __stpcpy (_fitoa (caller >= (const void *) info->dli_saddr
-                                ? caller - (const void *) info->dli_saddr
-                                : (const void *) info->dli_saddr - caller,
-                                __stpcpy (__mempcpy (buf + 1, info->dli_sname,
-                                                     len),
-                                          caller >= (void *) info->dli_saddr
-                                          ? "+0x" : "-0x"),
-                                16, 0),
-                        ")");
-            }
-
-          fprintf (mallstream, "@ %s%s%s[%p] ",
-                   info->dli_fname ? : "", info->dli_fname ? ":" : "",
-                   buf, caller);
-        }
-      else
-        fprintf (mallstream, "@ [%p] ", caller);
-    }
-}
-
-static Dl_info *
-lock_and_info (const void *caller, Dl_info *mem)
-{
-  if (caller == NULL)
-    return NULL;
-
-  Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL;
-
-  __libc_lock_lock (lock);
-
-  return res;
-}
-
-static void
-tr_freehook (void *ptr, const void *caller)
-{
-  if (ptr == NULL)
-    return;
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-  tr_where (caller, info);
-  /* Be sure to print it first.  */
-  fprintf (mallstream, "- %p\n", ptr);
-  if (ptr == mallwatch)
-    {
-      __libc_lock_unlock (lock);
-      tr_break ();
-      __libc_lock_lock (lock);
-    }
-  __free_hook = tr_old_free_hook;
-  if (tr_old_free_hook != NULL)
-    (*tr_old_free_hook)(ptr, caller);
-  else
-    free (ptr);
-  __free_hook = tr_freehook;
-  __libc_lock_unlock (lock);
-}
-
-static void *
-tr_mallochook (size_t size, const void *caller)
-{
-  void *hdr;
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-
-  __malloc_hook = tr_old_malloc_hook;
-  if (tr_old_malloc_hook != NULL)
-    hdr = (void *) (*tr_old_malloc_hook)(size, caller);
-  else
-    hdr = (void *) malloc (size);
-  __malloc_hook = tr_mallochook;
-
-  tr_where (caller, info);
-  /* We could be printing a NULL here; that's OK.  */
-  fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-
-  __libc_lock_unlock (lock);
-
-  if (hdr == mallwatch)
-    tr_break ();
-
-  return hdr;
-}
-
-static void *
-tr_reallochook (void *ptr, size_t size, const void *caller)
-{
-  void *hdr;
-
-  if (ptr == mallwatch)
-    tr_break ();
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-
-  __free_hook = tr_old_free_hook;
-  __malloc_hook = tr_old_malloc_hook;
-  __realloc_hook = tr_old_realloc_hook;
-  if (tr_old_realloc_hook != NULL)
-    hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
-  else
-    hdr = (void *) realloc (ptr, size);
-  __free_hook = tr_freehook;
-  __malloc_hook = tr_mallochook;
-  __realloc_hook = tr_reallochook;
-
-  tr_where (caller, info);
-  if (hdr == NULL)
-    {
-      if (size != 0)
-        /* Failed realloc.  */
-        fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
-      else
-        fprintf (mallstream, "- %p\n", ptr);
-    }
-  else if (ptr == NULL)
-    fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-  else
-    {
-      fprintf (mallstream, "< %p\n", ptr);
-      tr_where (caller, info);
-      fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size);
-    }
-
-  __libc_lock_unlock (lock);
-
-  if (hdr == mallwatch)
-    tr_break ();
-
-  return hdr;
-}
-
-static void *
-tr_memalignhook (size_t alignment, size_t size, const void *caller)
-{
-  void *hdr;
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-
-  __memalign_hook = tr_old_memalign_hook;
-  __malloc_hook = tr_old_malloc_hook;
-  if (tr_old_memalign_hook != NULL)
-    hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
-  else
-    hdr = (void *) memalign (alignment, size);
-  __memalign_hook = tr_memalignhook;
-  __malloc_hook = tr_mallochook;
-
-  tr_where (caller, info);
-  /* We could be printing a NULL here; that's OK.  */
-  fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-
-  __libc_lock_unlock (lock);
-
-  if (hdr == mallwatch)
-    tr_break ();
-
-  return hdr;
-}
-
-
-#ifdef _LIBC
-
-/* This function gets called to make sure all memory the library
-   allocates get freed and so does not irritate the user when studying
-   the mtrace output.  */
-static void __libc_freeres_fn_section
-release_libc_mem (void)
-{
-  /* Only call the free function if we still are running in mtrace mode.  */
-  if (mallstream != NULL)
-    __libc_freeres ();
-}
-#endif
-
-
 /* We enable tracing if either the environment variable MALLOC_TRACE
    is set, or if the variable mallwatch has been patched to an address
    that the debugging user wants us to stop on.  When patching mallwatch,
    don't forget to set a breakpoint on tr_break!  */
 
+void (*__glibc_mtrace_hook)(int) = NULL;
+int __glibc_mtrace_hook_enabled = 0;
+
 void
 mtrace (void)
 {
-#ifdef _LIBC
-  static int added_atexit_handler;
-#endif
-  char *mallfile;
-
-  /* Don't panic if we're called more than once.  */
-  if (mallstream != NULL)
-    return;
-
-#ifdef _LIBC
-  /* When compiling the GNU libc we use the secure getenv function
-     which prevents the misuse in case of SUID or SGID enabled
-     programs.  */
-  mallfile = __libc_secure_getenv (mallenv);
-#else
-  mallfile = getenv (mallenv);
-#endif
-  if (mallfile != NULL || mallwatch != NULL)
-    {
-      char *mtb = malloc (TRACE_BUFFER_SIZE);
-      if (mtb == NULL)
-        return;
-
-      mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
-      if (mallstream != NULL)
-        {
-          /* Be sure it doesn't malloc its buffer!  */
-          malloc_trace_buffer = mtb;
-          setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
-          fprintf (mallstream, "= Start\n");
-          tr_old_free_hook = __free_hook;
-          __free_hook = tr_freehook;
-          tr_old_malloc_hook = __malloc_hook;
-          __malloc_hook = tr_mallochook;
-          tr_old_realloc_hook = __realloc_hook;
-          __realloc_hook = tr_reallochook;
-          tr_old_memalign_hook = __memalign_hook;
-          __memalign_hook = tr_memalignhook;
-#ifdef _LIBC
-          if (!added_atexit_handler)
-            {
-              added_atexit_handler = 1;
-              __cxa_atexit ((void (*)(void *))release_libc_mem, NULL,
-			    __dso_handle);
-            }
-#endif
-        }
-      else
-        free (mtb);
-    }
+  if (__glibc_mtrace_hook)
+    __glibc_mtrace_hook(1);
+  __glibc_mtrace_hook_enabled = 1;
 }
 
 void
 muntrace (void)
 {
-  if (mallstream == NULL)
-    return;
-
-  /* Do the reverse of what done in mtrace: first reset the hooks and
-     MALLSTREAM, and only after that write the trailer and close the
-     file.  */
-  FILE *f = mallstream;
-  mallstream = NULL;
-  __free_hook = tr_old_free_hook;
-  __malloc_hook = tr_old_malloc_hook;
-  __realloc_hook = tr_old_realloc_hook;
-  __memalign_hook = tr_old_memalign_hook;
-
-  fprintf (f, "= End\n");
-  fclose (f);
+  if (__glibc_mtrace_hook)
+    __glibc_mtrace_hook(0);
+  __glibc_mtrace_hook_enabled = 0;
 }
diff --git a/malloc/tst-mtrace.sh b/malloc/tst-mtrace.sh
index 9c50c0675d..926c96e3bb 100755
--- a/malloc/tst-mtrace.sh
+++ b/malloc/tst-mtrace.sh
@@ -30,6 +30,7 @@ trap "rm -f ${common_objpfx}malloc/tst-mtrace.leak; exit 1" 1 2 15
 ${test_program_prefix_before_env} \
 ${run_program_env} \
 MALLOC_TRACE=${common_objpfx}malloc/tst-mtrace.leak \
+LD_PRELOAD=${common_objpfx}/malloc/libmalloc-extras.so \
 ${test_program_prefix_after_env} \
   ${common_objpfx}malloc/tst-mtrace || status=1
 
diff --git a/misc/Makefile b/misc/Makefile
index a5076b3672..81fe068b64 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -132,7 +132,8 @@ $(objpfx)libg.a: $(dep-dummy-lib); $(make-dummy-lib)
 
 $(objpfx)tst-tsearch: $(libm)
 
-tst-error1-ENV = MALLOC_TRACE=$(objpfx)tst-error1.mtrace
+tst-error1-ENV = MALLOC_TRACE=$(objpfx)tst-error1.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 tst-error1-ARGS = $(objpfx)tst-error1.out
 $(objpfx)tst-error1-mem.out: $(objpfx)tst-error1.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-error1.mtrace > $@; \
diff --git a/nptl/Makefile b/nptl/Makefile
index 94be92c789..7d014be36a 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -528,10 +528,12 @@ tst-umask1-ARGS = $(objpfx)tst-umask1.temp
 
 $(objpfx)tst-atfork2: $(libdl) $(shared-thread-library)
 LDFLAGS-tst-atfork2 = -rdynamic
-tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace
+tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 $(objpfx)tst-atfork2mod.so: $(shared-thread-library)
 
-tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace
+tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace \
+	LD_PRELOAD=$(objpfx)/../malloc/libmalloc-extras.so
 $(objpfx)tst-stack3-mem.out: $(objpfx)tst-stack3.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@; \
 	$(evaluate-test)
diff --git a/posix/Makefile b/posix/Makefile
index 51dcf129ec..3a902a284c 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -277,43 +277,50 @@ annexc-CFLAGS = -O
 $(objpfx)annexc: annexc.c
 	$(native-compile)
 
-tst-fnmatch-ENV += MALLOC_TRACE=$(objpfx)tst-fnmatch.mtrace
+tst-fnmatch-ENV += MALLOC_TRACE=$(objpfx)tst-fnmatch.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)tst-fnmatch-mem.out: $(objpfx)tst-fnmatch.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-fnmatch.mtrace > $@; \
 	$(evaluate-test)
 
-bug-regex2-ENV = MALLOC_TRACE=$(objpfx)bug-regex2.mtrace
+bug-regex2-ENV = MALLOC_TRACE=$(objpfx)bug-regex2.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)bug-regex2-mem.out: $(objpfx)bug-regex2.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-regex2.mtrace > $@; \
 	$(evaluate-test)
 
-bug-regex14-ENV = MALLOC_TRACE=$(objpfx)bug-regex14.mtrace
+bug-regex14-ENV = MALLOC_TRACE=$(objpfx)bug-regex14.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)bug-regex14-mem.out: $(objpfx)bug-regex14.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-regex14.mtrace > $@; \
 	$(evaluate-test)
 
-bug-regex21-ENV = MALLOC_TRACE=$(objpfx)bug-regex21.mtrace
+bug-regex21-ENV = MALLOC_TRACE=$(objpfx)bug-regex21.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)bug-regex21-mem.out: $(objpfx)bug-regex21.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-regex21.mtrace > $@; \
 	$(evaluate-test)
 
-bug-regex31-ENV = MALLOC_TRACE=$(objpfx)bug-regex31.mtrace
+bug-regex31-ENV = MALLOC_TRACE=$(objpfx)bug-regex31.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)bug-regex31-mem.out: $(objpfx)bug-regex31.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-regex31.mtrace > $@; \
 	$(evaluate-test)
 
-bug-regex36-ENV = MALLOC_TRACE=$(objpfx)bug-regex36.mtrace
+bug-regex36-ENV = MALLOC_TRACE=$(objpfx)bug-regex36.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)bug-regex36-mem.out: $(objpfx)bug-regex36.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-regex36.mtrace > $@; \
 	$(evaluate-test)
 
-tst-vfork3-ENV = MALLOC_TRACE=$(objpfx)tst-vfork3.mtrace
+tst-vfork3-ENV = MALLOC_TRACE=$(objpfx)tst-vfork3.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)tst-vfork3-mem.out: $(objpfx)tst-vfork3.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-vfork3.mtrace > $@; \
@@ -322,18 +329,21 @@ $(objpfx)tst-vfork3-mem.out: $(objpfx)tst-vfork3.out
 # tst-rxspencer.mtrace is not generated, only
 # tst-rxspencer-no-utf8.mtrace, since otherwise the file has almost
 # 100M and takes very long time to process.
-tst-rxspencer-no-utf8-ENV += MALLOC_TRACE=$(objpfx)tst-rxspencer-no-utf8.mtrace
+tst-rxspencer-no-utf8-ENV += MALLOC_TRACE=$(objpfx)tst-rxspencer-no-utf8.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 $(objpfx)tst-rxspencer-no-utf8-mem.out: $(objpfx)tst-rxspencer-no-utf8.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-rxspencer-no-utf8.mtrace \
 				      > $@; \
 	$(evaluate-test)
 
-tst-pcre-ENV = MALLOC_TRACE=$(objpfx)tst-pcre.mtrace
+tst-pcre-ENV = MALLOC_TRACE=$(objpfx)tst-pcre.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 $(objpfx)tst-pcre-mem.out: $(objpfx)tst-pcre.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-pcre.mtrace > $@; \
 	$(evaluate-test)
 
-tst-boost-ENV = MALLOC_TRACE=$(objpfx)tst-boost.mtrace
+tst-boost-ENV = MALLOC_TRACE=$(objpfx)tst-boost.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 $(objpfx)tst-boost-mem.out: $(objpfx)tst-boost.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-boost.mtrace > $@; \
 	$(evaluate-test)
@@ -346,15 +356,18 @@ $(objpfx)bug-ga2-mem.out: $(objpfx)bug-ga2.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-ga2.mtrace > $@; \
 	$(evaluate-test)
 
-bug-ga2-ENV = MALLOC_TRACE=$(objpfx)bug-ga2.mtrace
+bug-ga2-ENV = MALLOC_TRACE=$(objpfx)bug-ga2.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
-bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bug-glob2.mtrace
+bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bug-glob2.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)bug-glob2-mem.out: $(objpfx)bug-glob2.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@; \
 	$(evaluate-test)
 
-tst-glob-tilde-ENV = MALLOC_TRACE=$(objpfx)tst-glob-tilde.mtrace
+tst-glob-tilde-ENV = MALLOC_TRACE=$(objpfx)tst-glob-tilde.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)tst-glob-tilde-mem.out: $(objpfx)tst-glob-tilde.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-glob-tilde.mtrace > $@; \
diff --git a/posix/tst-vfork3.c b/posix/tst-vfork3.c
index 0449b2486a..199eaf1c0f 100644
--- a/posix/tst-vfork3.c
+++ b/posix/tst-vfork3.c
@@ -147,6 +147,8 @@ do_prepare (void)
     FAIL_EXIT1 ("out of memory");
   strcpy (stpcpy (tmpdirname, test_dir), "/tst-vfork3.XXXXXX");
 
+  unsetenv("LD_PRELOAD");
+
   tmpdirname = mkdtemp (tmpdirname);
   if (tmpdirname == NULL)
     FAIL_EXIT1 ("could not create temporary directory");
diff --git a/resolv/Makefile b/resolv/Makefile
index 6e70ae9f6b..6791a22de2 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -140,17 +140,20 @@ $(objpfx)tst-res_hconf_reorder: $(libdl) $(shared-thread-library)
 tst-res_hconf_reorder-ENV = RESOLV_REORDER=on
 
 $(objpfx)tst-leaks: $(objpfx)libresolv.so
-tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace
+tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace \
+	LD_PRELOAD=$(objpfx)/../malloc/libmalloc-extras.so
 $(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@; \
 	$(evaluate-test)
 
-tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
+tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace \
+	LD_PRELOAD=$(objpfx)/../malloc/libmalloc-extras.so
 $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
 	$(evaluate-test)
 
-tst-resolv-res_ninit-ENV = MALLOC_TRACE=$(objpfx)tst-resolv-res_ninit.mtrace
+tst-resolv-res_ninit-ENV = MALLOC_TRACE=$(objpfx)tst-resolv-res_ninit.mtrace \
+	LD_PRELOAD=$(objpfx)/../malloc/libmalloc-extras.so
 $(objpfx)mtrace-tst-resolv-res_ninit.out: $(objpfx)tst-resolv-res_ninit.out
 	$(common-objpfx)malloc/mtrace \
 	  $(objpfx)tst-resolv-res_ninit.mtrace > $@; \
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 9dfc115313..10da17ff6e 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -90,9 +90,11 @@ $(objpfx)tst-swprintf.out: $(gen-locales)
 $(objpfx)tst-vfprintf-mbs-prec.out: $(gen-locales)
 endif
 
-tst-printf-bz18872-ENV = MALLOC_TRACE=$(objpfx)tst-printf-bz18872.mtrace
+tst-printf-bz18872-ENV = MALLOC_TRACE=$(objpfx)tst-printf-bz18872.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 tst-vfprintf-width-prec-ENV = \
-  MALLOC_TRACE=$(objpfx)tst-vfprintf-width-prec.mtrace
+  MALLOC_TRACE=$(objpfx)tst-vfprintf-width-prec.mtrace \
+	LD_PRELOAD=$(objpfx)../malloc/libmalloc-extras.so
 
 $(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
 	$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' > $@; \
