@@ -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 libc_malloc_debug
in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
$(libof-$(<F)) \
@@ -97,6 +97,12 @@ 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.
+* Debugging features in malloc such as the MALLOC_CHECK_ environment variable
+ (or the glibc.malloc.check tunable), mtrace() and mcheck() have now been
+ disabled by default in the main C library. Users looking to use these
+ features now need to preload a new debugging DSO libc_malloc_debug.so to get
+ this functionality back.
+
Changes to build and runtime requirements:
* On Linux, the shm_open, sem_open, and related functions now expect the
@@ -279,10 +279,17 @@ endif
# All malloc-check tests will be run with MALLOC_CHECK_=3
define malloc-check-ENVS
-$(1)-malloc-check-ENV = MALLOC_CHECK_=3
+$(1)-malloc-check-ENV = MALLOC_CHECK_=3 \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
endef
$(foreach t,$(tests-malloc-check),$(eval $(call malloc-check-ENVS,$(t))))
+# mcheck tests need the debug DSO to support -lmcheck.
+define mcheck-ENVS
+$(1)-mcheck-ENV = LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+endef
+$(foreach t,$(tests-mcheck),$(eval $(call mcheck-ENVS,$(t))))
+
ifneq "$(strip $(tests) $(tests-internal) $(xtests) $(test-srcs))" ""
# These are the implicit rules for making test outputs
# from the test programs and whatever input files are present.
@@ -56,7 +56,9 @@ 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=$(common-objpfx)/malloc/libc_malloc_debug.so
ifeq ($(run-built-tests),yes)
# This test just checks whether the program produces any error or not.
@@ -156,7 +156,7 @@ $(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force)
$(do-install-program)
endif
-tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
+tests-static-normal := tst-array1-static tst-array5-static \
tst-dl-iter-static \
tst-tlsalign-static tst-tlsalign-extern-static \
tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
@@ -242,7 +242,7 @@ endif
tests += $(tests-execstack-$(have-z-execstack))
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 $(objpfx)tst-rtld-help.out
endif
tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@@ -895,7 +895,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=$(common-objpfx)/malloc/libc_malloc_debug.so
LDFLAGS-nodelete = -rdynamic
LDFLAGS-nodelmod1.so = -Wl,--enable-new-dtags,-z,nodelete
@@ -1273,12 +1274,8 @@ $(objpfx)tst-leaks1-mem.out: $(objpfx)tst-leaks1.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@; \
$(evaluate-test)
-$(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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-thrlock: $(shared-thread-library)
deleted file mode 100644
@@ -1 +0,0 @@
-#include "tst-leaks1.c"
@@ -301,7 +301,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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)mtrace-tst-loading.out: $(objpfx)tst-loading.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-loading.mtrace > $@; \
$(evaluate-test)
@@ -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/libc_malloc_debug.so \
LOCPATH=${objpfx}localedir:${common_objpfx}localedata \
${test_program_prefix_after_env} \
${objpfx}tst-gettext > ${objpfx}tst-gettext.out ${objpfx}domaindir
@@ -165,10 +165,14 @@ LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
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
-tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
+test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
generated += test-fmemopen.mtrace test-fmemopen.check
generated += tst-fopenloc.mtrace tst-fopenloc.check
@@ -456,7 +456,8 @@ $(INSTALL-SUPPORTED-LOCALE-FILES): 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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@; \
$(evaluate-test)
@@ -42,11 +42,11 @@ 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 \
- tst-interpose-static-thread \
- tst-malloc-usable-static \
+ tst-interpose-static-thread
# Test for the malloc_set_state symbol removed in glibc 2.25.
ifeq ($(have-GLIBC_2.24)$(build-shared),yesyes)
@@ -63,7 +63,6 @@ tests-internal += \
ifneq (no,$(have-tunables))
tests += tst-malloc-usable-tunables tst-mxfast
-tests-static += tst-malloc-usable-static-tunables
endif
tests += $(tests-static)
@@ -72,7 +71,8 @@ test-srcs = tst-mtrace
# These tests either are run with MALLOC_CHECK_=3 by default or do not work
# with MALLOC_CHECK_=3 because they expect a specific failure.
tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \
- tst-mxfast tst-safe-linking
+ tst-mxfast tst-safe-linking \
+ tst-compathooks-off tst-compathooks-on
# Run all tests with MALLOC_CHECK_=3
tests-malloc-check = $(filter-out $(tests-exclude-malloc-check),$(tests))
@@ -88,13 +88,12 @@ tests-exclude-mcheck = tst-mallocstate \
tst-malloc-tcache-leak \
tst-malloc-thread-exit \
tst-malloc-thread-fail \
- tst-malloc-usable-static \
- tst-malloc-usable-static-tunables \
tst-malloc-usable-tunables \
tst-malloc_info \
tst-memalign \
tst-posix_memalign \
- tst-posix-realloc
+ tst-posix-realloc \
+ tst-compathooks-off tst-compathooks-on
tests-mcheck = $(filter-out $(tests-exclude-mcheck), $(tests))
@@ -116,8 +115,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 libc_malloc_debug
extra-libs-others = $(extra-libs)
# Helper objects for some tests.
@@ -132,6 +131,9 @@ test-extras = \
libmemusage-routines = memusage
libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
+libc_malloc_debug-routines = malloc-debug
+libc_malloc_debug-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)
@@ -237,11 +239,12 @@ endif
endif
endif
-tst-malloc-check-ENV = MALLOC_CHECK_=3
-tst-malloc-usable-ENV = MALLOC_CHECK_=3
-tst-malloc-usable-static-ENV = $(tst-malloc-usable-ENV)
-tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3
-tst-malloc-usable-static-tunables-ENV = $(tst-malloc-usable-tunables-ENV)
+tst-malloc-check-ENV = MALLOC_CHECK_=3 \
+ LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
+tst-malloc-usable-ENV = MALLOC_CHECK_=3 \
+ LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
+tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 \
+ LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
tst-mxfast-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=0:glibc.malloc.mxfast=0
@@ -296,12 +299,14 @@ $(objpfx)tst-interpose-static-thread-mcheck: \
$(objpfx)tst-interpose-static-thread-malloc-check: \
$(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)libc_malloc_debug.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)libc_malloc_debug.so
$(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray-fail.mtrace > $@; \
$(evaluate-test)
@@ -315,3 +320,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)libc_malloc_debug.so
+tst-compathooks-on-mcheck-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-compathooks-on-malloc-check-ENV = \
+ LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-mallocstate-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
@@ -404,13 +404,6 @@ ptmalloc_init (void)
if (s && s[0] != '\0' && s[0] != '0')
__malloc_check_init ();
#endif
-
-#if HAVE_MALLOC_INIT_HOOK
- void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook);
- if (hook != NULL)
- (*hook)();
-#endif
- __malloc_initialized = 1;
}
/* Managing heaps and arenas (for concurrent threads) */
@@ -1,4 +1,4 @@
-/* Malloc implementation for multiple threads without lock contention.
+/* Compatibility code for malloc debugging and state management.
Copyright (C) 2001-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
@@ -17,32 +17,70 @@
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
+#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);
+#endif
+
+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 *, const void *) = NULL;
+void *weak_variable (*__malloc_hook)
+ (size_t, const void *) = malloc_hook_ini;
+void *weak_variable (*__realloc_hook)
+ (void *, size_t, const void *) = realloc_hook_ini;
+void *weak_variable (*__memalign_hook)
+ (size_t, size_t, const void *) = memalign_hook_ini;
+
/* Hooks for debugging versions. The initial hooks just call the
initialization routine, then do the normal work. */
-static void *
-malloc_hook_ini (size_t sz, const void *caller)
+/* These hooks will get executed only through the interposed allocator
+ functions in libc_malloc_debug.so. 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;
ptmalloc_init ();
- return __libc_malloc (sz);
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24)
+ void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook);
+ if (hook != NULL)
+ (*hook)();
+#endif
+ __malloc_initialized = 1;
+}
+
+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)
{
- __malloc_hook = NULL;
- __realloc_hook = NULL;
- ptmalloc_init ();
- return __libc_realloc (ptr, sz);
+ generic_hook_ini ();
+ return realloc (ptr, sz);
}
static void *
memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
{
- __memalign_hook = NULL;
- ptmalloc_init ();
- return __libc_memalign (alignment, sz);
+ generic_hook_ini ();
+ return memalign (alignment, sz);
}
#include "malloc-check.c"
new file mode 100644
@@ -0,0 +1,189 @@
+/* Malloc debug 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>
+#include <sys/param.h>
+
+/* 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);
+
+#define DEBUG_FN(fn) \
+ static __typeof (__libc_ ## fn) __debug_ ## fn
+
+DEBUG_FN(malloc);
+DEBUG_FN(free);
+DEBUG_FN(realloc);
+DEBUG_FN(memalign);
+DEBUG_FN(valloc);
+DEBUG_FN(pvalloc);
+DEBUG_FN(calloc);
+
+extern void (*__free_hook) (void *, const void *);
+compat_symbol_reference (libc, __free_hook, __free_hook, GLIBC_2_0);
+extern void * (*__malloc_hook) (size_t, const void *);
+compat_symbol_reference (libc, __malloc_hook, __malloc_hook, GLIBC_2_0);
+extern void * (*__realloc_hook) (void *, size_t, const void *);
+compat_symbol_reference (libc, __realloc_hook, __realloc_hook, GLIBC_2_0);
+extern void * (*__memalign_hook) (size_t, size_t, const void *);
+compat_symbol_reference (libc, __memalign_hook, __memalign_hook, GLIBC_2_0);
+
+static size_t pagesize;
+
+/* The allocator functions. */
+
+static void *
+__debug_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 (__debug_malloc, malloc)
+
+static void
+__debug_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 (__debug_free, free)
+
+static void *
+__debug_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 (__debug_realloc, realloc)
+
+static void *
+_mid_memalign (size_t alignment, size_t bytes, const void *address)
+{
+ void *(*hook) (size_t, size_t, const void *) =
+ atomic_forced_read (__memalign_hook);
+ if (__builtin_expect (hook != NULL, 0))
+ return (*hook)(alignment, bytes, address);
+
+ return __libc_memalign (alignment, bytes);
+}
+
+static void *
+__debug_memalign (size_t alignment, size_t bytes)
+{
+ return _mid_memalign (alignment, bytes, RETURN_ADDRESS (0));
+}
+strong_alias (__debug_memalign, memalign)
+strong_alias (__debug_memalign, aligned_alloc)
+
+static void *
+__debug_pvalloc (size_t bytes)
+{
+ 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 _mid_memalign (pagesize, rounded_bytes, RETURN_ADDRESS (0));
+}
+strong_alias (__debug_pvalloc, pvalloc)
+
+static void *
+__debug_valloc (size_t bytes)
+{
+ if (!pagesize)
+ pagesize = sysconf (_SC_PAGESIZE);
+
+ return _mid_memalign (pagesize, bytes, RETURN_ADDRESS (0));
+}
+strong_alias (__debug_valloc, valloc)
+
+static int
+__debug_posix_memalign (void **memptr, size_t alignment, size_t bytes)
+{
+ /* 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;
+
+ *memptr = _mid_memalign (alignment, bytes, RETURN_ADDRESS (0));
+
+ if (*memptr == NULL)
+ return ENOMEM;
+
+ return 0;
+}
+strong_alias (__debug_posix_memalign, posix_memalign)
+
+static void *
+__debug_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 (__debug_calloc, calloc)
@@ -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
@@ -2013,30 +2003,6 @@ static void malloc_consolidate (mstate);
# define weak_variable weak_function
#endif
-/* Forward declarations. */
-static void *malloc_hook_ini (size_t sz,
- const void *caller) __THROW;
-static void *realloc_hook_ini (void *ptr, size_t sz,
- const void *caller) __THROW;
-static void *memalign_hook_ini (size_t alignment, size_t sz,
- const void *caller) __THROW;
-
-#if HAVE_MALLOC_INIT_HOOK
-void (*__malloc_initialize_hook) (void) __attribute__ ((nocommon));
-compat_symbol (libc, __malloc_initialize_hook,
- __malloc_initialize_hook, GLIBC_2_0);
-#endif
-
-void weak_variable (*__free_hook) (void *__ptr,
- const void *) = NULL;
-void *weak_variable (*__malloc_hook)
- (size_t __size, const void *) = malloc_hook_ini;
-void *weak_variable (*__realloc_hook)
- (void *__ptr, size_t __size, const void *)
- = realloc_hook_ini;
-void *weak_variable (*__memalign_hook)
- (size_t __alignment, size_t __size, const void *)
- = memalign_hook_ini;
void weak_variable (*__after_morecore_hook) (void) = NULL;
/* This function is called from the arena shutdown hook, to free the
@@ -3229,10 +3195,8 @@ __libc_malloc (size_t bytes)
_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))
- 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;
@@ -3293,14 +3257,6 @@ __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 (mem == 0) /* free(0) has no effect */
return;
@@ -3352,10 +3308,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)
@@ -3490,6 +3444,9 @@ libc_hidden_def (__libc_realloc)
void *
__libc_memalign (size_t alignment, size_t bytes)
{
+ if (__malloc_initialized < 0)
+ ptmalloc_init ();
+
void *address = RETURN_ADDRESS (0);
return _mid_memalign (alignment, bytes, address);
}
@@ -3500,11 +3457,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);
@@ -3613,16 +3565,8 @@ __libc_calloc (size_t n, size_t elem_size)
sz = bytes;
- void *(*hook) (size_t, const void *) =
- atomic_forced_read (__malloc_hook);
- if (__builtin_expect (hook != NULL, 0))
- {
- mem = (*hook)(sz, RETURN_ADDRESS (0));
- if (mem == 0)
- return 0;
-
- return memset (mem, 0, sz);
- }
+ if (__malloc_initialized < 0)
+ ptmalloc_init ();
MAYBE_INIT_TCACHE ();
@@ -5651,6 +5595,9 @@ __posix_memalign (void **memptr, size_t alignment, size_t size)
{
void *mem;
+ if (__malloc_initialized < 0)
+ ptmalloc_init ();
+
/* Test whether the SIZE argument is valid. It must be a power of
two multiple of sizeof (void *). */
if (alignment % sizeof (void *) != 0
@@ -25,6 +25,7 @@
# include <stdio.h>
# include <libintl.h>
# include <errno.h>
+# include <malloc-internal.h>
#endif
/* Old hook values. */
@@ -22,6 +22,7 @@
# define _MALLOC_INTERNAL
# include <malloc.h>
# include <mcheck.h>
+# include <malloc-internal.h>
# include <libc-lock.h>
#endif
new file mode 100644
@@ -0,0 +1,145 @@
+/* Minimal tests to verify libc_malloc_debug.so functionality.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <shlib-compat.h>
+#include <libc-diag.h>
+
+#include <support/check.h>
+#include <support/support.h>
+
+extern void (*volatile __free_hook) (void *, const void *);
+extern void *(*volatile __malloc_hook)(size_t, const void *);
+extern void *(*volatile __realloc_hook)(void *, size_t, const void *);
+extern void *(*volatile __memalign_hook)(size_t, size_t, const void *);
+
+int hook_count, call_count;
+
+DIAG_PUSH_NEEDS_COMMENT;
+DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
+
+void
+free_called (void *mem, const void *address)
+{
+ hook_count++;
+ __free_hook = NULL;
+ free (mem);
+ __free_hook = free_called;
+}
+
+void *
+malloc_called (size_t bytes, const void *address)
+{
+ hook_count++;
+ __malloc_hook = NULL;
+ void *mem = malloc (bytes);
+ __malloc_hook = malloc_called;
+ return mem;
+}
+
+void *
+realloc_called (void *oldptr, size_t bytes, const void *address)
+{
+ hook_count++;
+ __realloc_hook = NULL;
+ void *mem = realloc (oldptr, bytes);
+ __realloc_hook = realloc_called;
+ return mem;
+}
+
+void *
+calloc_called (size_t n, size_t size, const void *address)
+{
+ hook_count++;
+ __malloc_hook = NULL;
+ void *mem = calloc (n, size);
+ __malloc_hook = malloc_called;
+ return mem;
+}
+
+void *
+memalign_called (size_t align, size_t size, const void *address)
+{
+ hook_count++;
+ __memalign_hook = NULL;
+ void *mem = memalign (align, size);
+ __memalign_hook = memalign_called;
+ return mem;
+}
+
+static void initialize_hooks (void)
+{
+ __free_hook = free_called;
+ __malloc_hook = malloc_called;
+ __realloc_hook = realloc_called;
+ __memalign_hook = memalign_called;
+}
+void (*__malloc_initialize_hook) (void) = initialize_hooks;
+compat_symbol_reference (libc, __malloc_initialize_hook,
+ __malloc_initialize_hook, GLIBC_2_0);
+compat_symbol_reference (libc, __free_hook,
+ __free_hook, GLIBC_2_0);
+compat_symbol_reference (libc, __malloc_hook,
+ __malloc_hook, GLIBC_2_0);
+compat_symbol_reference (libc, __realloc_hook,
+ __realloc_hook, GLIBC_2_0);
+compat_symbol_reference (libc, __memalign_hook,
+ __memalign_hook, GLIBC_2_0);
+
+DIAG_POP_NEEDS_COMMENT;
+
+static int
+do_test (void)
+{
+ void *p;
+ p = malloc (0);
+ TEST_VERIFY_EXIT (p != NULL);
+ call_count++;
+
+ p = realloc (p, 0);
+ TEST_VERIFY_EXIT (p == NULL);
+ call_count++;
+
+ p = calloc (512, 1);
+ TEST_VERIFY_EXIT (p != NULL);
+ call_count++;
+
+ free (p);
+ call_count++;
+
+ p = memalign (0x100, 0x100);
+ TEST_VERIFY_EXIT (p != NULL);
+ call_count++;
+
+ free (p);
+ call_count++;
+
+ printf ("call_count: %d, hook_count: %d\n", call_count, hook_count);
+
+#ifdef HOOKS_ENABLED
+ TEST_VERIFY_EXIT (call_count == hook_count);
+#else
+ TEST_VERIFY_EXIT (hook_count == 0);
+#endif
+
+ exit (0);
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,2 @@
+#define HOOKS_ENABLED 1
+#include "tst-compathooks-off.c"
deleted file mode 100644
@@ -1 +0,0 @@
-#include <malloc/tst-malloc-usable.c>
deleted file mode 100644
@@ -1 +0,0 @@
-#include <malloc/tst-malloc-usable.c>
@@ -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/libc_malloc_debug.so \
${test_program_prefix_after_env} \
${common_objpfx}malloc/tst-mtrace || status=1
@@ -1256,8 +1256,9 @@ environment variable @env{MALLOC_ARENA_MAX} to the desired value.
@cindex consistency checking, of heap
You can ask @code{malloc} to check the consistency of dynamic memory by
-using the @code{mcheck} function. This function is a GNU extension,
-declared in @file{mcheck.h}.
+using the @code{mcheck} function and preloading the malloc debug library
+@file{libc_malloc_debug.so} using the @var{LD_PRELOAD} environment variable.
+This function is a GNU extension, declared in @file{mcheck.h}.
@pindex mcheck.h
@deftypefun int mcheck (void (*@var{abortfn}) (enum mcheck_status @var{status}))
@@ -1368,7 +1369,10 @@ non-zero value, a special (less efficient) implementation is used which
is designed to be tolerant against simple errors, such as double calls
of @code{free} with the same argument, or overruns of a single byte
(off-by-one bugs). Not all such errors can be protected against,
-however, and memory leaks can result.
+however, and memory leaks can result. Like in the case of @code{mcheck},
+one would need to preload the @file{libc_malloc_debug.so} library to
+enable @code{MALLOC_CHECK_} functionality. Without this preloaded
+library, setting @code{MALLOC_CHECK_} will have no effect.
Any detected heap corruption results in immediate termination of the
process.
@@ -1747,6 +1751,12 @@ penalties for the program if the debugging mode is not enabled.
@c fprintf dup (on newly-created stream) @aculock
@c __cxa_atexit (once) dup @asulock @aculock @acsmem
@c free dup @ascuheap @acsmem
+The @code{mtrace} function provides a way to trace memory allocation
+events in the program that calls it. It is disabled by default in the
+library and can be enabled by preloading the debugging library
+@file{libc_malloc_debug.so} using the @code{LD_PRELOAD} environment
+variable.
+
When the @code{mtrace} function is called it looks for an environment
variable named @code{MALLOC_TRACE}. This variable is supposed to
contain a valid file name. The user must have write access. If the
@@ -113,7 +113,9 @@ following tunables in the @code{malloc} namespace:
@deftp Tunable glibc.malloc.check
This tunable supersedes the @env{MALLOC_CHECK_} environment variable and is
-identical in features.
+identical in features. This tunable has no effect by default and needs the
+debug library @file{libc_malloc_debug.so} to be preloaded using the
+@code{LD_PRELOAD} environment variable.
Setting this tunable to a non-zero value enables a special (less
efficient) memory allocator for the @code{malloc} family of functions that is
@@ -152,13 +152,15 @@ $(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=$(common-objpfx)/malloc/libc_malloc_debug.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 > $@; \
$(evaluate-test)
-tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace
+tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \
$(evaluate-test)
@@ -494,7 +494,8 @@ CFLAGS-tst-initializers1-gnu11.c += $(CFLAGS-tst-initializers1-<)
tst-cancel7-ARGS = --command "exec $(host-test-program-cmd)"
tst-cancelx7-ARGS = $(tst-cancel7-ARGS)
-tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace
+tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-stack3-mem.out: $(objpfx)tst-stack3.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@; \
$(evaluate-test)
@@ -311,43 +311,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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-vfork3-mem.out: $(objpfx)tst-vfork3.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-vfork3.mtrace > $@; \
@@ -356,18 +363,22 @@ $(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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-boost-mem.out: $(objpfx)tst-boost.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-boost.mtrace > $@; \
$(evaluate-test)
@@ -382,15 +393,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=$(common-objpfx)/malloc/libc_malloc_debug.so
-bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bug-glob2.mtrace
+bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bug-glob2.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-glob-tilde-mem.out: $(objpfx)tst-glob-tilde.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-glob-tilde.mtrace > $@; \
@@ -156,19 +156,22 @@ $(objpfx)tst-res_hconf_reorder: $(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=$(common-objpfx)/malloc/libc_malloc_debug.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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
{ test -r $(objpfx)tst-leaks2.mtrace \
|| ( echo "tst-leaks2.mtrace does not exist"; exit 77; ) \
&& $(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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)mtrace-tst-resolv-res_ninit.out: $(objpfx)tst-resolv-res_ninit.out
$(common-objpfx)malloc/mtrace \
$(objpfx)tst-resolv-res_ninit.mtrace > $@; \
@@ -110,15 +110,20 @@ $(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=$(common-objpfx)/malloc/libc_malloc_debug.so
tst-vfprintf-width-prec-ENV = \
- MALLOC_TRACE=$(objpfx)tst-vfprintf-width-prec.mtrace
+ MALLOC_TRACE=$(objpfx)tst-vfprintf-width-prec.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
tst-printf-bz25691-ENV = \
- MALLOC_TRACE=$(objpfx)tst-printf-bz25691.mtrace
+ MALLOC_TRACE=$(objpfx)tst-printf-bz25691.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
tst-printf-fp-free-ENV = \
- MALLOC_TRACE=$(objpfx)tst-printf-fp-free.mtrace
+ MALLOC_TRACE=$(objpfx)tst-printf-fp-free.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
tst-printf-fp-leak-ENV = \
- MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace
+ MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
@@ -211,7 +211,8 @@ tst-umask1-ARGS = $(objpfx)tst-umask1.temp
$(objpfx)tst-atfork2: $(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=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-atfork2mod.so: $(shared-thread-library)
ifeq ($(build-shared),yes)