aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--Rules9
-rw-r--r--catgets/Makefile4
-rw-r--r--elf/Makefile15
-rw-r--r--elf/tst-leaks1-static.c1
-rw-r--r--iconvdata/Makefile3
-rwxr-xr-xintl/tst-gettext.sh1
-rw-r--r--libio/Makefile12
-rw-r--r--localedata/Makefile3
-rw-r--r--malloc/Makefile47
-rw-r--r--malloc/Versions20
-rw-r--r--malloc/arena.c7
-rw-r--r--malloc/hooks.c64
-rw-r--r--malloc/malloc-debug.c189
-rw-r--r--malloc/malloc.c85
-rw-r--r--malloc/mcheck.c1
-rw-r--r--malloc/mtrace.c1
-rw-r--r--malloc/tst-compathooks-off.c145
-rw-r--r--malloc/tst-compathooks-on.c2
-rw-r--r--malloc/tst-malloc-usable-static-tunables.c1
-rw-r--r--malloc/tst-malloc-usable-static.c1
-rwxr-xr-xmalloc/tst-mtrace.sh1
-rw-r--r--manual/memory.texi16
-rw-r--r--manual/tunables.texi4
-rw-r--r--misc/Makefile6
-rw-r--r--nptl/Makefile3
-rw-r--r--posix/Makefile40
-rw-r--r--resolv/Makefile9
-rw-r--r--shlib-versions3
-rw-r--r--stdio-common/Makefile15
-rw-r--r--sysdeps/generic/libc_malloc_debug.abilist0
-rw-r--r--sysdeps/mach/hurd/Makefile1
-rw-r--r--sysdeps/mach/hurd/i386/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/pthread/Makefile3
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/alpha/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/arm/be/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/arm/le/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/csky/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/hppa/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/hppa/shlib-versions2
-rw-r--r--sysdeps/unix/sysv/linux/i386/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/ia64/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/ia64/shlib-versions2
-rw-r--r--sysdeps/unix/sysv/linux/m68k/coldfire/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/m68k/m680x0/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/be/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/le/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/fpu/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n32/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n64/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/mips/shlib-versions2
-rw-r--r--sysdeps/unix/sysv/linux/nios2/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/riscv/rv32/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/riscv/rv64/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/sh/be/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/sh/le/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/sh/shlib-versions1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/shlib-versions1
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/64/libc_malloc_debug.abilist9
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/libc_malloc_debug.abilist9
71 files changed, 865 insertions, 158 deletions
diff --git a/NEWS b/NEWS
index 75ad8a9b95..fa80c9685b 100644
--- a/NEWS
+++ b/NEWS
@@ -132,6 +132,12 @@ Deprecated and removed features, and other changes affecting compatibility:
applications will continue to link against these symbols but the interfaces
no longer have any effect on malloc.
+* 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
diff --git a/Rules b/Rules
index ba13598df6..b1137afe71 100644
--- a/Rules
+++ b/Rules
@@ -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.
diff --git a/catgets/Makefile b/catgets/Makefile
index 54da9a985f..215965b352 100644
--- a/catgets/Makefile
+++ b/catgets/Makefile
@@ -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.
diff --git a/elf/Makefile b/elf/Makefile
index 4fe60947ad..87a70d6c7a 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -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
@@ -904,7 +904,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
@@ -1282,12 +1283,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)
$(objpfx)tst-thrlock.out: $(libm)
diff --git a/elf/tst-leaks1-static.c b/elf/tst-leaks1-static.c
deleted file mode 100644
index b956d66905..0000000000
--- a/elf/tst-leaks1-static.c
+++ /dev/null
@@ -1 +0,0 @@
-#include "tst-leaks1.c"
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index bb3f621b49..c216f959df 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -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)
diff --git a/intl/tst-gettext.sh b/intl/tst-gettext.sh
index 77864de18c..37d9fcb80a 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/libc_malloc_debug.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 73f731e064..5336b7d595 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -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
diff --git a/localedata/Makefile b/localedata/Makefile
index 14e04cd3c5..f585e0dd41 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -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)
diff --git a/malloc/Makefile b/malloc/Makefile
index bbb70f6f87..cafe427097 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -46,12 +46,11 @@ 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
# Test for the malloc_set_state symbol removed in glibc 2.25.
-ifeq ($(have-GLIBC_2.24)$(build-shared),yesyes)
-tests += tst-mallocstate
+ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
+tests += tst-mallocstate tst-compathooks-off tst-compathooks-on
endif
tests-internal := tst-scratch_buffer
@@ -64,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)
@@ -73,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))
@@ -91,15 +90,14 @@ 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-realloc \
tst-pvalloc-fortify \
- tst-reallocarray
+ tst-reallocarray \
+ tst-compathooks-off tst-compathooks-on
tests-mcheck = $(filter-out $(tests-exclude-mcheck), $(tests))
endif
@@ -122,8 +120,8 @@ routines = malloc 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.
@@ -138,6 +136,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)
@@ -244,11 +245,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
@@ -303,12 +305,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)
@@ -322,3 +326,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
diff --git a/malloc/Versions b/malloc/Versions
index 470a940666..c87f6df8ca 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -98,3 +98,23 @@ libc {
__libc_alloc_buffer_create_failure;
}
}
+
+# Keep in sync with symbols in libc.
+libc_malloc_debug {
+ GLIBC_2.0 {
+ calloc;
+ free;
+ malloc;
+ memalign;
+ pvalloc;
+ realloc;
+ valloc;
+
+ }
+ GLIBC_2.2 {
+ posix_memalign;
+ }
+ GLIBC_2.16 {
+ aligned_alloc;
+ }
+}
diff --git a/malloc/arena.c b/malloc/arena.c
index f1693ed48f..9111b49589 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -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) */
diff --git a/malloc/hooks.c b/malloc/hooks.c
index 4aa6dadcff..3cd44eeb84 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -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,6 +17,16 @@
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
+#ifndef weak_variable
+# define weak_variable weak_function
+#endif
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24)
+void (*__malloc_initialize_hook) (void);
+compat_symbol (libc, __malloc_initialize_hook,
+ __malloc_initialize_hook, GLIBC_2_0);
+#endif
+
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
void weak_variable (*__after_morecore_hook) (void) = NULL;
compat_symbol (libc, __after_morecore_hook, __after_morecore_hook, GLIBC_2_0);
@@ -24,32 +34,64 @@ void *(*__morecore)(ptrdiff_t);
compat_symbol (libc, __morecore, __morecore, 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"
diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c
new file mode 100644
index 0000000000..41dfcd3369
--- /dev/null
+++ b/malloc/malloc-debug.c
@@ -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 *
+_debug_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 _debug_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 _debug_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 _debug_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 = _debug_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)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 6e8fa9e424..cf71314b2b 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -573,16 +573,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
@@ -2008,38 +1998,6 @@ static void malloc_consolidate (mstate);
/* -------------- Early definitions for debugging hooks ---------------- */
-/* Define and initialize the hook variables. These weak definitions must
- appear before any use of the variables in a function (arena.c uses one). */
-#ifndef weak_variable
-/* In GNU libc we want the hook variables to be weak definitions to
- avoid a problem with Emacs. */
-# 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);
-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;
/* This function is called from the arena shutdown hook, to free the
thread cache (if it exists). */
static void tcache_thread_shutdown (void);
@@ -3237,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;
@@ -3301,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;
@@ -3360,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)
@@ -3498,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);
}
@@ -3508,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);
@@ -3621,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 ();
@@ -5659,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
diff --git a/malloc/mcheck.c b/malloc/mcheck.c
index d2efcfb742..1e68cedbf5 100644
--- a/malloc/mcheck.c
+++ b/malloc/mcheck.c
@@ -26,6 +26,7 @@
# include <stdio.h>
# include <libintl.h>
# include <errno.h>
+# include <malloc-internal.h>
#endif
/* Old hook values. */
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
index 6c2c58b706..fb58413d39 100644
--- a/malloc/mtrace.c
+++ b/malloc/mtrace.c
@@ -22,6 +22,7 @@
# define _MALLOC_INTERNAL
# include <malloc.h>
# include <mcheck.h>
+# include <malloc-internal.h>
# include <libc-lock.h>
#endif
diff --git a/malloc/tst-compathooks-off.c b/malloc/tst-compathooks-off.c
new file mode 100644
index 0000000000..7b3722d8b3
--- /dev/null
+++ b/malloc/tst-compathooks-off.c
@@ -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>
diff --git a/malloc/tst-compathooks-on.c b/malloc/tst-compathooks-on.c
new file mode 100644
index 0000000000..4da183687a
--- /dev/null
+++ b/malloc/tst-compathooks-on.c
@@ -0,0 +1,2 @@
+#define HOOKS_ENABLED 1
+#include "tst-compathooks-off.c"
diff --git a/malloc/tst-malloc-usable-static-tunables.c b/malloc/tst-malloc-usable-static-tunables.c
deleted file mode 100644
index 8907db01a5..0000000000
--- a/malloc/tst-malloc-usable-static-tunables.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <malloc/tst-malloc-usable.c>
diff --git a/malloc/tst-malloc-usable-static.c b/malloc/tst-malloc-usable-static.c
deleted file mode 100644
index 8907db01a5..0000000000
--- a/malloc/tst-malloc-usable-static.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <malloc/tst-malloc-usable.c>
diff --git a/malloc/tst-mtrace.sh b/malloc/tst-mtrace.sh
index 9295683aff..a830204d5e 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/libc_malloc_debug.so \
${test_program_prefix_after_env} \
${common_objpfx}malloc/tst-mtrace || status=1
diff --git a/manual/memory.texi b/manual/memory.texi
index 31ee36be8c..93305f289b 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -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 less than 4, 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.
+against, 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
diff --git a/manual/tunables.texi b/manual/tunables.texi
index ebdb562e36..e264e9150c 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -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 less than 4 enables a special (less
efficient) memory allocator for the @code{malloc} family of functions that is
diff --git a/misc/Makefile b/misc/Makefile
index 22923efde9..1083ba3bfc 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -155,13 +155,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)
diff --git a/nptl/Makefile b/nptl/Makefile
index 9b94bfcd31..ff4d590f11 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -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)
diff --git a/posix/Makefile b/posix/Makefile
index d82e43eaad..b895638865 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -313,43 +313,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 > $@; \
@@ -358,18 +365,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)
@@ -384,15 +395,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 > $@; \
diff --git a/resolv/Makefile b/resolv/Makefile
index e138a1fdac..59e599535c 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -215,19 +215,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 > $@; \
diff --git a/shlib-versions b/shlib-versions
index edabba08eb..df6603e699 100644
--- a/shlib-versions
+++ b/shlib-versions
@@ -73,3 +73,6 @@ libgcc_s=1
# The vector math library
libmvec=1
+
+# The malloc debug library
+libc_malloc_debug=0
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index f87796a8ce..803f16dae0 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -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)'; \
diff --git a/sysdeps/generic/libc_malloc_debug.abilist b/sysdeps/generic/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/sysdeps/generic/libc_malloc_debug.abilist
diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
index 46bd7b4600..17bb643c18 100644
--- a/sysdeps/mach/hurd/Makefile
+++ b/sysdeps/mach/hurd/Makefile
@@ -222,5 +222,6 @@ CFLAGS-ypclnt.c += -DUSE_BINDINGDIR=1
endif
LDLIBS-pthread.so += $(objdir)/hurd/libhurduser.so
+LDLIBS-c_malloc_debug.so += $(link-rpcuserlibs)
endif # in-Makerules
diff --git a/sysdeps/mach/hurd/i386/libc_malloc_debug.abilist b/sysdeps/mach/hurd/i386/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..393ef2acd7
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2.6 calloc F
+GLIBC_2.2.6 free F
+GLIBC_2.2.6 malloc F
+GLIBC_2.2.6 memalign F
+GLIBC_2.2.6 posix_memalign F
+GLIBC_2.2.6 pvalloc F
+GLIBC_2.2.6 realloc F
+GLIBC_2.2.6 valloc F
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
index 9b862b93c4..42f9fc5072 100644
--- a/sysdeps/pthread/Makefile
+++ b/sysdeps/pthread/Makefile
@@ -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)
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/aarch64/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..2b183c90d4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.17 aligned_alloc F
+GLIBC_2.17 calloc F
+GLIBC_2.17 free F
+GLIBC_2.17 malloc F
+GLIBC_2.17 memalign F
+GLIBC_2.17 posix_memalign F
+GLIBC_2.17 pvalloc F
+GLIBC_2.17 realloc F
+GLIBC_2.17 valloc F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/alpha/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..3ec745c9ac
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.32 aligned_alloc F
+GLIBC_2.32 calloc F
+GLIBC_2.32 free F
+GLIBC_2.32 malloc F
+GLIBC_2.32 memalign F
+GLIBC_2.32 posix_memalign F
+GLIBC_2.32 pvalloc F
+GLIBC_2.32 realloc F
+GLIBC_2.32 valloc F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/arm/be/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..f7938d075f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arm/be/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.4 calloc F
+GLIBC_2.4 free F
+GLIBC_2.4 malloc F
+GLIBC_2.4 memalign F
+GLIBC_2.4 posix_memalign F
+GLIBC_2.4 pvalloc F
+GLIBC_2.4 realloc F
+GLIBC_2.4 valloc F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/arm/le/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..f7938d075f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arm/le/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.4 calloc F
+GLIBC_2.4 free F
+GLIBC_2.4 malloc F
+GLIBC_2.4 memalign F
+GLIBC_2.4 posix_memalign F
+GLIBC_2.4 pvalloc F
+GLIBC_2.4 realloc F
+GLIBC_2.4 valloc F
diff --git a/sysdeps/unix/sysv/linux/csky/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/csky/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..54da2c3e38
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.29 aligned_alloc F
+GLIBC_2.29 calloc F
+GLIBC_2.29 free F
+GLIBC_2.29 malloc F
+GLIBC_2.29 memalign F
+GLIBC_2.29 posix_memalign F
+GLIBC_2.29 pvalloc F
+GLIBC_2.29 realloc F
+GLIBC_2.29 valloc F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/hppa/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..3ea834d9a2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 calloc F
+GLIBC_2.2 free F
+GLIBC_2.2 malloc F
+GLIBC_2.2 memalign F
+GLIBC_2.2 posix_memalign F
+GLIBC_2.2 pvalloc F
+GLIBC_2.2 realloc F
+GLIBC_2.2 valloc F
diff --git a/sysdeps/unix/sysv/linux/hppa/shlib-versions b/sysdeps/unix/sysv/linux/hppa/shlib-versions
index 3a2d496220..7818a32cc4 100644
--- a/sysdeps/unix/sysv/linux/hppa/shlib-versions
+++ b/sysdeps/unix/sysv/linux/hppa/shlib-versions
@@ -7,3 +7,5 @@ ld=ld.so.1 GLIBC_2.2
libBrokenLocale=1 GLIBC_2.2
libpthread=0 GLIBC_2.2
+
+libc_malloc_debug=0 GLIBC_2.2
diff --git a/sysdeps/unix/sysv/linux/i386/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/i386/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/ia64/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..3ea834d9a2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 calloc F
+GLIBC_2.2 free F
+GLIBC_2.2 malloc F
+GLIBC_2.2 memalign F
+GLIBC_2.2 posix_memalign F
+GLIBC_2.2 pvalloc F
+GLIBC_2.2 realloc F
+GLIBC_2.2 valloc F
diff --git a/sysdeps/unix/sysv/linux/ia64/shlib-versions b/sysdeps/unix/sysv/linux/ia64/shlib-versions
index 37374c0e20..f57e5bae5e 100644
--- a/sysdeps/unix/sysv/linux/ia64/shlib-versions
+++ b/sysdeps/unix/sysv/linux/ia64/shlib-versions
@@ -6,3 +6,5 @@ ld=ld-linux-ia64.so.2 GLIBC_2.2
libBrokenLocale=1 GLIBC_2.2
libpthread=0 GLIBC_2.2
+
+libc_malloc_debug=0 GLIBC_2.2
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..f7938d075f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.4 calloc F
+GLIBC_2.4 free F
+GLIBC_2.4 malloc F
+GLIBC_2.4 memalign F
+GLIBC_2.4 posix_memalign F
+GLIBC_2.4 pvalloc F
+GLIBC_2.4 realloc F
+GLIBC_2.4 valloc F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..d02da8ef66
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.18 aligned_alloc F
+GLIBC_2.18 calloc F
+GLIBC_2.18 free F
+GLIBC_2.18 malloc F
+GLIBC_2.18 memalign F
+GLIBC_2.18 posix_memalign F
+GLIBC_2.18 pvalloc F
+GLIBC_2.18 realloc F
+GLIBC_2.18 valloc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..d02da8ef66
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.18 aligned_alloc F
+GLIBC_2.18 calloc F
+GLIBC_2.18 free F
+GLIBC_2.18 malloc F
+GLIBC_2.18 memalign F
+GLIBC_2.18 posix_memalign F
+GLIBC_2.18 pvalloc F
+GLIBC_2.18 realloc F
+GLIBC_2.18 valloc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/mips/shlib-versions b/sysdeps/unix/sysv/linux/mips/shlib-versions
index ecfe1845f4..c57674deec 100644
--- a/sysdeps/unix/sysv/linux/mips/shlib-versions
+++ b/sysdeps/unix/sysv/linux/mips/shlib-versions
@@ -23,3 +23,5 @@ libnsl=1 GLIBC_2.0 GLIBC_2.2
librt=1 GLIBC_2.0 GLIBC_2.2
libpthread=0 GLIBC_2.0 GLIBC_2.2
+
+libc_malloc_debug=0 GLIBC_2.0 GLIBC_2.2
diff --git a/sysdeps/unix/sysv/linux/nios2/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/nios2/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..658c965b08
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nios2/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.21 aligned_alloc F
+GLIBC_2.21 calloc F
+GLIBC_2.21 free F
+GLIBC_2.21 malloc F
+GLIBC_2.21 memalign F
+GLIBC_2.21 posix_memalign F
+GLIBC_2.21 pvalloc F
+GLIBC_2.21 realloc F
+GLIBC_2.21 valloc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..921079580c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.3 calloc F
+GLIBC_2.3 free F
+GLIBC_2.3 malloc F
+GLIBC_2.3 memalign F
+GLIBC_2.3 posix_memalign F
+GLIBC_2.3 pvalloc F
+GLIBC_2.3 realloc F
+GLIBC_2.3 valloc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..2b183c90d4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.17 aligned_alloc F
+GLIBC_2.17 calloc F
+GLIBC_2.17 free F
+GLIBC_2.17 malloc F
+GLIBC_2.17 memalign F
+GLIBC_2.17 posix_memalign F
+GLIBC_2.17 pvalloc F
+GLIBC_2.17 realloc F
+GLIBC_2.17 valloc F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..05c8ba8c9f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.33 aligned_alloc F
+GLIBC_2.33 calloc F
+GLIBC_2.33 free F
+GLIBC_2.33 malloc F
+GLIBC_2.33 memalign F
+GLIBC_2.33 posix_memalign F
+GLIBC_2.33 pvalloc F
+GLIBC_2.33 realloc F
+GLIBC_2.33 valloc F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..20531a7372
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.27 aligned_alloc F
+GLIBC_2.27 calloc F
+GLIBC_2.27 free F
+GLIBC_2.27 malloc F
+GLIBC_2.27 memalign F
+GLIBC_2.27 posix_memalign F
+GLIBC_2.27 pvalloc F
+GLIBC_2.27 realloc F
+GLIBC_2.27 valloc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..3ea834d9a2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 calloc F
+GLIBC_2.2 free F
+GLIBC_2.2 malloc F
+GLIBC_2.2 memalign F
+GLIBC_2.2 posix_memalign F
+GLIBC_2.2 pvalloc F
+GLIBC_2.2 realloc F
+GLIBC_2.2 valloc F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/sh/be/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..3ea834d9a2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sh/be/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 calloc F
+GLIBC_2.2 free F
+GLIBC_2.2 malloc F
+GLIBC_2.2 memalign F
+GLIBC_2.2 posix_memalign F
+GLIBC_2.2 pvalloc F
+GLIBC_2.2 realloc F
+GLIBC_2.2 valloc F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/sh/le/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..3ea834d9a2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sh/le/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 calloc F
+GLIBC_2.2 free F
+GLIBC_2.2 malloc F
+GLIBC_2.2 memalign F
+GLIBC_2.2 posix_memalign F
+GLIBC_2.2 pvalloc F
+GLIBC_2.2 realloc F
+GLIBC_2.2 valloc F
diff --git a/sysdeps/unix/sysv/linux/sh/shlib-versions b/sysdeps/unix/sysv/linux/sh/shlib-versions
index 9333bbd7a3..3124264300 100644
--- a/sysdeps/unix/sysv/linux/sh/shlib-versions
+++ b/sysdeps/unix/sysv/linux/sh/shlib-versions
@@ -3,3 +3,4 @@ libc=6 GLIBC_2.2
ld=ld-linux.so.2 GLIBC_2.2
libBrokenLocale=1 GLIBC_2.2
libpthread=0 GLIBC_2.2
+libc_malloc_debug=0 GLIBC_2.2
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..7621d1266e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.0 calloc F
+GLIBC_2.0 free F
+GLIBC_2.0 malloc F
+GLIBC_2.0 memalign F
+GLIBC_2.0 pvalloc F
+GLIBC_2.0 realloc F
+GLIBC_2.0 valloc F
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 posix_memalign F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..3ea834d9a2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2 calloc F
+GLIBC_2.2 free F
+GLIBC_2.2 malloc F
+GLIBC_2.2 memalign F
+GLIBC_2.2 posix_memalign F
+GLIBC_2.2 pvalloc F
+GLIBC_2.2 realloc F
+GLIBC_2.2 valloc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/shlib-versions b/sysdeps/unix/sysv/linux/sparc/sparc64/shlib-versions
index 9333bbd7a3..3124264300 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/shlib-versions
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/shlib-versions
@@ -3,3 +3,4 @@ libc=6 GLIBC_2.2
ld=ld-linux.so.2 GLIBC_2.2
libBrokenLocale=1 GLIBC_2.2
libpthread=0 GLIBC_2.2
+libc_malloc_debug=0 GLIBC_2.2
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..723c5f48f0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.2.5 calloc F
+GLIBC_2.2.5 free F
+GLIBC_2.2.5 malloc F
+GLIBC_2.2.5 memalign F
+GLIBC_2.2.5 posix_memalign F
+GLIBC_2.2.5 pvalloc F
+GLIBC_2.2.5 realloc F
+GLIBC_2.2.5 valloc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc_malloc_debug.abilist
new file mode 100644
index 0000000000..c506f45101
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc_malloc_debug.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.16 aligned_alloc F
+GLIBC_2.16 calloc F
+GLIBC_2.16 free F
+GLIBC_2.16 malloc F
+GLIBC_2.16 memalign F
+GLIBC_2.16 posix_memalign F
+GLIBC_2.16 pvalloc F
+GLIBC_2.16 realloc F
+GLIBC_2.16 valloc F