public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v5 0/8] malloc hooks removal
@ 2021-07-05 17:08 Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 1/8] Move malloc hooks into a compat DSO Siddhesh Poyarekar
                   ` (8 more replies)
  0 siblings, 9 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

This patchset removes the malloc hooks __malloc_hook, __free_hook,
__realloc_hook and __memalign_hook from the API and leaves compatibility
symbols so that existing applications can continue to link to them.  The
reading and execution of the hooks has been moved to a DSO
libc_malloc_debug.so, which can be preloaded for applications that need
it.  By default these hooks no longer have any effect in the library.

Further, debugging features such as MALLOC_CHECK_, mcheck() and mtrace
have been weaned away from these hooks and also moved to
libc_malloc_debug.so.  With this change, these features are only enabled
when libc_malloc_debug.so is preloaded using LD_PRELOAD.

Finally, the __morecore, __morecore_after_hook and __default_morecore
hooks have also been moved to compat symbols and removed from the API.
Existing applications will continue to link to them but they won't have
any effect on malloc behaviour.

Changes from v4:
- Patchset has a different approach, starting with moving out hooks
  first to restrict all major malloc.c changes to the first patch
- Renamed libmalloc_compathooks.so to libc_malloc_debug.so
- Moved all debugging features into libc_malloc_debug.so
- Made more documentation updates
- Simplified __malloc_initialized variable use
- Removed debugging tests on static variables since that is no longer
  supported

Changes from v3:
- Remove source file dependencies
- Commit mcheck tests

Changes from v2:
- Move hooks dependencies to malloc.o{,sS}

Changes from v1:

- Added makefile dependencies for the new hooks files
- Fixed memset call in calloc debugging hooks
- Added the tr_break deprecation patch and mcheck test patch to this
  series

Siddhesh Poyarekar (8):
  Move malloc hooks into a compat DSO
  mcheck: Wean away from malloc hooks
  Simplify __malloc_initialized
  mtrace: Wean away from malloc hooks
  glibc.malloc.check: Wean away from malloc hooks
  Remove malloc hooks
  Remove __after_morecore_hook
  Remove __morecore and __default_morecore

 Makeconfig                                 |   2 +-
 NEWS                                       |  21 ++
 Rules                                      |   9 +-
 catgets/Makefile                           |   4 +-
 elf/Makefile                               |  18 +-
 elf/tst-leaks1-static.c                    |   1 -
 iconvdata/Makefile                         |   3 +-
 include/malloc.h                           |   6 -
 include/mcheck.h                           |   4 -
 include/stdlib.h                           |   3 -
 intl/tst-gettext.sh                        |   1 +
 libio/Makefile                             |  12 +-
 localedata/Makefile                        |   3 +-
 malloc/Makefile                            |  44 ++-
 malloc/Versions                            |   9 +
 malloc/arena.c                             |  42 +--
 malloc/hooks.c                             |  84 ++++-
 malloc/malloc-check.c                      |  86 +++--
 malloc/{malloc-hooks.h => malloc-check.h}  |  22 +-
 malloc/malloc-debug.c                      | 346 ++++++++++++++++++
 malloc/malloc-internal.h                   |   5 +
 malloc/malloc.c                            | 135 ++-----
 malloc/malloc.h                            |  27 --
 malloc/mcheck-impl.c                       | 406 +++++++++++++++++++++
 malloc/mcheck.c                            | 396 ++------------------
 malloc/morecore.c                          |  15 +-
 malloc/mtrace-impl.c                       | 224 ++++++++++++
 malloc/mtrace.c                            | 313 +---------------
 malloc/tst-compathooks-off.c               | 145 ++++++++
 malloc/tst-compathooks-on.c                |   2 +
 malloc/tst-malloc-usable-static-tunables.c |   1 -
 malloc/tst-malloc-usable-static.c          |   1 -
 malloc/tst-mtrace.sh                       |   1 +
 manual/memory.texi                         | 207 +----------
 manual/tunables.texi                       |   4 +-
 misc/Makefile                              |   6 +-
 nptl/Makefile                              |   3 +-
 posix/Makefile                             |  40 +-
 resolv/Makefile                            |   9 +-
 stdio-common/Makefile                      |  15 +-
 sysdeps/pthread/Makefile                   |   3 +-
 41 files changed, 1502 insertions(+), 1176 deletions(-)
 delete mode 100644 elf/tst-leaks1-static.c
 rename malloc/{malloc-hooks.h => malloc-check.h} (55%)
 create mode 100644 malloc/malloc-debug.c
 create mode 100644 malloc/mcheck-impl.c
 create mode 100644 malloc/mtrace-impl.c
 create mode 100644 malloc/tst-compathooks-off.c
 create mode 100644 malloc/tst-compathooks-on.c
 delete mode 100644 malloc/tst-malloc-usable-static-tunables.c
 delete mode 100644 malloc/tst-malloc-usable-static.c

-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 1/8] Move malloc hooks into a compat DSO
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-06 10:17   ` Florian Weimer
  2021-07-05 17:08 ` [PATCH v5 2/8] mcheck: Wean away from malloc hooks Siddhesh Poyarekar
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

Remove all malloc hook uses from core malloc functions and move it
into a new library libc_malloc_debug.so.  With this, the hooks now no
longer have any effect on the core library.

libc_malloc_debug.so is a malloc interposer that needs to be preloaded
to get hooks functionality back so that the debugging features that
depend on the hooks, i.e. malloc-check, mcheck and mtrace work again.
Without the preloaded DSO these debugging features will be nops.
These features will be ported away from hooks in subsequent patches.

Similarly, legacy applications that need hooks functionality need to
preload libc_malloc_debug.so.

Finally, static binaries will no longer be able to use malloc
debugging features since they cannot preload the debugging DSO.
---
 Makeconfig                                 |   2 +-
 NEWS                                       |   6 +
 Rules                                      |   9 +-
 catgets/Makefile                           |   4 +-
 elf/Makefile                               |  18 +-
 elf/tst-leaks1-static.c                    |   1 -
 iconvdata/Makefile                         |   3 +-
 intl/tst-gettext.sh                        |   1 +
 libio/Makefile                             |  12 +-
 localedata/Makefile                        |   3 +-
 malloc/Makefile                            |  44 +++--
 malloc/arena.c                             |   7 -
 malloc/hooks.c                             |  60 +++++--
 malloc/malloc-debug.c                      | 189 +++++++++++++++++++++
 malloc/malloc.c                            |  77 ++-------
 malloc/mcheck.c                            |   1 +
 malloc/mtrace.c                            |   1 +
 malloc/tst-compathooks-off.c               | 145 ++++++++++++++++
 malloc/tst-compathooks-on.c                |   2 +
 malloc/tst-malloc-usable-static-tunables.c |   1 -
 malloc/tst-malloc-usable-static.c          |   1 -
 malloc/tst-mtrace.sh                       |   1 +
 manual/memory.texi                         |  16 +-
 manual/tunables.texi                       |   4 +-
 misc/Makefile                              |   6 +-
 nptl/Makefile                              |   3 +-
 posix/Makefile                             |  40 +++--
 resolv/Makefile                            |   9 +-
 stdio-common/Makefile                      |  15 +-
 sysdeps/pthread/Makefile                   |   3 +-
 30 files changed, 534 insertions(+), 150 deletions(-)
 delete mode 100644 elf/tst-leaks1-static.c
 create mode 100644 malloc/malloc-debug.c
 create mode 100644 malloc/tst-compathooks-off.c
 create mode 100644 malloc/tst-compathooks-on.c
 delete mode 100644 malloc/tst-malloc-usable-static-tunables.c
 delete mode 100644 malloc/tst-malloc-usable-static.c

diff --git a/Makeconfig b/Makeconfig
index efc7351d71..6319941ef9 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -951,7 +951,7 @@ libio-include = -I$(..)libio
 built-modules = iconvprogs iconvdata ldconfig lddlibc4 libmemusage \
 		libSegFault libpcprofile librpcsvc locale-programs \
 		memusagestat nonlib nscd extramodules libnldbl libsupport \
-		testsuite
+		testsuite libc_malloc_debug
 
 in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
 				    $(libof-$(<F)) \
diff --git a/NEWS b/NEWS
index 8e72946c3f..213d790024 100644
--- a/NEWS
+++ b/NEWS
@@ -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
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 698a6ab985..b432e78d39 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
@@ -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)
 
@@ -1561,7 +1558,8 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
 				   $(objpfx)tst-nodelete-dlclose-plugin.so
 
 tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
-		     LD_HWCAP_MASK=0x1
+		     LD_HWCAP_MASK=0x1 \
+		     LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
 
 $(objpfx)tst-debug1.out: $(objpfx)tst-debug1mod1.so
 
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 2f9b3d596d..deff659d34 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -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,12 +88,11 @@ 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_memalign \
+	tst-compathooks-off tst-compathooks-on
 
 tests-mcheck = $(filter-out $(tests-exclude-mcheck), $(tests))
 
@@ -115,8 +114,8 @@ routines = malloc morecore mcheck mtrace obstack reallocarray \
 install-lib := libmcheck.a
 non-lib.a := libmcheck.a
 
-# Additional library.
-extra-libs = libmemusage
+# Additional libraries.
+extra-libs = libmemusage libc_malloc_debug
 extra-libs-others = $(extra-libs)
 
 # Helper objects for some tests.
@@ -131,6 +130,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)
@@ -236,11 +238,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
 
@@ -295,12 +298,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)
@@ -314,3 +319,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/arena.c b/malloc/arena.c
index 7eb110445e..8f890d5ff0 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 daa5c7cfae..b18c2b8c90 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,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 libmalloc_compathooks.  This means that the calls to malloc,
+   realloc, etc. will lead back into the interposed functions, which is what we
+   want.
+
+   These initial hooks are assumed to be called in a single-threaded context,
+   so it is safe to reset all hooks at once upon initialization.  */
+
+static void
+generic_hook_ini (void)
 {
   __malloc_hook = NULL;
+  __realloc_hook = NULL;
+  __memalign_hook = NULL;
   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..1c80c33f43
--- /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 *
+_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)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index bb9a1642aa..d2e45664b1 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -570,16 +570,6 @@ tag_at (void *ptr)
 #define HAVE_MREMAP 0
 #endif
 
-/* We may need to support __malloc_initialize_hook for backwards
-   compatibility.  */
-
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24)
-# define HAVE_MALLOC_INIT_HOOK 1
-#else
-# define HAVE_MALLOC_INIT_HOOK 0
-#endif
-
-
 /*
   This version of malloc supports the standard SVID/XPG mallinfo
   routine that returns a struct containing usage properties and
@@ -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
diff --git a/malloc/mcheck.c b/malloc/mcheck.c
index 2a1fc645d4..b46b9b26bf 100644
--- a/malloc/mcheck.c
+++ b/malloc/mcheck.c
@@ -25,6 +25,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 f5b8321c6b..274db3fb47 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..b1290cf367
--- /dev/null
+++ b/malloc/tst-compathooks-off.c
@@ -0,0 +1,145 @@
+/* Minimal tests to verify libmalloc_compathooks.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 28ec2e4e63..0aae1f8720 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, 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
diff --git a/manual/tunables.texi b/manual/tunables.texi
index d5d957fb5b..b9c52a0090 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 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 ae03e26f1b..b144a3df6c 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -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)
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 e91ea25ba1..3f1649369a 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -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 > $@; \
diff --git a/resolv/Makefile b/resolv/Makefile
index 1d3565d478..09b2f129eb 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -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 > $@; \
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/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)
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 2/8] mcheck: Wean away from malloc hooks
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 1/8] Move malloc hooks into a compat DSO Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 3/8] Simplify __malloc_initialized Siddhesh Poyarekar
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

Split the mcheck implementation into the debugging hooks and API so
that the API can be replicated in libc and libc_malloc_debug.so.  The
libc APIs always result in failure.

The mcheck implementation has also been moved entirely into
libc_malloc_debug.so and its initialization is now dependent upon
whether the debug versions of malloc, realloc, etc. were called or
not.  That is, it no longer depends on __malloc_initialized and
consequently, on any internal glibc constructs.
---
 include/mcheck.h      |   4 -
 malloc/Makefile       |   2 -
 malloc/hooks.c        |   1 -
 malloc/malloc-debug.c | 112 ++++++++++--
 malloc/mcheck-impl.c  | 406 ++++++++++++++++++++++++++++++++++++++++++
 malloc/mcheck.c       | 397 +++--------------------------------------
 6 files changed, 527 insertions(+), 395 deletions(-)
 create mode 100644 malloc/mcheck-impl.c

diff --git a/include/mcheck.h b/include/mcheck.h
index 8883c3d53e..5ad7cd1313 100644
--- a/include/mcheck.h
+++ b/include/mcheck.h
@@ -3,9 +3,5 @@
 #include <malloc/mcheck.h>
 
 # ifndef _ISOMAC
-
-libc_hidden_proto (mcheck)
-libc_hidden_proto (mcheck_check_all)
-
 # endif /* !_ISOMAC */
 #endif
diff --git a/malloc/Makefile b/malloc/Makefile
index deff659d34..b1c8e3c9e0 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -90,8 +90,6 @@ tests-exclude-mcheck = tst-mallocstate \
 	tst-malloc-thread-fail \
 	tst-malloc-usable-tunables \
 	tst-malloc_info \
-	tst-memalign \
-	tst-posix_memalign \
 	tst-compathooks-off tst-compathooks-on
 
 tests-mcheck = $(filter-out $(tests-exclude-mcheck), $(tests))
diff --git a/malloc/hooks.c b/malloc/hooks.c
index b18c2b8c90..d924e35e6f 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -59,7 +59,6 @@ generic_hook_ini (void)
   if (hook != NULL)
     (*hook)();
 #endif
-  __malloc_initialized = 1;
 }
 
 static void *
diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c
index 1c80c33f43..daf48e0633 100644
--- a/malloc/malloc-debug.c
+++ b/malloc/malloc-debug.c
@@ -43,6 +43,35 @@ DEBUG_FN(valloc);
 DEBUG_FN(pvalloc);
 DEBUG_FN(calloc);
 
+static bool malloc_called;
+
+enum malloc_debug_hooks
+{
+  MALLOC_NONE_HOOK = 0,
+  MALLOC_MCHECK_HOOK = 1 << 0, /* mcheck()  */
+};
+static unsigned __malloc_debugging_hooks;
+
+static __always_inline bool
+__is_malloc_debug_enabled (enum malloc_debug_hooks flag)
+{
+  return __malloc_debugging_hooks & flag;
+}
+
+static __always_inline void
+__malloc_debug_enable (enum malloc_debug_hooks flag)
+{
+  __malloc_debugging_hooks |= flag;
+}
+
+static __always_inline void
+__malloc_debug_disable (enum malloc_debug_hooks flag)
+{
+  __malloc_debugging_hooks &= ~flag;
+}
+
+#include "mcheck.c"
+
 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 *);
@@ -63,7 +92,19 @@ __debug_malloc (size_t bytes)
   if (__builtin_expect (hook != NULL, 0))
     return (*hook)(bytes, RETURN_ADDRESS (0));
 
-  return __libc_malloc (bytes);
+  malloc_called = true;
+
+  void *victim = NULL;
+  size_t orig_bytes = bytes;
+  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+      || !malloc_mcheck_before (&bytes, &victim))
+    {
+      victim = __libc_malloc (bytes);
+    }
+  if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
+    victim = malloc_mcheck_after (victim, orig_bytes);
+
+  return victim;
 }
 strong_alias (__debug_malloc, malloc)
 
@@ -76,6 +117,10 @@ __debug_free (void *mem)
       (*hook)(mem, RETURN_ADDRESS (0));
       return;
     }
+
+  if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
+    mem = free_mcheck (mem);
+
   __libc_free (mem);
 }
 strong_alias (__debug_free, free)
@@ -88,7 +133,21 @@ __debug_realloc (void *oldmem, size_t bytes)
   if (__builtin_expect (hook != NULL, 0))
     return (*hook)(oldmem, bytes, RETURN_ADDRESS (0));
 
-  return __libc_realloc (oldmem, bytes);
+  malloc_called = true;
+
+  size_t orig_bytes = bytes, oldsize = 0;
+  void *victim = NULL;
+
+  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+      || !realloc_mcheck_before (&oldmem, &bytes, &oldsize, &victim))
+    {
+      victim = __libc_realloc (oldmem, bytes);
+    }
+  if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
+    victim = realloc_mcheck_after (victim, oldmem, orig_bytes,
+				   oldsize);
+
+  return victim;
 }
 strong_alias (__debug_realloc, realloc)
 
@@ -100,7 +159,20 @@ _mid_memalign (size_t alignment, size_t bytes, const void *address)
   if (__builtin_expect (hook != NULL, 0))
     return (*hook)(alignment, bytes, address);
 
-  return __libc_memalign (alignment, bytes);
+  malloc_called = true;
+
+  void *victim = NULL;
+  size_t orig_bytes = bytes;
+
+  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+      || !memalign_mcheck_before (alignment, &bytes, &victim))
+    {
+      victim = __libc_memalign (alignment, bytes);
+    }
+  if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
+    victim = memalign_mcheck_after (victim, alignment, orig_bytes);
+
+  return victim;
 }
 
 static void *
@@ -165,17 +237,17 @@ strong_alias (__debug_posix_memalign, posix_memalign)
 static void *
 __debug_calloc (size_t nmemb, size_t size)
 {
+  size_t bytes;
+
+  if (__glibc_unlikely (__builtin_mul_overflow (nmemb, size, &bytes)))
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+
   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)
@@ -184,6 +256,22 @@ __debug_calloc (size_t nmemb, size_t size)
       return mem;
     }
 
-  return __libc_calloc (nmemb, size);
+  malloc_called = true;
+
+  size_t orig_bytes = bytes;
+  void *victim = NULL;
+
+  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+      || !malloc_mcheck_before (&bytes, &victim))
+    {
+      victim = __libc_malloc (bytes);
+    }
+  if (victim != NULL)
+    {
+      if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
+	victim = malloc_mcheck_after (victim, orig_bytes);
+      memset (victim, 0, orig_bytes);
+    }
+  return victim;
 }
 strong_alias (__debug_calloc, calloc)
diff --git a/malloc/mcheck-impl.c b/malloc/mcheck-impl.c
new file mode 100644
index 0000000000..0b96fdabda
--- /dev/null
+++ b/malloc/mcheck-impl.c
@@ -0,0 +1,406 @@
+/* mcheck debugging hooks for malloc.
+   Copyright (C) 1990-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written May 1989 by Mike Haertel.
+
+   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 <malloc-internal.h>
+#include <mcheck.h>
+#include <libintl.h>
+#include <stdint.h>
+#include <stdio.h>
+
+/* Arbitrary magical numbers.  */
+#define MAGICWORD       0xfedabeeb
+#define MAGICFREE       0xd8675309
+#define MAGICBYTE       ((char) 0xd7)
+#define MALLOCFLOOD     ((char) 0x93)
+#define FREEFLOOD       ((char) 0x95)
+
+/* Function to call when something awful happens.  */
+static void (*abortfunc) (enum mcheck_status);
+
+struct hdr
+{
+  size_t size;                  /* Exact size requested by user.  */
+  unsigned long int magic;      /* Magic number to check header integrity.  */
+  struct hdr *prev;
+  struct hdr *next;
+  void *block;                  /* Real block allocated, for memalign.  */
+  unsigned long int magic2;     /* Extra, keeps us doubleword aligned.  */
+};
+
+/* This is the beginning of the list of all memory blocks allocated.
+   It is only constructed if the pedantic testing is requested.  */
+static struct hdr *__mcheck_root;
+
+/* Nonzero if pedentic checking of all blocks is requested.  */
+static bool pedantic;
+
+#if defined _LIBC || defined STDC_HEADERS || defined USG
+# include <string.h>
+# define flood memset
+#else
+static void flood (void *, int, size_t);
+static void
+flood (void *ptr, int val, size_t size)
+{
+  char *cp = ptr;
+  while (size--)
+    *cp++ = val;
+}
+#endif
+
+static enum mcheck_status
+checkhdr (const struct hdr *hdr)
+{
+  enum mcheck_status status;
+  bool mcheck_used = __is_malloc_debug_enabled (MALLOC_MCHECK_HOOK);
+
+  if (!mcheck_used)
+    /* Maybe the mcheck used is disabled?  This happens when we find
+       an error and report it.  */
+    return MCHECK_OK;
+
+  switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
+    {
+    default:
+      status = MCHECK_HEAD;
+      break;
+    case MAGICFREE:
+      status = MCHECK_FREE;
+      break;
+    case MAGICWORD:
+      if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+	status = MCHECK_TAIL;
+      else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
+	status = MCHECK_HEAD;
+      else
+	status = MCHECK_OK;
+      break;
+    }
+  if (status != MCHECK_OK)
+    {
+      mcheck_used = 0;
+      (*abortfunc) (status);
+      mcheck_used = 1;
+    }
+  return status;
+}
+
+static enum mcheck_status
+__mcheck_checkptr (const void *ptr)
+{
+  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
+      return MCHECK_DISABLED;
+
+  if (ptr != NULL)
+    return checkhdr (((struct hdr *) ptr) - 1);
+
+  /* Walk through all the active blocks and test whether they were tampered
+     with.  */
+  struct hdr *runp = __mcheck_root;
+
+  /* Temporarily turn off the checks.  */
+  pedantic = false;
+
+  while (runp != NULL)
+    {
+      (void) checkhdr (runp);
+
+      runp = runp->next;
+    }
+
+  /* Turn checks on again.  */
+  pedantic = true;
+
+  return MCHECK_OK;
+}
+
+static void
+unlink_blk (struct hdr *ptr)
+{
+  if (ptr->next != NULL)
+    {
+      ptr->next->prev = ptr->prev;
+      ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
+                                      + (uintptr_t) ptr->next->next);
+    }
+  if (ptr->prev != NULL)
+    {
+      ptr->prev->next = ptr->next;
+      ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
+                                      + (uintptr_t) ptr->prev->next);
+    }
+  else
+    __mcheck_root = ptr->next;
+}
+
+static void
+link_blk (struct hdr *hdr)
+{
+  hdr->prev = NULL;
+  hdr->next = __mcheck_root;
+  __mcheck_root = hdr;
+  hdr->magic = MAGICWORD ^ (uintptr_t) hdr->next;
+
+  /* And the next block.  */
+  if (hdr->next != NULL)
+    {
+      hdr->next->prev = hdr;
+      hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
+                                      + (uintptr_t) hdr->next->next);
+    }
+}
+
+static void *
+free_mcheck (void *ptr)
+{
+  if (pedantic)
+    __mcheck_checkptr (NULL);
+  if (ptr)
+    {
+      struct hdr *hdr = ((struct hdr *) ptr) - 1;
+      checkhdr (hdr);
+      hdr->magic = MAGICFREE;
+      hdr->magic2 = MAGICFREE;
+      unlink_blk (hdr);
+      hdr->prev = hdr->next = NULL;
+      flood (ptr, FREEFLOOD, hdr->size);
+      ptr = hdr->block;
+    }
+  return ptr;
+}
+
+static bool
+malloc_mcheck_before (size_t *sizep, void **victimp)
+{
+  size_t size = *sizep;
+
+  if (pedantic)
+    __mcheck_checkptr (NULL);
+
+  if (size > ~((size_t) 0) - (sizeof (struct hdr) + 1))
+    {
+      __set_errno (ENOMEM);
+      *victimp = NULL;
+      return true;
+    }
+
+  *sizep = sizeof (struct hdr) + size + 1;
+  return false;
+}
+
+static void *
+malloc_mcheck_after (void *mem, size_t size)
+{
+  struct hdr *hdr = mem;
+
+  if (hdr == NULL)
+    return NULL;
+
+  hdr->size = size;
+  link_blk (hdr);
+  hdr->block = hdr;
+  hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  flood ((void *) (hdr + 1), MALLOCFLOOD, size);
+  return (void *) (hdr + 1);
+}
+
+static bool
+memalign_mcheck_before (size_t alignment, size_t *sizep, void **victimp)
+{
+  struct hdr *hdr;
+  size_t slop, size = *sizep;
+
+  /* Punt to malloc to avoid double headers.  */
+  if (alignment <= MALLOC_ALIGNMENT)
+    {
+      *victimp = __debug_malloc (size);
+      return true;
+    }
+
+  if (pedantic)
+    __mcheck_checkptr (NULL);
+
+  slop = (sizeof *hdr + alignment - 1) & - alignment;
+
+  if (size > ~((size_t) 0) - (slop + 1))
+    {
+      __set_errno (ENOMEM);
+      *victimp = NULL;
+      return true;
+    }
+
+  *sizep = slop + size + 1;
+  return false;
+}
+
+static void *
+memalign_mcheck_after (void *block, size_t alignment, size_t size)
+{
+  if (block == NULL)
+    return NULL;
+
+  /* This was served by __debug_malloc, so return as is.  */
+  if (alignment <= MALLOC_ALIGNMENT)
+    return block;
+
+  size_t slop = (sizeof (struct hdr) + alignment - 1) & - alignment;
+  struct hdr *hdr = ((struct hdr *) (block + slop)) - 1;
+
+  hdr->size = size;
+  link_blk (hdr);
+  hdr->block = (void *) block;
+  hdr->magic2 = (uintptr_t) block ^ MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  flood ((void *) (hdr + 1), MALLOCFLOOD, size);
+  return (void *) (hdr + 1);
+}
+
+static bool
+realloc_mcheck_before (void **ptrp, size_t *sizep, size_t *oldsize,
+		       void **victimp)
+{
+  size_t size = *sizep;
+  void *ptr = *ptrp;
+
+  if (size == 0)
+    {
+      __debug_free (ptr);
+      *victimp = NULL;
+      return true;
+    }
+
+  if (ptr == NULL)
+    {
+      *victimp = __debug_malloc (size);
+      *oldsize = 0;
+      return true;
+    }
+
+  if (size > ~((size_t) 0) - (sizeof (struct hdr) + 1))
+    {
+      __set_errno (ENOMEM);
+      *victimp = NULL;
+      *oldsize = 0;
+      return true;
+    }
+
+  if (pedantic)
+    __mcheck_checkptr (NULL);
+
+  struct hdr *hdr;
+  size_t osize;
+
+  /* Update the oldptr for glibc realloc.  */
+  *ptrp = hdr = ((struct hdr *) ptr) - 1;
+
+  osize = hdr->size;
+
+  checkhdr (hdr);
+  unlink_blk (hdr);
+  if (size < osize)
+    flood ((char *) ptr + size, FREEFLOOD, osize - size);
+
+  *oldsize = osize;
+  *sizep = sizeof (struct hdr) + size + 1;
+  return false;
+}
+
+static void *
+realloc_mcheck_after (void *ptr, void *oldptr, size_t size, size_t osize)
+{
+  struct hdr *hdr = ptr;
+
+  if (hdr == NULL)
+    return NULL;
+
+  /* Malloc already added the header so don't tamper with it.  */
+  if (oldptr == NULL)
+    return ptr;
+
+  hdr->size = size;
+  link_blk (hdr);
+  hdr->block = hdr;
+  hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  if (size > osize)
+    flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
+  return (void *) (hdr + 1);
+}
+
+__attribute__ ((noreturn))
+static void
+mabort (enum mcheck_status status)
+{
+  const char *msg;
+  switch (status)
+    {
+    case MCHECK_OK:
+      msg = _ ("memory is consistent, library is buggy\n");
+      break;
+    case MCHECK_HEAD:
+      msg = _ ("memory clobbered before allocated block\n");
+      break;
+    case MCHECK_TAIL:
+      msg = _ ("memory clobbered past end of allocated block\n");
+      break;
+    case MCHECK_FREE:
+      msg = _ ("block freed twice\n");
+      break;
+    default:
+      msg = _ ("bogus mcheck_status, library is buggy\n");
+      break;
+    }
+#ifdef _LIBC
+  __libc_fatal (msg);
+#else
+  fprintf (stderr, "mcheck: %s", msg);
+  fflush (stderr);
+  abort ();
+#endif
+}
+
+/* Memory barrier so that GCC does not optimize out the argument.  */
+#define malloc_opt_barrier(x) \
+  ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
+
+static int
+__mcheck_initialize (void (*func) (enum mcheck_status), bool in_pedantic)
+{
+  abortfunc = (func != NULL) ? func : &mabort;
+
+  if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
+    goto out;
+
+  /* There was a call to malloc before this initializer was called.  */
+  if (malloc_called)
+    return -1;
+
+  /* We call malloc() once here to ensure it is initialized.  */
+  void *p = malloc (0);
+  /* GCC might optimize out the malloc/free pair without a barrier.  */
+  p = malloc_opt_barrier (p);
+  free (p);
+  /* FALLTHROUGH */
+  __malloc_debug_enable (MALLOC_MCHECK_HOOK);
+
+out:
+  pedantic = in_pedantic;
+  return 0;
+}
diff --git a/malloc/mcheck.c b/malloc/mcheck.c
index b46b9b26bf..74c20ffe25 100644
--- a/malloc/mcheck.c
+++ b/malloc/mcheck.c
@@ -1,4 +1,4 @@
-/* Standard debugging hooks for `malloc'.
+/* The mcheck() interface.
    Copyright (C) 1990-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written May 1989 by Mike Haertel.
@@ -17,401 +17,46 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef _MALLOC_INTERNAL
-# define _MALLOC_INTERNAL
-# include <malloc.h>
-# include <mcheck.h>
-# include <stdint.h>
-# include <stdio.h>
-# include <libintl.h>
-# include <errno.h>
-# include <malloc-internal.h>
-#endif
-
-/* Old hook values.  */
-static void (*old_free_hook)(void *ptr, const void *);
-static void *(*old_malloc_hook) (size_t size, const void *);
-static void *(*old_memalign_hook) (size_t alignment, size_t size,
-				   const void *);
-static void *(*old_realloc_hook) (void *ptr, size_t size,
-				  const void *);
-
-/* Function to call when something awful happens.  */
-static void (*abortfunc) (enum mcheck_status);
-
-/* Arbitrary magical numbers.  */
-#define MAGICWORD       0xfedabeeb
-#define MAGICFREE       0xd8675309
-#define MAGICBYTE       ((char) 0xd7)
-#define MALLOCFLOOD     ((char) 0x93)
-#define FREEFLOOD       ((char) 0x95)
-
-struct hdr
-{
-  size_t size;                  /* Exact size requested by user.  */
-  unsigned long int magic;      /* Magic number to check header integrity.  */
-  struct hdr *prev;
-  struct hdr *next;
-  void *block;                  /* Real block allocated, for memalign.  */
-  unsigned long int magic2;     /* Extra, keeps us doubleword aligned.  */
-};
-
-/* This is the beginning of the list of all memory blocks allocated.
-   It is only constructed if the pedantic testing is requested.  */
-static struct hdr *root;
-
-static int mcheck_used;
-
-/* Nonzero if pedentic checking of all blocks is requested.  */
-static int pedantic;
-
-#if defined _LIBC || defined STDC_HEADERS || defined USG
-# include <string.h>
-# define flood memset
+#if !IS_IN (libc)
+# include "mcheck-impl.c"
 #else
-static void flood (void *, int, size_t);
-static void
-flood (void *ptr, int val, size_t size)
-{
-  char *cp = ptr;
-  while (size--)
-    *cp++ = val;
-}
+# include <mcheck.h>
 #endif
 
-static enum mcheck_status
-checkhdr (const struct hdr *hdr)
-{
-  enum mcheck_status status;
-
-  if (!mcheck_used)
-    /* Maybe the mcheck used is disabled?  This happens when we find
-       an error and report it.  */
-    return MCHECK_OK;
-
-  switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
-    {
-    default:
-      status = MCHECK_HEAD;
-      break;
-    case MAGICFREE:
-      status = MCHECK_FREE;
-      break;
-    case MAGICWORD:
-      if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
-        status = MCHECK_TAIL;
-      else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
-        status = MCHECK_HEAD;
-      else
-        status = MCHECK_OK;
-      break;
-    }
-  if (status != MCHECK_OK)
-    {
-      mcheck_used = 0;
-      (*abortfunc) (status);
-      mcheck_used = 1;
-    }
-  return status;
-}
-
 void
 mcheck_check_all (void)
 {
-  /* Walk through all the active blocks and test whether they were tampered
-     with.  */
-  struct hdr *runp = root;
-
-  /* Temporarily turn off the checks.  */
-  pedantic = 0;
-
-  while (runp != NULL)
-    {
-      (void) checkhdr (runp);
-
-      runp = runp->next;
-    }
-
-  /* Turn checks on again.  */
-  pedantic = 1;
-}
-#ifdef _LIBC
-libc_hidden_def (mcheck_check_all)
+#if !IS_IN (libc)
+  __mcheck_checkptr (NULL);
 #endif
-
-static void
-unlink_blk (struct hdr *ptr)
-{
-  if (ptr->next != NULL)
-    {
-      ptr->next->prev = ptr->prev;
-      ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
-                                      + (uintptr_t) ptr->next->next);
-    }
-  if (ptr->prev != NULL)
-    {
-      ptr->prev->next = ptr->next;
-      ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
-                                      + (uintptr_t) ptr->prev->next);
-    }
-  else
-    root = ptr->next;
-}
-
-static void
-link_blk (struct hdr *hdr)
-{
-  hdr->prev = NULL;
-  hdr->next = root;
-  root = hdr;
-  hdr->magic = MAGICWORD ^ (uintptr_t) hdr->next;
-
-  /* And the next block.  */
-  if (hdr->next != NULL)
-    {
-      hdr->next->prev = hdr;
-      hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
-                                      + (uintptr_t) hdr->next->next);
-    }
 }
-static void
-freehook (void *ptr, const void *caller)
-{
-  if (pedantic)
-    mcheck_check_all ();
-  if (ptr)
-    {
-      struct hdr *hdr = ((struct hdr *) ptr) - 1;
-      checkhdr (hdr);
-      hdr->magic = MAGICFREE;
-      hdr->magic2 = MAGICFREE;
-      unlink_blk (hdr);
-      hdr->prev = hdr->next = NULL;
-      flood (ptr, FREEFLOOD, hdr->size);
-      ptr = hdr->block;
-    }
-  __free_hook = old_free_hook;
-  if (old_free_hook != NULL)
-    (*old_free_hook)(ptr, caller);
-  else
-    free (ptr);
-  __free_hook = freehook;
-}
-
-static void *
-mallochook (size_t size, const void *caller)
-{
-  struct hdr *hdr;
-
-  if (pedantic)
-    mcheck_check_all ();
-
-  if (size > ~((size_t) 0) - (sizeof (struct hdr) + 1))
-    {
-      __set_errno (ENOMEM);
-      return NULL;
-    }
-
-  __malloc_hook = old_malloc_hook;
-  if (old_malloc_hook != NULL)
-    hdr = (struct hdr *) (*old_malloc_hook)(sizeof (struct hdr) + size + 1,
-                                            caller);
-  else
-    hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
-  __malloc_hook = mallochook;
-  if (hdr == NULL)
-    return NULL;
-
-  hdr->size = size;
-  link_blk (hdr);
-  hdr->block = hdr;
-  hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
-  ((char *) &hdr[1])[size] = MAGICBYTE;
-  flood ((void *) (hdr + 1), MALLOCFLOOD, size);
-  return (void *) (hdr + 1);
-}
-
-static void *
-memalignhook (size_t alignment, size_t size,
-              const void *caller)
-{
-  struct hdr *hdr;
-  size_t slop;
-  char *block;
-
-  if (pedantic)
-    mcheck_check_all ();
-
-  slop = (sizeof *hdr + alignment - 1) & - alignment;
-
-  if (size > ~((size_t) 0) - (slop + 1))
-    {
-      __set_errno (ENOMEM);
-      return NULL;
-    }
-
-  __memalign_hook = old_memalign_hook;
-  if (old_memalign_hook != NULL)
-    block = (*old_memalign_hook)(alignment, slop + size + 1, caller);
-  else
-    block = memalign (alignment, slop + size + 1);
-  __memalign_hook = memalignhook;
-  if (block == NULL)
-    return NULL;
-
-  hdr = ((struct hdr *) (block + slop)) - 1;
-
-  hdr->size = size;
-  link_blk (hdr);
-  hdr->block = (void *) block;
-  hdr->magic2 = (uintptr_t) block ^ MAGICWORD;
-  ((char *) &hdr[1])[size] = MAGICBYTE;
-  flood ((void *) (hdr + 1), MALLOCFLOOD, size);
-  return (void *) (hdr + 1);
-}
-
-static void *
-reallochook (void *ptr, size_t size, const void *caller)
-{
-  if (size == 0)
-    {
-      freehook (ptr, caller);
-      return NULL;
-    }
-
-  struct hdr *hdr;
-  size_t osize;
-
-  if (pedantic)
-    mcheck_check_all ();
-
-  if (size > ~((size_t) 0) - (sizeof (struct hdr) + 1))
-    {
-      __set_errno (ENOMEM);
-      return NULL;
-    }
-
-  if (ptr)
-    {
-      hdr = ((struct hdr *) ptr) - 1;
-      osize = hdr->size;
-
-      checkhdr (hdr);
-      unlink_blk (hdr);
-      if (size < osize)
-        flood ((char *) ptr + size, FREEFLOOD, osize - size);
-    }
-  else
-    {
-      osize = 0;
-      hdr = NULL;
-    }
-  __free_hook = old_free_hook;
-  __malloc_hook = old_malloc_hook;
-  __memalign_hook = old_memalign_hook;
-  __realloc_hook = old_realloc_hook;
-  if (old_realloc_hook != NULL)
-    hdr = (struct hdr *) (*old_realloc_hook)((void *) hdr,
-                                             sizeof (struct hdr) + size + 1,
-                                             caller);
-  else
-    hdr = (struct hdr *) realloc ((void *) hdr,
-                                  sizeof (struct hdr) + size + 1);
-  __free_hook = freehook;
-  __malloc_hook = mallochook;
-  __memalign_hook = memalignhook;
-  __realloc_hook = reallochook;
-  if (hdr == NULL)
-    return NULL;
-
-  hdr->size = size;
-  link_blk (hdr);
-  hdr->block = hdr;
-  hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
-  ((char *) &hdr[1])[size] = MAGICBYTE;
-  if (size > osize)
-    flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
-  return (void *) (hdr + 1);
-}
-
-__attribute__ ((noreturn))
-static void
-mabort (enum mcheck_status status)
-{
-  const char *msg;
-  switch (status)
-    {
-    case MCHECK_OK:
-      msg = _ ("memory is consistent, library is buggy\n");
-      break;
-    case MCHECK_HEAD:
-      msg = _ ("memory clobbered before allocated block\n");
-      break;
-    case MCHECK_TAIL:
-      msg = _ ("memory clobbered past end of allocated block\n");
-      break;
-    case MCHECK_FREE:
-      msg = _ ("block freed twice\n");
-      break;
-    default:
-      msg = _ ("bogus mcheck_status, library is buggy\n");
-      break;
-    }
-#ifdef _LIBC
-  __libc_fatal (msg);
-#else
-  fprintf (stderr, "mcheck: %s", msg);
-  fflush (stderr);
-  abort ();
-#endif
-}
-
-/* Memory barrier so that GCC does not optimize out the argument.  */
-#define malloc_opt_barrier(x) \
-  ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
 
 int
 mcheck (void (*func) (enum mcheck_status))
 {
-  abortfunc = (func != NULL) ? func : &mabort;
-
-  /* These hooks may not be safely inserted if malloc is already in use.  */
-  if (__malloc_initialized <= 0 && !mcheck_used)
-    {
-      /* We call malloc() once here to ensure it is initialized.  */
-      void *p = malloc (0);
-      /* GCC might optimize out the malloc/free pair without a barrier.  */
-      p = malloc_opt_barrier (p);
-      free (p);
-
-      old_free_hook = __free_hook;
-      __free_hook = freehook;
-      old_malloc_hook = __malloc_hook;
-      __malloc_hook = mallochook;
-      old_memalign_hook = __memalign_hook;
-      __memalign_hook = memalignhook;
-      old_realloc_hook = __realloc_hook;
-      __realloc_hook = reallochook;
-      mcheck_used = 1;
-    }
-
-  return mcheck_used ? 0 : -1;
-}
-#ifdef _LIBC
-libc_hidden_def (mcheck)
+#if IS_IN (libc)
+  return -1;
+#else
+  return __mcheck_initialize (func, false);
 #endif
+}
 
 int
 mcheck_pedantic (void (*func) (enum mcheck_status))
 {
-  int res = mcheck (func);
-  if (res == 0)
-    pedantic = 1;
-  return res;
+#if IS_IN (libc)
+  return -1;
+#else
+  return __mcheck_initialize (func, true);
+#endif
 }
 
 enum mcheck_status
 mprobe (void *ptr)
 {
-  return mcheck_used ? checkhdr (((struct hdr *) ptr) - 1) : MCHECK_DISABLED;
+#if IS_IN (libc)
+  return MCHECK_DISABLED;
+#else
+  return __mcheck_checkptr (ptr);
+#endif
 }
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 3/8] Simplify __malloc_initialized
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 1/8] Move malloc hooks into a compat DSO Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 2/8] mcheck: Wean away from malloc hooks Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 4/8] mtrace: Wean away from malloc hooks Siddhesh Poyarekar
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

Now that mcheck no longer needs to check __malloc_initialized (and no
other third party hook can since the symbol is not exported), make the
variable boolean and static so that it is used strictly within malloc.
---
 include/malloc.h |  6 ------
 malloc/arena.c   | 12 ++++++------
 malloc/malloc.c  | 24 ++++++++++++------------
 3 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/include/malloc.h b/include/malloc.h
index b77761f74d..f9c9610548 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -5,12 +5,6 @@
 # ifndef _ISOMAC
 #  include <rtld-malloc.h>
 
-/* In the GNU libc we rename the global variable
-   `__malloc_initialized' to `__libc_malloc_initialized'.  */
-#define __malloc_initialized __libc_malloc_initialized
-/* Nonzero if the malloc is already initialized.  */
-extern int __malloc_initialized attribute_hidden;
-
 struct malloc_state;
 typedef struct malloc_state *mstate;
 
diff --git a/malloc/arena.c b/malloc/arena.c
index 8f890d5ff0..cae3387db0 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -97,7 +97,7 @@ static mstate free_list;
 __libc_lock_define_initialized (static, list_lock);
 
 /* Already initialized? */
-int __malloc_initialized = -1;
+static bool __malloc_initialized = false;
 
 /**************************************************************************/
 
@@ -143,7 +143,7 @@ int __malloc_initialized = -1;
 void
 __malloc_fork_lock_parent (void)
 {
-  if (__malloc_initialized < 1)
+  if (!__malloc_initialized)
     return;
 
   /* We do not acquire free_list_lock here because we completely
@@ -163,7 +163,7 @@ __malloc_fork_lock_parent (void)
 void
 __malloc_fork_unlock_parent (void)
 {
-  if (__malloc_initialized < 1)
+  if (!__malloc_initialized)
     return;
 
   for (mstate ar_ptr = &main_arena;; )
@@ -179,7 +179,7 @@ __malloc_fork_unlock_parent (void)
 void
 __malloc_fork_unlock_child (void)
 {
-  if (__malloc_initialized < 1)
+  if (!__malloc_initialized)
     return;
 
   /* Push all arenas to the free list, except thread_arena, which is
@@ -290,10 +290,10 @@ libc_hidden_proto (_dl_open_hook);
 static void
 ptmalloc_init (void)
 {
-  if (__malloc_initialized >= 0)
+  if (__malloc_initialized)
     return;
 
-  __malloc_initialized = 0;
+  __malloc_initialized = true;
 
 #ifdef USE_MTAG
   if ((TUNABLE_GET_FULL (glibc, mem, tagging, int32_t, NULL) & 1) != 0)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index d2e45664b1..595dd8bbdb 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3195,7 +3195,7 @@ __libc_malloc (size_t bytes)
   _Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
                   "PTRDIFF_MAX is not more than half of SIZE_MAX");
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 #if USE_TCACHE
   /* int_free also calls request2size, be careful to not pad twice.  */
@@ -3308,7 +3308,7 @@ __libc_realloc (void *oldmem, size_t bytes)
 
   void *newp;             /* chunk to return */
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
 #if REALLOC_ZERO_BYTES_FREES
@@ -3444,7 +3444,7 @@ libc_hidden_def (__libc_realloc)
 void *
 __libc_memalign (size_t alignment, size_t bytes)
 {
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   void *address = RETURN_ADDRESS (0);
@@ -3515,7 +3515,7 @@ libc_hidden_def (__libc_memalign)
 void *
 __libc_valloc (size_t bytes)
 {
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   void *address = RETURN_ADDRESS (0);
@@ -3526,7 +3526,7 @@ __libc_valloc (size_t bytes)
 void *
 __libc_pvalloc (size_t bytes)
 {
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   void *address = RETURN_ADDRESS (0);
@@ -3565,7 +3565,7 @@ __libc_calloc (size_t n, size_t elem_size)
 
   sz = bytes;
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   MAYBE_INIT_TCACHE ();
@@ -5022,7 +5022,7 @@ __malloc_trim (size_t s)
 {
   int result = 0;
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   mstate ar_ptr = &main_arena;
@@ -5157,7 +5157,7 @@ __libc_mallinfo2 (void)
   struct mallinfo2 m;
   mstate ar_ptr;
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   memset (&m, 0, sizeof (m));
@@ -5208,7 +5208,7 @@ __malloc_stats (void)
   mstate ar_ptr;
   unsigned int in_use_b = mp_.mmapped_mem, system_b = in_use_b;
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
   _IO_flockfile (stderr);
   int old_flags2 = stderr->_flags2;
@@ -5377,7 +5377,7 @@ __libc_mallopt (int param_number, int value)
   mstate av = &main_arena;
   int res = 1;
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
   __libc_lock_lock (av->mutex);
 
@@ -5595,7 +5595,7 @@ __posix_memalign (void **memptr, size_t alignment, size_t size)
 {
   void *mem;
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   /* Test whether the SIZE argument is valid.  It must be a power of
@@ -5639,7 +5639,7 @@ __malloc_info (int options, FILE *fp)
 
 
 
-  if (__malloc_initialized < 0)
+  if (!__malloc_initialized)
     ptmalloc_init ();
 
   fputs ("<malloc version=\"1\">\n", fp);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 4/8] mtrace: Wean away from malloc hooks
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
                   ` (2 preceding siblings ...)
  2021-07-05 17:08 ` [PATCH v5 3/8] Simplify __malloc_initialized Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 5/8] glibc.malloc.check: " Siddhesh Poyarekar
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

Wean mtrace away from the malloc hooks and move them into the debug
DSO.  Split the API away from the implementation so that we can add
the API to libc.so as well as libc_malloc_debug.so, with the libc
implementations being empty.
---
 malloc/malloc-debug.c |  13 ++
 malloc/mtrace-impl.c  | 224 ++++++++++++++++++++++++++++++
 malloc/mtrace.c       | 314 ++----------------------------------------
 3 files changed, 249 insertions(+), 302 deletions(-)
 create mode 100644 malloc/mtrace-impl.c

diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c
index daf48e0633..e810d47107 100644
--- a/malloc/malloc-debug.c
+++ b/malloc/malloc-debug.c
@@ -49,6 +49,7 @@ enum malloc_debug_hooks
 {
   MALLOC_NONE_HOOK = 0,
   MALLOC_MCHECK_HOOK = 1 << 0, /* mcheck()  */
+  MALLOC_MTRACE_HOOK = 1 << 1, /* mtrace()  */
 };
 static unsigned __malloc_debugging_hooks;
 
@@ -71,6 +72,7 @@ __malloc_debug_disable (enum malloc_debug_hooks flag)
 }
 
 #include "mcheck.c"
+#include "mtrace.c"
 
 extern void (*__free_hook) (void *, const void *);
 compat_symbol_reference (libc, __free_hook, __free_hook, GLIBC_2_0);
@@ -103,6 +105,8 @@ __debug_malloc (size_t bytes)
     }
   if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
     victim = malloc_mcheck_after (victim, orig_bytes);
+  if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+    malloc_mtrace_after (victim, orig_bytes, RETURN_ADDRESS (0));
 
   return victim;
 }
@@ -120,6 +124,8 @@ __debug_free (void *mem)
 
   if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
     mem = free_mcheck (mem);
+  if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+    free_mtrace (mem, RETURN_ADDRESS (0));
 
   __libc_free (mem);
 }
@@ -146,6 +152,8 @@ __debug_realloc (void *oldmem, size_t bytes)
   if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
     victim = realloc_mcheck_after (victim, oldmem, orig_bytes,
 				   oldsize);
+  if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+    realloc_mtrace_after (victim, oldmem, orig_bytes, RETURN_ADDRESS (0));
 
   return victim;
 }
@@ -171,6 +179,8 @@ _mid_memalign (size_t alignment, size_t bytes, const void *address)
     }
   if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
     victim = memalign_mcheck_after (victim, alignment, orig_bytes);
+  if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+    memalign_mtrace_after (victim, orig_bytes, address);
 
   return victim;
 }
@@ -272,6 +282,9 @@ __debug_calloc (size_t nmemb, size_t size)
 	victim = malloc_mcheck_after (victim, orig_bytes);
       memset (victim, 0, orig_bytes);
     }
+  if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+    malloc_mtrace_after (victim, orig_bytes, RETURN_ADDRESS (0));
+
   return victim;
 }
 strong_alias (__debug_calloc, calloc)
diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c
new file mode 100644
index 0000000000..de8e88e4f7
--- /dev/null
+++ b/malloc/mtrace-impl.c
@@ -0,0 +1,224 @@
+/* mtrace implementation for `malloc'.
+   Copyright (C) 1991-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+                 Written April 2, 1991 by John Gilmore of Cygnus Support.
+                 Based on mcheck.c by Mike Haertel.
+
+   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 <malloc.h>
+#include <mcheck.h>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <libc-internal.h>
+#include <dso_handle.h>
+
+#include <kernel-features.h>
+
+#define TRACE_BUFFER_SIZE 512
+
+static FILE *mallstream;
+static const char mallenv[] = "MALLOC_TRACE";
+static char *malloc_trace_buffer;
+
+static void
+tr_where (const void *caller, Dl_info *info)
+{
+  if (caller != NULL)
+    {
+      if (info != NULL)
+        {
+          char *buf = (char *) "";
+          if (info->dli_sname != NULL)
+            {
+              size_t len = strlen (info->dli_sname);
+              buf = alloca (len + 6 + 2 * sizeof (void *));
+	      char sign;
+	      ptrdiff_t offset =
+		(ptrdiff_t) info->dli_saddr - (ptrdiff_t) caller;
+
+	      if (caller >= (const void *) info->dli_saddr)
+		{
+		  sign = '+';
+		  offset = -offset;
+		}
+	      else
+		  sign = '-';
+
+	      sprintf (buf, "(%s%c%lx)", info->dli_sname, sign, offset);
+            }
+
+	  fprintf (mallstream, "@ %s%s%s[%p] ", info->dli_fname ? : "",
+		   info->dli_fname ? ":" : "",
+                   buf, caller);
+        }
+      else
+        fprintf (mallstream, "@ [%p] ", caller);
+    }
+}
+
+static Dl_info *
+lock_and_info (const void *caller, Dl_info *mem)
+{
+  if (caller == NULL)
+    return NULL;
+
+  Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL;
+
+  flockfile (mallstream);
+
+  return res;
+}
+
+static void
+free_mtrace (void *ptr, const void *caller)
+{
+  if (ptr == NULL)
+    return;
+
+  Dl_info mem;
+  Dl_info *info = lock_and_info (caller, &mem);
+  tr_where (caller, info);
+  /* Be sure to print it first.  */
+  fprintf (mallstream, "- %p\n", ptr);
+  funlockfile (mallstream);
+}
+
+static void
+malloc_mtrace_after (void *block, size_t size, const void *caller)
+{
+  Dl_info mem;
+  Dl_info *info = lock_and_info (caller, &mem);
+
+  tr_where (caller, info);
+  /* We could be printing a NULL here; that's OK.  */
+  fprintf (mallstream, "+ %p %#lx\n", block, (unsigned long int) size);
+
+  funlockfile (mallstream);
+}
+
+static void
+realloc_mtrace_after (void *block, const void *oldptr, size_t size,
+		      const void *caller)
+{
+  Dl_info mem;
+  Dl_info *info = lock_and_info (caller, &mem);
+
+  tr_where (caller, info);
+  if (block == NULL)
+    {
+      if (size != 0)
+        /* Failed realloc.  */
+	fprintf (mallstream, "! %p %#lx\n", oldptr, (unsigned long int) size);
+      else
+        fprintf (mallstream, "- %p\n", oldptr);
+    }
+  else if (oldptr == NULL)
+    fprintf (mallstream, "+ %p %#lx\n", block, (unsigned long int) size);
+  else
+    {
+      fprintf (mallstream, "< %p\n", oldptr);
+      tr_where (caller, info);
+      fprintf (mallstream, "> %p %#lx\n", block, (unsigned long int) size);
+    }
+
+  funlockfile (mallstream);
+}
+
+static void
+memalign_mtrace_after (void *block, size_t size, const void *caller)
+{
+  Dl_info mem;
+  Dl_info *info = lock_and_info (caller, &mem);
+
+  tr_where (caller, info);
+  /* We could be printing a NULL here; that's OK.  */
+  fprintf (mallstream, "+ %p %#lx\n", block, (unsigned long int) size);
+
+  funlockfile (mallstream);
+}
+
+/* This function gets called to make sure all memory the library
+   allocates get freed and so does not irritate the user when studying
+   the mtrace output.  */
+static void
+release_libc_mem (void)
+{
+  /* Only call the free function if we still are running in mtrace mode.  */
+  if (mallstream != NULL)
+    __libc_freeres ();
+}
+
+/* We enable tracing if the environment variable MALLOC_TRACE is set.  */
+
+static void
+do_mtrace (void)
+{
+  static int added_atexit_handler;
+  char *mallfile;
+
+  /* Don't panic if we're called more than once.  */
+  if (mallstream != NULL)
+    return;
+
+  mallfile = secure_getenv (mallenv);
+  if (mallfile != NULL)
+    {
+      char *mtb = malloc (TRACE_BUFFER_SIZE);
+      if (mtb == NULL)
+        return;
+
+      mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
+      if (mallstream != NULL)
+        {
+          /* Be sure it doesn't malloc its buffer!  */
+          malloc_trace_buffer = mtb;
+          setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
+          fprintf (mallstream, "= Start\n");
+          if (!added_atexit_handler)
+            {
+              added_atexit_handler = 1;
+              __cxa_atexit ((void (*)(void *))release_libc_mem, NULL,
+			    __dso_handle);
+            }
+	  __malloc_debug_enable (MALLOC_MTRACE_HOOK);
+        }
+      else
+        free (mtb);
+    }
+}
+
+static void
+do_muntrace (void)
+{
+  __malloc_debug_disable (MALLOC_MTRACE_HOOK);
+  if (mallstream == NULL)
+    return;
+
+  /* Do the reverse of what done in mtrace: first reset the hooks and
+     MALLSTREAM, and only after that write the trailer and close the
+     file.  */
+  FILE *f = mallstream;
+  mallstream = NULL;
+
+  fprintf (f, "= End\n");
+  fclose (f);
+}
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
index 274db3fb47..b632116dd1 100644
--- a/malloc/mtrace.c
+++ b/malloc/mtrace.c
@@ -1,4 +1,4 @@
-/* More debugging hooks for `malloc'.
+/* mtrace API for `malloc'.
    Copyright (C) 1991-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
                  Written April 2, 1991 by John Gilmore of Cygnus Support.
@@ -18,40 +18,14 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef _MALLOC_INTERNAL
-# define _MALLOC_INTERNAL
-# include <malloc.h>
-# include <mcheck.h>
-# include <malloc-internal.h>
-# include <libc-lock.h>
+#if !IS_IN (libc)
+# include "mtrace-impl.c"
+#else
+# include <shlib-compat.h>
+# include <libc-symbols.h>
 #endif
 
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <_itoa.h>
-
-#include <libc-internal.h>
-#include <dso_handle.h>
-
-#include <libio/iolibio.h>
-#define setvbuf(s, b, f, l) _IO_setvbuf (s, b, f, l)
-#define fwrite(buf, size, count, fp) _IO_fwrite (buf, size, count, fp)
-
-#include <kernel-features.h>
-
-#define TRACE_BUFFER_SIZE 512
-
-static FILE *mallstream;
-static const char mallenv[] = "MALLOC_TRACE";
-static char *malloc_trace_buffer;
-
-__libc_lock_define_initialized (static, lock);
-
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
+#if IS_IN (libc) && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
 /* Compatibility symbols that were introduced to help break at allocation sites
    for specific memory allocations.  This is unusable with ASLR, although gdb
    may allow predictable allocation addresses.  Even then, gdb has watchpoint
@@ -71,282 +45,18 @@ compat_symbol (libc, tr_break, tr_break, GLIBC_2_0);
 #endif
 
 
-/* Old hook values.  */
-static void (*tr_old_free_hook) (void *ptr, const void *);
-static void *(*tr_old_malloc_hook) (size_t size, const void *);
-static void *(*tr_old_realloc_hook) (void *ptr, size_t size,
-				     const void *);
-static void *(*tr_old_memalign_hook) (size_t __alignment, size_t __size,
-				      const void *);
-
-static void
-tr_where (const void *caller, Dl_info *info)
-{
-  if (caller != NULL)
-    {
-      if (info != NULL)
-        {
-          char *buf = (char *) "";
-          if (info->dli_sname != NULL)
-            {
-              size_t len = strlen (info->dli_sname);
-              buf = alloca (len + 6 + 2 * sizeof (void *));
-
-              buf[0] = '(';
-              __stpcpy (_fitoa (caller >= (const void *) info->dli_saddr
-                                ? caller - (const void *) info->dli_saddr
-                                : (const void *) info->dli_saddr - caller,
-                                __stpcpy (__mempcpy (buf + 1, info->dli_sname,
-                                                     len),
-                                          caller >= (void *) info->dli_saddr
-                                          ? "+0x" : "-0x"),
-                                16, 0),
-                        ")");
-            }
-
-          fprintf (mallstream, "@ %s%s%s[%p] ",
-                   info->dli_fname ? : "", info->dli_fname ? ":" : "",
-                   buf, caller);
-        }
-      else
-        fprintf (mallstream, "@ [%p] ", caller);
-    }
-}
-
-static Dl_info *
-lock_and_info (const void *caller, Dl_info *mem)
-{
-  if (caller == NULL)
-    return NULL;
-
-  Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL;
-
-  __libc_lock_lock (lock);
-
-  return res;
-}
-
-static void tr_freehook (void *, const void *);
-static void * tr_mallochook (size_t, const void *);
-static void * tr_reallochook (void *, size_t, const void *);
-static void * tr_memalignhook (size_t, size_t, const void *);
-
-/* Set all the default non-trace hooks.  */
-static __always_inline void
-set_default_hooks (void)
-{
-  __free_hook = tr_old_free_hook;
-  __malloc_hook = tr_old_malloc_hook;
-  __realloc_hook = tr_old_realloc_hook;
-  __memalign_hook = tr_old_memalign_hook;
-}
-
-/* Set all of the tracing hooks used for mtrace.  */
-static __always_inline void
-set_trace_hooks (void)
-{
-  __free_hook = tr_freehook;
-  __malloc_hook = tr_mallochook;
-  __realloc_hook = tr_reallochook;
-  __memalign_hook = tr_memalignhook;
-}
-
-/* Save the current set of hooks as the default hooks.  */
-static __always_inline void
-save_default_hooks (void)
-{
-  tr_old_free_hook = __free_hook;
-  tr_old_malloc_hook = __malloc_hook;
-  tr_old_realloc_hook = __realloc_hook;
-  tr_old_memalign_hook = __memalign_hook;
-}
-
-static void
-tr_freehook (void *ptr, const void *caller)
-{
-  if (ptr == NULL)
-    return;
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-  tr_where (caller, info);
-  /* Be sure to print it first.  */
-  fprintf (mallstream, "- %p\n", ptr);
-  set_default_hooks ();
-  if (tr_old_free_hook != NULL)
-    (*tr_old_free_hook)(ptr, caller);
-  else
-    free (ptr);
-  set_trace_hooks ();
-  __libc_lock_unlock (lock);
-}
-
-static void *
-tr_mallochook (size_t size, const void *caller)
-{
-  void *hdr;
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-
-  set_default_hooks ();
-  if (tr_old_malloc_hook != NULL)
-    hdr = (void *) (*tr_old_malloc_hook)(size, caller);
-  else
-    hdr = (void *) malloc (size);
-  set_trace_hooks ();
-
-  tr_where (caller, info);
-  /* We could be printing a NULL here; that's OK.  */
-  fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-
-  __libc_lock_unlock (lock);
-
-  return hdr;
-}
-
-static void *
-tr_reallochook (void *ptr, size_t size, const void *caller)
-{
-  void *hdr;
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-
-  set_default_hooks ();
-  if (tr_old_realloc_hook != NULL)
-    hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
-  else
-    hdr = (void *) realloc (ptr, size);
-  set_trace_hooks ();
-
-  tr_where (caller, info);
-  if (hdr == NULL)
-    {
-      if (size != 0)
-        /* Failed realloc.  */
-        fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
-      else
-        fprintf (mallstream, "- %p\n", ptr);
-    }
-  else if (ptr == NULL)
-    fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-  else
-    {
-      fprintf (mallstream, "< %p\n", ptr);
-      tr_where (caller, info);
-      fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size);
-    }
-
-  __libc_lock_unlock (lock);
-
-  return hdr;
-}
-
-static void *
-tr_memalignhook (size_t alignment, size_t size, const void *caller)
-{
-  void *hdr;
-
-  Dl_info mem;
-  Dl_info *info = lock_and_info (caller, &mem);
-
-  set_default_hooks ();
-  if (tr_old_memalign_hook != NULL)
-    hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
-  else
-    hdr = (void *) memalign (alignment, size);
-  set_trace_hooks ();
-
-  tr_where (caller, info);
-  /* We could be printing a NULL here; that's OK.  */
-  fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-
-  __libc_lock_unlock (lock);
-
-  return hdr;
-}
-
-
-#ifdef _LIBC
-
-/* This function gets called to make sure all memory the library
-   allocates get freed and so does not irritate the user when studying
-   the mtrace output.  */
-static void __libc_freeres_fn_section
-release_libc_mem (void)
-{
-  /* Only call the free function if we still are running in mtrace mode.  */
-  if (mallstream != NULL)
-    __libc_freeres ();
-}
-#endif
-
-
-/* We enable tracing if the environment variable MALLOC_TRACE is set.  */
-
 void
 mtrace (void)
 {
-#ifdef _LIBC
-  static int added_atexit_handler;
+#if !IS_IN (libc)
+  do_mtrace ();
 #endif
-  char *mallfile;
-
-  /* Don't panic if we're called more than once.  */
-  if (mallstream != NULL)
-    return;
-
-#ifdef _LIBC
-  /* When compiling the GNU libc we use the secure getenv function
-     which prevents the misuse in case of SUID or SGID enabled
-     programs.  */
-  mallfile = __libc_secure_getenv (mallenv);
-#else
-  mallfile = getenv (mallenv);
-#endif
-  if (mallfile != NULL)
-    {
-      char *mtb = malloc (TRACE_BUFFER_SIZE);
-      if (mtb == NULL)
-        return;
-
-      mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
-      if (mallstream != NULL)
-        {
-          /* Be sure it doesn't malloc its buffer!  */
-          malloc_trace_buffer = mtb;
-          setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
-          fprintf (mallstream, "= Start\n");
-	  save_default_hooks ();
-	  set_trace_hooks ();
-#ifdef _LIBC
-          if (!added_atexit_handler)
-            {
-              added_atexit_handler = 1;
-              __cxa_atexit ((void (*)(void *))release_libc_mem, NULL,
-			    __dso_handle);
-            }
-#endif
-        }
-      else
-        free (mtb);
-    }
 }
 
 void
 muntrace (void)
 {
-  if (mallstream == NULL)
-    return;
-
-  /* Do the reverse of what done in mtrace: first reset the hooks and
-     MALLSTREAM, and only after that write the trailer and close the
-     file.  */
-  FILE *f = mallstream;
-  mallstream = NULL;
-  set_default_hooks ();
-
-  fprintf (f, "= End\n");
-  fclose (f);
+#if !IS_IN (libc)
+  do_muntrace ();
+#endif
 }
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 5/8] glibc.malloc.check: Wean away from malloc hooks
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
                   ` (3 preceding siblings ...)
  2021-07-05 17:08 ` [PATCH v5 4/8] mtrace: Wean away from malloc hooks Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 6/8] Remove " Siddhesh Poyarekar
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

The malloc-check debugging feature is tightly integrated into glibc
malloc because of which the implementation needs to stay in libc.so
for now.  The flags to control its execution however has been moved to
libc_malloc_debug.so so that it is called only when the library is
preloaded.  To achieve this, the checking functions have been exported
into the GLIBC_PRIVATE namespace to allow libc_malloc_debug.so to call
it.

Further, a special totem variable __malloc_debug_totem@GLIBC_PRIVATE
is set in libc malloc initialization, which is a hint to
libc_malloc_debug.so that it is running with a compatible DSO.  This
is necessary to skip malloc check tests with older glibc, which
inadvertently happens as the LD_PRELOAD environment variable sometimes
needs through pass through multiple programs, e.g. with testrun.sh.

A long term solution here would be to tweeze malloc-check away from
the core malloc so that it can be embedded into libc_malloc_debug.so.
---
 malloc/Versions       |  9 +++++
 malloc/arena.c        | 11 ------
 malloc/hooks.c        | 10 ++++-
 malloc/malloc-check.c | 86 ++++++++++++++++++++++++-------------------
 malloc/malloc-check.h | 32 ++++++++++++++++
 malloc/malloc-debug.c | 84 +++++++++++++++++++++++++++++++++++-------
 malloc/malloc.c       | 10 -----
 7 files changed, 168 insertions(+), 74 deletions(-)
 create mode 100644 malloc/malloc-check.h

diff --git a/malloc/Versions b/malloc/Versions
index 62e4698a08..5e84bd5d05 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -96,5 +96,14 @@ libc {
     __libc_alloc_buffer_copy_bytes;
     __libc_alloc_buffer_copy_string;
     __libc_alloc_buffer_create_failure;
+
+    # Malloc debugging support
+    __malloc_debug_totem;
+    __malloc_check_malloc_usable_size;
+    __malloc_check_free;
+    __malloc_check_malloc;
+    __malloc_check_realloc;
+    __malloc_check_memalign;
+    __malloc_usable_size;
   }
 }
diff --git a/malloc/arena.c b/malloc/arena.c
index cae3387db0..1ae57f43d5 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -207,14 +207,6 @@ __malloc_fork_unlock_child (void)
 }
 
 #if HAVE_TUNABLES
-static void
-TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp)
-{
-  int32_t value = (int32_t) valp->numval;
-  if (value != 0)
-    __malloc_check_init ();
-}
-
 # define TUNABLE_CALLBACK_FNDECL(__name, __type) \
 static inline int do_ ## __name (__type value);				      \
 static void									      \
@@ -323,7 +315,6 @@ ptmalloc_init (void)
   malloc_init_state (&main_arena);
 
 #if HAVE_TUNABLES
-  TUNABLE_GET (check, int32_t, TUNABLE_CALLBACK (set_mallopt_check));
   TUNABLE_GET (top_pad, size_t, TUNABLE_CALLBACK (set_top_pad));
   TUNABLE_GET (perturb, int32_t, TUNABLE_CALLBACK (set_perturb_byte));
   TUNABLE_GET (mmap_threshold, size_t, TUNABLE_CALLBACK (set_mmap_threshold));
@@ -401,8 +392,6 @@ ptmalloc_init (void)
             }
         }
     }
-  if (s && s[0] != '\0' && s[0] != '0')
-    __malloc_check_init ();
 #endif
 }
 
diff --git a/malloc/hooks.c b/malloc/hooks.c
index d924e35e6f..a9aebdd057 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -35,6 +35,11 @@ void *weak_variable (*__realloc_hook)
 void *weak_variable (*__memalign_hook)
   (size_t, size_t, const void *) = memalign_hook_ini;
 
+/* This is interposed by libc_malloc_debug.so to match with a compatible libc.
+   We don't use dlsym or equivalent because the dlsym symbol version got bumped
+   in 2.34 and is hence unusable in libc_malloc_debug.so.  */
+unsigned __malloc_debug_totem = 0;
+
 /* Hooks for debugging versions.  The initial hooks just call the
    initialization routine, then do the normal work. */
 
@@ -59,6 +64,7 @@ generic_hook_ini (void)
   if (hook != NULL)
     (*hook)();
 #endif
+  __malloc_debug_totem = 1;
 }
 
 static void *
@@ -82,6 +88,8 @@ memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
   return memalign (alignment, sz);
 }
 
+static bool force_malloc_check_off = false;
+
 #include "malloc-check.c"
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_25)
@@ -156,7 +164,7 @@ malloc_set_state (void *msptr)
   __realloc_hook = NULL;
   __free_hook = NULL;
   __memalign_hook = NULL;
-  using_malloc_checking = 0;
+  force_malloc_check_off = true;
 
   /* Patch the dumped heap.  We no longer try to integrate into the
      existing heap.  Instead, we mark the existing chunks as mmapped.
diff --git a/malloc/malloc-check.c b/malloc/malloc-check.c
index dcab880510..54d77fb926 100644
--- a/malloc/malloc-check.c
+++ b/malloc/malloc-check.c
@@ -18,20 +18,6 @@
    not, see <https://www.gnu.org/licenses/>.  */
 
 
-/* Whether we are using malloc checking.  */
-static int using_malloc_checking;
-
-/* Activate a standard set of debugging hooks. */
-void
-__malloc_check_init (void)
-{
-  using_malloc_checking = 1;
-  __malloc_hook = malloc_check;
-  __free_hook = free_check;
-  __realloc_hook = realloc_check;
-  __memalign_hook = memalign_check;
-}
-
 /* When memory is tagged, the checking data is stored in the user part
    of the chunk.  We can't rely on the user not having modified the
    tags, so fetch the tag at each location before dereferencing
@@ -62,15 +48,14 @@ magicbyte (const void *p)
    memory.  Our magic byte is right at the end of the requested size, so we
    must reach it with this iteration, otherwise we have witnessed a memory
    corruption.  */
-static size_t
-malloc_check_get_size (mchunkptr p)
+size_t
+__malloc_check_malloc_usable_size (void *mem)
 {
   size_t size;
   unsigned char c;
+  mchunkptr p = mem2chunk (mem);
   unsigned char magic = magicbyte (p);
 
-  assert (using_malloc_checking == 1);
-
   for (size = CHUNK_HDR_SZ + memsize (p) - 1;
        (c = *SAFE_CHAR_OFFSET (p, size)) != magic;
        size -= c)
@@ -202,32 +187,42 @@ top_check (void)
   malloc_printerr ("malloc: top chunk is corrupt");
 }
 
-static void *
-malloc_check (size_t sz, const void *caller)
+static bool
+malloc_check (size_t sz, void **victimp)
 {
   void *victim;
   size_t nb;
 
+  if (force_malloc_check_off)
+    return false;
+
   if (__builtin_add_overflow (sz, 1, &nb))
     {
       __set_errno (ENOMEM);
-      return NULL;
+      *victimp = NULL;
+      return true;
     }
 
   __libc_lock_lock (main_arena.mutex);
   top_check ();
   victim = _int_malloc (&main_arena, nb);
   __libc_lock_unlock (main_arena.mutex);
-  return mem2mem_check (tag_new_usable (victim), sz);
+  *victimp = mem2mem_check (tag_new_usable (victim), sz);
+
+  return true;
 }
+strong_alias (malloc_check, __malloc_check_malloc)
 
-static void
-free_check (void *mem, const void *caller)
+static bool
+free_check (void *mem)
 {
   mchunkptr p;
 
+  if (force_malloc_check_off)
+    return false;
+
   if (!mem)
-    return;
+    return true;
 
   int err = errno;
 
@@ -253,28 +248,36 @@ free_check (void *mem, const void *caller)
       __libc_lock_unlock (main_arena.mutex);
     }
   __set_errno (err);
+
+  return true;
 }
+strong_alias (free_check, __malloc_check_free)
 
-static void *
-realloc_check (void *oldmem, size_t bytes, const void *caller)
+bool
+__malloc_check_realloc (void *oldmem, size_t bytes, void **victimp)
 {
   INTERNAL_SIZE_T chnb;
   void *newmem = 0;
   unsigned char *magic_p;
   size_t rb;
 
+  if (force_malloc_check_off)
+    return false;
+
   if (__builtin_add_overflow (bytes, 1, &rb))
     {
       __set_errno (ENOMEM);
-      return NULL;
+      *victimp = NULL;
+      return true;
     }
   if (oldmem == 0)
-    return malloc_check (bytes, NULL);
+    return malloc_check (bytes, victimp);
 
   if (bytes == 0)
     {
-      free_check (oldmem, NULL);
-      return NULL;
+      free_check (oldmem);
+      *victimp = NULL;
+      return true;
     }
 
   /* Quickly check that the freed pointer matches the tag for the memory.
@@ -344,16 +347,20 @@ invert:
 
   __libc_lock_unlock (main_arena.mutex);
 
-  return mem2mem_check (tag_new_usable (newmem), bytes);
+  *victimp = mem2mem_check (tag_new_usable (newmem), bytes);
+  return true;
 }
 
-static void *
-memalign_check (size_t alignment, size_t bytes, const void *caller)
+bool
+__malloc_check_memalign (size_t alignment, size_t bytes, void **victimp)
 {
   void *mem;
 
+  if (force_malloc_check_off)
+    return false;
+
   if (alignment <= MALLOC_ALIGNMENT)
-    return malloc_check (bytes, NULL);
+    return malloc_check (bytes, victimp);
 
   if (alignment < MINSIZE)
     alignment = MINSIZE;
@@ -363,14 +370,16 @@ memalign_check (size_t alignment, size_t bytes, const void *caller)
   if (alignment > SIZE_MAX / 2 + 1)
     {
       __set_errno (EINVAL);
-      return 0;
+      *victimp = NULL;
+      return true;
     }
 
   /* Check for overflow.  */
   if (bytes > SIZE_MAX - alignment - MINSIZE)
     {
       __set_errno (ENOMEM);
-      return 0;
+      *victimp = NULL;
+      return true;
     }
 
   /* Make sure alignment is power of 2.  */
@@ -386,5 +395,6 @@ memalign_check (size_t alignment, size_t bytes, const void *caller)
   top_check ();
   mem = _int_memalign (&main_arena, alignment, bytes + 1);
   __libc_lock_unlock (main_arena.mutex);
-  return mem2mem_check (tag_new_usable (mem), bytes);
+  *victimp = mem2mem_check (tag_new_usable (mem), bytes);
+  return true;
 }
diff --git a/malloc/malloc-check.h b/malloc/malloc-check.h
new file mode 100644
index 0000000000..6fae260b8b
--- /dev/null
+++ b/malloc/malloc-check.h
@@ -0,0 +1,32 @@
+/* glibc.malloc.check function interface for libc_malloc_debug.so.
+   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/>.  */
+
+#ifndef _MALLOC_CHECK_H_
+# define _MALLOC_CHECK_H_
+
+# if !IS_IN (libc_malloc_debug)
+#  error "These functions must only be used in libc_malloc_debug.so"
+# else
+extern size_t __malloc_usable_size (void *);
+extern size_t __malloc_check_malloc_usable_size (void *);
+extern bool __malloc_check_malloc (size_t, void **);
+extern bool __malloc_check_free (void *);
+extern bool __malloc_check_realloc (void *, size_t, void **);
+extern bool __malloc_check_memalign (size_t, size_t, void **);
+# endif
+#endif
diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c
index e810d47107..87048f8536 100644
--- a/malloc/malloc-debug.c
+++ b/malloc/malloc-debug.c
@@ -23,6 +23,14 @@
 #include <unistd.h>
 #include <sys/param.h>
 
+#define TUNABLE_NAMESPACE malloc
+#include <elf/dl-tunables.h>
+
+/* A compatible libc will set this totem to a non-zero value.  This is
+   needed for __malloc_check at the moment because the new __malloc_check_*
+   functions are not available in older libc.  */
+unsigned __malloc_debug_totem = 0;
+
 /* Support only the glibc allocators.  */
 extern void *__libc_malloc (size_t);
 extern void __libc_free (void *);
@@ -50,6 +58,7 @@ enum malloc_debug_hooks
   MALLOC_NONE_HOOK = 0,
   MALLOC_MCHECK_HOOK = 1 << 0, /* mcheck()  */
   MALLOC_MTRACE_HOOK = 1 << 1, /* mtrace()  */
+  MALLOC_CHECK_HOOK = 1 << 2,  /* MALLOC_CHECK_ or glibc.malloc.check.  */
 };
 static unsigned __malloc_debugging_hooks;
 
@@ -73,6 +82,7 @@ __malloc_debug_disable (enum malloc_debug_hooks flag)
 
 #include "mcheck.c"
 #include "mtrace.c"
+#include "malloc-check.h"
 
 extern void (*__free_hook) (void *, const void *);
 compat_symbol_reference (libc, __free_hook, __free_hook, GLIBC_2_0);
@@ -85,6 +95,32 @@ compat_symbol_reference (libc, __memalign_hook, __memalign_hook, GLIBC_2_0);
 
 static size_t pagesize;
 
+static void
+TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp)
+{
+  int32_t value = (int32_t) valp->numval;
+  if (value != 0 && __malloc_debug_totem)
+    __malloc_debug_enable (MALLOC_CHECK_HOOK);
+}
+
+static __always_inline void
+maybe_initialize (void)
+{
+  if (!malloc_called)
+    {
+#if HAVE_TUNABLES
+      TUNABLE_GET (check, int32_t, TUNABLE_CALLBACK (set_mallopt_check));
+#else
+      const char *s = secure_getenv ("MALLOC_CHECK_");
+      if (s && s[0] != '\0' && s[0] != '0' && __malloc_debug_totem)
+	__malloc_debug_enable (MALLOC_CHECK_HOOK);
+#endif
+      /* The mcheck initializer runs before this through the initializer
+	 hook so it is safe to set this here.  */
+      malloc_called = true;
+    }
+}
+
 /* The allocator functions.  */
 
 static void *
@@ -94,12 +130,14 @@ __debug_malloc (size_t bytes)
   if (__builtin_expect (hook != NULL, 0))
     return (*hook)(bytes, RETURN_ADDRESS (0));
 
-  malloc_called = true;
+  maybe_initialize ();
 
   void *victim = NULL;
   size_t orig_bytes = bytes;
-  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
-      || !malloc_mcheck_before (&bytes, &victim))
+  if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+       || !malloc_mcheck_before (&bytes, &victim))
+      && (!__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
+	  || !__malloc_check_malloc (bytes, &victim)))
     {
       victim = __libc_malloc (bytes);
     }
@@ -124,10 +162,13 @@ __debug_free (void *mem)
 
   if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
     mem = free_mcheck (mem);
+  if (!__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
+      || !__malloc_check_free (mem))
+    {
+      __libc_free (mem);
+    }
   if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
     free_mtrace (mem, RETURN_ADDRESS (0));
-
-  __libc_free (mem);
 }
 strong_alias (__debug_free, free)
 
@@ -139,13 +180,15 @@ __debug_realloc (void *oldmem, size_t bytes)
   if (__builtin_expect (hook != NULL, 0))
     return (*hook)(oldmem, bytes, RETURN_ADDRESS (0));
 
-  malloc_called = true;
+  maybe_initialize ();
 
   size_t orig_bytes = bytes, oldsize = 0;
   void *victim = NULL;
 
-  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
-      || !realloc_mcheck_before (&oldmem, &bytes, &oldsize, &victim))
+  if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+       || !realloc_mcheck_before (&oldmem, &bytes, &oldsize, &victim))
+      && (!__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
+	  || !__malloc_check_realloc (oldmem, bytes, &victim)))
     {
       victim = __libc_realloc (oldmem, bytes);
     }
@@ -167,13 +210,15 @@ _mid_memalign (size_t alignment, size_t bytes, const void *address)
   if (__builtin_expect (hook != NULL, 0))
     return (*hook)(alignment, bytes, address);
 
-  malloc_called = true;
+  maybe_initialize ();
 
   void *victim = NULL;
   size_t orig_bytes = bytes;
 
-  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
-      || !memalign_mcheck_before (alignment, &bytes, &victim))
+  if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+       || !memalign_mcheck_before (alignment, &bytes, &victim))
+      && (!__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
+	  || !__malloc_check_memalign (alignment, bytes, &victim)))
     {
       victim = __libc_memalign (alignment, bytes);
     }
@@ -266,13 +311,15 @@ __debug_calloc (size_t nmemb, size_t size)
       return mem;
     }
 
-  malloc_called = true;
+  maybe_initialize ();
 
   size_t orig_bytes = bytes;
   void *victim = NULL;
 
-  if (!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
-      || !malloc_mcheck_before (&bytes, &victim))
+  if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
+       || !malloc_mcheck_before (&bytes, &victim))
+      && (!__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
+	  || !__malloc_check_malloc (bytes, &victim)))
     {
       victim = __libc_malloc (bytes);
     }
@@ -288,3 +335,12 @@ __debug_calloc (size_t nmemb, size_t size)
   return victim;
 }
 strong_alias (__debug_calloc, calloc)
+
+size_t
+malloc_usable_size (void *mem)
+{
+  if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
+    return __malloc_check_malloc_usable_size (mem);
+
+  return __malloc_usable_size (mem);
+}
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 595dd8bbdb..1c1e1ab60b 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1114,13 +1114,6 @@ static void munmap_chunk(mchunkptr p);
 static mchunkptr mremap_chunk(mchunkptr p, size_t new_size);
 #endif
 
-static void*   malloc_check(size_t sz, const void *caller);
-static void      free_check(void* mem, const void *caller);
-static void*   realloc_check(void* oldmem, size_t bytes,
-			       const void *caller);
-static void*   memalign_check(size_t alignment, size_t bytes,
-				const void *caller);
-
 /* ------------------ MMAP support ------------------  */
 
 
@@ -5054,9 +5047,6 @@ musable (void *mem)
 
       p = mem2chunk (mem);
 
-      if (__builtin_expect (using_malloc_checking == 1, 0))
-	return malloc_check_get_size (p);
-
       if (chunk_is_mmapped (p))
 	{
 	  if (DUMPED_MAIN_ARENA_CHUNK (p))
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 6/8] Remove malloc hooks
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
                   ` (4 preceding siblings ...)
  2021-07-05 17:08 ` [PATCH v5 5/8] glibc.malloc.check: " Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 7/8] Remove __after_morecore_hook Siddhesh Poyarekar
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

Make malloc hooks symbols compat-only so that new applications cannot
link against them and remove the declarations from the API.  Also
remove the unused malloc-hooks.h.

Add a note about the deprecation in NEWS.
---
 NEWS                  |  10 +++
 malloc/hooks.c        |   6 ++
 malloc/malloc-hooks.h |  24 ------
 malloc/malloc.h       |  14 ----
 manual/memory.texi    | 191 ++----------------------------------------
 5 files changed, 22 insertions(+), 223 deletions(-)
 delete mode 100644 malloc/malloc-hooks.h

diff --git a/NEWS b/NEWS
index 213d790024..4fd4ff0e90 100644
--- a/NEWS
+++ b/NEWS
@@ -103,6 +103,16 @@ Deprecated and removed features, and other changes affecting compatibility:
   features now need to preload a new debugging DSO libc_malloc_debug.so to get
   this functionality back.
 
+* The deprecated memory allocation hooks __malloc_hook, __realloc_hook,
+  __memalign_hook and __free_hook are now removed from the API.  Compatibility
+  symbols are present to support legacy programs but new applications can no
+  longer link to these symbols.  These hooks no longer have any effect on glibc
+  functionality.  The malloc debugging DSO libc_malloc_debug.so currently
+  supports hooks and can be preloaded to get this functionality back for older
+  programs.  However this is a transitional measure and may be removed in a
+  future release of the GNU C Library.  Users may port away from these hooks by
+  writing and preloading their own malloc interposition library.
+
 Changes to build and runtime requirements:
 
 * On Linux, the shm_open, sem_open, and related functions now expect the
diff --git a/malloc/hooks.c b/malloc/hooks.c
index a9aebdd057..ffaf3a645a 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -23,17 +23,22 @@ compat_symbol (libc, __malloc_initialize_hook,
 	       __malloc_initialize_hook, GLIBC_2_0);
 #endif
 
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
 static void *malloc_hook_ini (size_t, const void *) __THROW;
 static void *realloc_hook_ini (void *, size_t, const void *) __THROW;
 static void *memalign_hook_ini (size_t, size_t, const void *) __THROW;
 
 void weak_variable (*__free_hook) (void *, const void *) = NULL;
+compat_symbol (libc, __free_hook, __free_hook, GLIBC_2_0);
 void *weak_variable (*__malloc_hook)
   (size_t, const void *) = malloc_hook_ini;
+compat_symbol (libc, __malloc_hook, __malloc_hook, GLIBC_2_0);
 void *weak_variable (*__realloc_hook)
   (void *, size_t, const void *) = realloc_hook_ini;
+compat_symbol (libc, __realloc_hook, __realloc_hook, GLIBC_2_0);
 void *weak_variable (*__memalign_hook)
   (size_t, size_t, const void *) = memalign_hook_ini;
+compat_symbol (libc, __memalign_hook, __memalign_hook, GLIBC_2_0);
 
 /* This is interposed by libc_malloc_debug.so to match with a compatible libc.
    We don't use dlsym or equivalent because the dlsym symbol version got bumped
@@ -87,6 +92,7 @@ memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
   generic_hook_ini ();
   return memalign (alignment, sz);
 }
+#endif
 
 static bool force_malloc_check_off = false;
 
diff --git a/malloc/malloc-hooks.h b/malloc/malloc-hooks.h
deleted file mode 100644
index 0133331b83..0000000000
--- a/malloc/malloc-hooks.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Internal declarations of malloc hooks no longer in the public API.
-   Copyright (C) 2016-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/>.  */
-
-#ifndef _MALLOC_HOOKS_H
-#define _MALLOC_HOOKS_H
-
-void (*__malloc_initialize_hook) (void);
-
-#endif  /* _MALLOC_HOOKS_H */
diff --git a/malloc/malloc.h b/malloc/malloc.h
index c1c0896d29..709fa454b5 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -165,20 +165,6 @@ extern void malloc_stats (void) __THROW;
 extern int malloc_info (int __options, FILE *__fp) __THROW;
 
 /* Hooks for debugging and user-defined versions. */
-extern void (*__MALLOC_HOOK_VOLATILE __free_hook) (void *__ptr,
-                                                   const void *)
-__MALLOC_DEPRECATED;
-extern void *(*__MALLOC_HOOK_VOLATILE __malloc_hook)(size_t __size,
-                                                     const void *)
-__MALLOC_DEPRECATED;
-extern void *(*__MALLOC_HOOK_VOLATILE __realloc_hook)(void *__ptr,
-                                                      size_t __size,
-                                                      const void *)
-__MALLOC_DEPRECATED;
-extern void *(*__MALLOC_HOOK_VOLATILE __memalign_hook)(size_t __alignment,
-                                                       size_t __size,
-                                                       const void *)
-__MALLOC_DEPRECATED;
 extern void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void)
   __MALLOC_DEPRECATED;
 
diff --git a/manual/memory.texi b/manual/memory.texi
index 0aae1f8720..e310061d76 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -328,8 +328,6 @@ any time (or never).
 * Malloc Tunable Parameters::   Use @code{mallopt} to adjust allocation
                                  parameters.
 * Heap Consistency Checking::   Automatic checking for errors.
-* Hooks for Malloc::            You can use these hooks for debugging
-				 programs that use @code{malloc}.
 * Statistics of Malloc::        Getting information about how much
 				 memory your program is using.
 * Summary of Malloc::           Summary of @code{malloc} and related functions.
@@ -1392,170 +1390,6 @@ compatibility.  Both @code{MALLOC_CHECK_} and @samp{-lmcheck} should
 uncover the same bugs - but using @code{MALLOC_CHECK_} you don't need to
 recompile your application.
 
-@node Hooks for Malloc
-@subsubsection Memory Allocation Hooks
-@cindex allocation hooks, for @code{malloc}
-
-@Theglibc{} lets you modify the behavior of @code{malloc},
-@code{realloc}, and @code{free} by specifying appropriate hook
-functions.  You can use these hooks to help you debug programs that use
-dynamic memory allocation, for example.
-
-The hook variables are declared in @file{malloc.h}.
-@pindex malloc.h
-
-@defvar __malloc_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to the function that
-@code{malloc} uses whenever it is called.  You should define this
-function to look like @code{malloc}; that is, like:
-
-@smallexample
-void *@var{function} (size_t @var{size}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{malloc} function was called.  This value allows you to trace
-the memory consumption of the program.
-@end defvar
-
-@defvar __realloc_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to function that @code{realloc}
-uses whenever it is called.  You should define this function to look
-like @code{realloc}; that is, like:
-
-@smallexample
-void *@var{function} (void *@var{ptr}, size_t @var{size}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{realloc} function was called.  This value allows you to trace the
-memory consumption of the program.
-@end defvar
-
-@defvar __free_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to function that @code{free}
-uses whenever it is called.  You should define this function to look
-like @code{free}; that is, like:
-
-@smallexample
-void @var{function} (void *@var{ptr}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{free} function was called.  This value allows you to trace the
-memory consumption of the program.
-@end defvar
-
-@defvar __memalign_hook
-@standards{GNU, malloc.h}
-The value of this variable is a pointer to function that @code{aligned_alloc},
-@code{memalign}, @code{posix_memalign} and @code{valloc} use whenever they
-are called.  You should define this function to look like @code{aligned_alloc};
-that is, like:
-
-@smallexample
-void *@var{function} (size_t @var{alignment}, size_t @var{size}, const void *@var{caller})
-@end smallexample
-
-The value of @var{caller} is the return address found on the stack when
-the @code{aligned_alloc}, @code{memalign}, @code{posix_memalign} or
-@code{valloc} functions are called.  This value allows you to trace the
-memory consumption of the program.
-@end defvar
-
-You must make sure that the function you install as a hook for one of
-these functions does not call that function recursively without restoring
-the old value of the hook first!  Otherwise, your program will get stuck
-in an infinite recursion.  Before calling the function recursively, one
-should make sure to restore all the hooks to their previous value.  When
-coming back from the recursive call, all the hooks should be resaved
-since a hook might modify itself.
-
-An issue to look out for is the time at which the hook functions
-can be safely installed.  If the hook functions call the @code{malloc}-related
-functions recursively, it is necessary that @code{malloc} has already properly
-initialized itself at the time when @code{__malloc_hook} etc. is
-assigned to.  On the other hand, if the hook functions provide a
-complete @code{malloc} implementation of their own, it is vital that the hooks
-are assigned to @emph{before} the very first @code{malloc} call has
-completed, because otherwise a chunk obtained from the ordinary,
-un-hooked @code{malloc} may later be handed to @code{__free_hook}, for example.
-
-Here is an example showing how to use @code{__malloc_hook} and
-@code{__free_hook} properly.  It installs a function that prints out
-information every time @code{malloc} or @code{free} is called.  We just
-assume here that @code{realloc} and @code{memalign} are not used in our
-program.
-
-@smallexample
-/* Prototypes for __malloc_hook, __free_hook */
-#include <malloc.h>
-
-/* Prototypes for our hooks.  */
-static void my_init_hook (void);
-static void *my_malloc_hook (size_t, const void *);
-static void my_free_hook (void*, const void *);
-
-static void
-my_init (void)
-@{
-  old_malloc_hook = __malloc_hook;
-  old_free_hook = __free_hook;
-  __malloc_hook = my_malloc_hook;
-  __free_hook = my_free_hook;
-@}
-
-static void *
-my_malloc_hook (size_t size, const void *caller)
-@{
-  void *result;
-  /* Restore all old hooks */
-  __malloc_hook = old_malloc_hook;
-  __free_hook = old_free_hook;
-  /* Call recursively */
-  result = malloc (size);
-  /* Save underlying hooks */
-  old_malloc_hook = __malloc_hook;
-  old_free_hook = __free_hook;
-  /* @r{@code{printf} might call @code{malloc}, so protect it too.} */
-  printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
-  /* Restore our own hooks */
-  __malloc_hook = my_malloc_hook;
-  __free_hook = my_free_hook;
-  return result;
-@}
-
-static void
-my_free_hook (void *ptr, const void *caller)
-@{
-  /* Restore all old hooks */
-  __malloc_hook = old_malloc_hook;
-  __free_hook = old_free_hook;
-  /* Call recursively */
-  free (ptr);
-  /* Save underlying hooks */
-  old_malloc_hook = __malloc_hook;
-  old_free_hook = __free_hook;
-  /* @r{@code{printf} might call @code{free}, so protect it too.} */
-  printf ("freed pointer %p\n", ptr);
-  /* Restore our own hooks */
-  __malloc_hook = my_malloc_hook;
-  __free_hook = my_free_hook;
-@}
-
-main ()
-@{
-  my_init ();
-  @dots{}
-@}
-@end smallexample
-
-The @code{mcheck} function (@pxref{Heap Consistency Checking}) works by
-installing such hooks.
-
 @c __morecore, __after_morecore_hook are undocumented
 @c It's not clear whether to document them.
 
@@ -1690,19 +1524,6 @@ Tell @code{malloc} to perform occasional consistency checks on
 dynamically allocated memory, and to call @var{abortfn} when an
 inconsistency is found.  @xref{Heap Consistency Checking}.
 
-@item void *(*__malloc_hook) (size_t @var{size}, const void *@var{caller})
-A pointer to a function that @code{malloc} uses whenever it is called.
-
-@item void *(*__realloc_hook) (void *@var{ptr}, size_t @var{size}, const void *@var{caller})
-A pointer to a function that @code{realloc} uses whenever it is called.
-
-@item void (*__free_hook) (void *@var{ptr}, const void *@var{caller})
-A pointer to a function that @code{free} uses whenever it is called.
-
-@item void (*__memalign_hook) (size_t @var{size}, size_t @var{alignment}, const void *@var{caller})
-A pointer to a function that @code{aligned_alloc}, @code{memalign},
-@code{posix_memalign} and @code{valloc} use whenever they are called.
-
 @item struct mallinfo2 mallinfo2 (void)
 Return information about the current dynamic memory usage.
 @xref{Statistics of Malloc}.
@@ -1737,7 +1558,7 @@ penalties for the program if the debugging mode is not enabled.
 
 @deftypefun void mtrace (void)
 @standards{GNU, mcheck.h}
-@safety{@prelim{}@mtunsafe{@mtsenv{} @mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtuinit{}}@asunsafe{@asuinit{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsfd{} @acsmem{}}}
+@safety{@prelim{}@mtunsafe{@mtsenv{} @mtasurace{:mtrace} @mtuinit{}}@asunsafe{@asuinit{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsfd{} @acsmem{}}}
 @c Like the mcheck hooks, these are not designed with thread safety in
 @c mind, because the hook pointers are temporarily modified without
 @c regard to other threads, signals or cancellation.
@@ -1768,10 +1589,10 @@ with the SUID or SGID bit set.
 
 If the named file is successfully opened, @code{mtrace} installs special
 handlers for the functions @code{malloc}, @code{realloc}, and
-@code{free} (@pxref{Hooks for Malloc}).  From then on, all uses of these
-functions are traced and protocolled into the file.  There is now of
-course a speed penalty for all calls to the traced functions so tracing
-should not be enabled during normal use.
+@code{free}.  From then on, all uses of these functions are traced and
+protocolled into the file.  There is now of course a speed penalty for all
+calls to the traced functions so tracing should not be enabled during normal
+use.
 
 This function is a GNU extension and generally not available on other
 systems.  The prototype can be found in @file{mcheck.h}.
@@ -1779,7 +1600,7 @@ systems.  The prototype can be found in @file{mcheck.h}.
 
 @deftypefun void muntrace (void)
 @standards{GNU, mcheck.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{} @aculock{} @acsfd{}}}
+@safety{@prelim{}@mtunsafe{@mtasurace{:mtrace} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{} @aculock{} @acsfd{}}}
 
 @c muntrace @mtasurace:mtrace @mtslocale @asucorrupt @ascuheap @acucorrupt @acsmem @aculock @acsfd
 @c  fprintf (fputs) dup @mtslocale @asucorrupt @ascuheap @acsmem @aculock @acucorrupt
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 7/8] Remove __after_morecore_hook
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
                   ` (5 preceding siblings ...)
  2021-07-05 17:08 ` [PATCH v5 6/8] Remove " Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-05 17:08 ` [PATCH v5 8/8] Remove __morecore and __default_morecore Siddhesh Poyarekar
  2021-07-06 19:45 ` [PATCH v5 0/8] malloc hooks removal DJ Delorie
  8 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

Remove __after_morecore_hook from the API and finalize the symbol so
that it can no longer be used in new applications.  Old applications
using __after_morecore_hook will find that their hook is no longer
called.
---
 malloc/hooks.c  |  7 +++++++
 malloc/malloc.c | 30 +-----------------------------
 malloc/malloc.h |  5 -----
 3 files changed, 8 insertions(+), 34 deletions(-)

diff --git a/malloc/hooks.c b/malloc/hooks.c
index ffaf3a645a..50ea03b562 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -24,6 +24,10 @@ compat_symbol (libc, __malloc_initialize_hook,
 #endif
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
+# ifndef weak_variable
+#  define weak_variable weak_function
+# 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;
@@ -40,6 +44,9 @@ void *weak_variable (*__memalign_hook)
   (size_t, size_t, const void *) = memalign_hook_ini;
 compat_symbol (libc, __memalign_hook, __memalign_hook, GLIBC_2_0);
 
+void weak_variable (*__after_morecore_hook) (void) = NULL;
+compat_symbol (libc, __after_morecore_hook, __after_morecore_hook, GLIBC_2_0);
+
 /* This is interposed by libc_malloc_debug.so to match with a compatible libc.
    We don't use dlsym or equivalent because the dlsym symbol version got bumped
    in 2.34 and is hence unusable in libc_malloc_debug.so.  */
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 1c1e1ab60b..00fcc676a0 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1988,16 +1988,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
-
-void weak_variable (*__after_morecore_hook) (void) = NULL;
-
 /* This function is called from the arena shutdown hook, to free the
    thread cache (if it exists).  */
 static void tcache_thread_shutdown (void);
@@ -2623,14 +2613,7 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
           LIBC_PROBE (memory_sbrk_more, 2, brk, size);
         }
 
-      if (brk != (char *) (MORECORE_FAILURE))
-        {
-          /* Call the `morecore' hook if necessary.  */
-          void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
-          if (__builtin_expect (hook != NULL, 0))
-            (*hook)();
-        }
-      else
+      if (brk == (char *) (MORECORE_FAILURE))
         {
           /*
              If have mmap, try using it as a backup when MORECORE fails or
@@ -2769,13 +2752,6 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
                       correction = 0;
                       snd_brk = (char *) (MORECORE (0));
                     }
-                  else
-                    {
-                      /* Call the `morecore' hook if necessary.  */
-                      void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
-                      if (__builtin_expect (hook != NULL, 0))
-                        (*hook)();
-                    }
                 }
 
               /* handle non-contiguous cases */
@@ -2934,10 +2910,6 @@ systrim (size_t pad, mstate av)
        */
 
       MORECORE (-extra);
-      /* Call the `morecore' hook if necessary.  */
-      void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
-      if (__builtin_expect (hook != NULL, 0))
-        (*hook)();
       new_brk = (char *) (MORECORE (0));
 
       LIBC_PROBE (memory_sbrk_less, 2, new_brk, extra);
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 709fa454b5..d066a05d82 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -164,10 +164,5 @@ extern void malloc_stats (void) __THROW;
 /* Output information about state of allocator to stream FP.  */
 extern int malloc_info (int __options, FILE *__fp) __THROW;
 
-/* Hooks for debugging and user-defined versions. */
-extern void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void)
-  __MALLOC_DEPRECATED;
-
-
 __END_DECLS
 #endif /* malloc.h */
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 8/8] Remove __morecore and __default_morecore
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
                   ` (6 preceding siblings ...)
  2021-07-05 17:08 ` [PATCH v5 7/8] Remove __after_morecore_hook Siddhesh Poyarekar
@ 2021-07-05 17:08 ` Siddhesh Poyarekar
  2021-07-06 19:45 ` [PATCH v5 0/8] malloc hooks removal DJ Delorie
  8 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-05 17:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: dj, carlos, fweimer

Make the __morecore and __default_morecore symbols compat-only and
remove their declarations from the API.
---
 NEWS                     |  5 +++++
 include/stdlib.h         |  3 ---
 malloc/arena.c           | 12 ++----------
 malloc/hooks.c           |  2 ++
 malloc/malloc-internal.h |  5 +++++
 malloc/malloc.c          |  4 +---
 malloc/malloc.h          |  8 --------
 malloc/morecore.c        | 15 +++++++++++++--
 8 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/NEWS b/NEWS
index 4fd4ff0e90..038420a621 100644
--- a/NEWS
+++ b/NEWS
@@ -113,6 +113,11 @@ Deprecated and removed features, and other changes affecting compatibility:
   future release of the GNU C Library.  Users may port away from these hooks by
   writing and preloading their own malloc interposition library.
 
+* The __morecore and __after_morecore_hook malloc hooks and the default
+  implementation __default_morecore have been removed from the API.  Existing
+  applications will continue to link against these symbols but the interfaces
+  no longer have any effect on malloc.
+
 Changes to build and runtime requirements:
 
 * On Linux, the shm_open, sem_open, and related functions now expect the
diff --git a/include/stdlib.h b/include/stdlib.h
index 1f6e1508e4..1c6f70b082 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -306,9 +306,6 @@ libc_hidden_proto (__qfcvt_r)
 #  define MB_CUR_MAX (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX))
 # endif
 
-extern void *__default_morecore (ptrdiff_t) __THROW;
-libc_hidden_proto (__default_morecore)
-
 struct abort_msg_s
 {
   unsigned int size;
diff --git a/malloc/arena.c b/malloc/arena.c
index 1ae57f43d5..0650b05c79 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -266,14 +266,6 @@ next_env_entry (char ***position)
 #endif
 
 
-#if defined(SHARED) || defined(USE_MTAG)
-static void *
-__failing_morecore (ptrdiff_t d)
-{
-  return (void *) MORECORE_FAILURE;
-}
-#endif
-
 #ifdef SHARED
 extern struct dl_open_hook *_dl_open_hook;
 libc_hidden_proto (_dl_open_hook);
@@ -294,7 +286,7 @@ ptmalloc_init (void)
 	 and that morecore does not support tagged regions, then
 	 disable it.  */
       if (__MTAG_SBRK_UNTAGGED)
-	__morecore = __failing_morecore;
+	__always_fail_morecore = true;
 
       mtag_enabled = true;
       mtag_mmap_flags = __MTAG_MMAP_FLAGS;
@@ -307,7 +299,7 @@ ptmalloc_init (void)
      generic sbrk implementation also enforces this, but it is not
      used on Hurd.  */
   if (!__libc_initial)
-    __morecore = __failing_morecore;
+    __always_fail_morecore = true;
 #endif
 
   thread_arena = &main_arena;
diff --git a/malloc/hooks.c b/malloc/hooks.c
index 50ea03b562..360e4920d1 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -46,6 +46,8 @@ compat_symbol (libc, __memalign_hook, __memalign_hook, GLIBC_2_0);
 
 void weak_variable (*__after_morecore_hook) (void) = NULL;
 compat_symbol (libc, __after_morecore_hook, __after_morecore_hook, GLIBC_2_0);
+void *(*__morecore)(ptrdiff_t);
+compat_symbol (libc, __morecore, __morecore, GLIBC_2_0);
 
 /* This is interposed by libc_malloc_debug.so to match with a compatible libc.
    We don't use dlsym or equivalent because the dlsym symbol version got bumped
diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index 258f29584e..611aa97762 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -21,6 +21,7 @@
 
 #include <malloc-machine.h>
 #include <malloc-sysdep.h>
+#include <stdbool.h>
 
 /* INTERNAL_SIZE_T is the word-size used for internal bookkeeping of
    chunk sizes.
@@ -62,6 +63,8 @@
 #define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
 
 
+extern bool __always_fail_morecore attribute_hidden;
+
 /* Called in the parent process before a fork.  */
 void __malloc_fork_lock_parent (void) attribute_hidden;
 
@@ -77,4 +80,6 @@ void __malloc_arena_thread_freeres (void) attribute_hidden;
 /* Activate a standard set of debugging hooks. */
 void __malloc_check_init (void) attribute_hidden;
 
+extern void *__glibc_morecore (ptrdiff_t) attribute_hidden;
+
 #endif /* _MALLOC_INTERNAL_H */
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 00fcc676a0..0b8c6d9086 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -382,10 +382,8 @@ __malloc_assert (const char *assertion, const char *file, unsigned int line,
 
 
 /* Definition for getting more memory from the OS.  */
-#define MORECORE         (*__morecore)
+#define MORECORE         (*__glibc_morecore)
 #define MORECORE_FAILURE 0
-void * __default_morecore (ptrdiff_t);
-void *(*__morecore)(ptrdiff_t) = __default_morecore;
 
 /* Memory tagging.  */
 
diff --git a/malloc/malloc.h b/malloc/malloc.h
index d066a05d82..2df0b38050 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -76,14 +76,6 @@ extern void *valloc (size_t __size) __THROW __attribute_malloc__
 extern void *pvalloc (size_t __size) __THROW __attribute_malloc__
   __wur __attr_dealloc_free;
 
-/* Underlying allocation function; successive calls should return
-   contiguous pieces of memory.  */
-extern void *(*__morecore) (ptrdiff_t __size) __MALLOC_DEPRECATED;
-
-/* Default value of `__morecore'.  */
-extern void *__default_morecore (ptrdiff_t __size)
-__THROW __attribute_malloc__  __MALLOC_DEPRECATED;
-
 /* SVID2/XPG mallinfo structure */
 
 struct mallinfo
diff --git a/malloc/morecore.c b/malloc/morecore.c
index 047228779b..c85a85c0eb 100644
--- a/malloc/morecore.c
+++ b/malloc/morecore.c
@@ -38,16 +38,27 @@ libc_hidden_proto (__sbrk)
 # define NULL 0
 #endif
 
+#if defined(SHARED) || defined(USE_MTAG)
+bool __always_fail_morecore = false;
+#endif
+
 /* Allocate INCREMENT more bytes of data space,
    and return the start of data space, or NULL on errors.
    If INCREMENT is negative, shrink data space.  */
 void *
-__default_morecore (ptrdiff_t increment)
+__glibc_morecore (ptrdiff_t increment)
 {
+#if defined(SHARED) || defined(USE_MTAG)
+  if (__always_fail_morecore)
+    return NULL;
+#endif
+
   void *result = (void *) __sbrk (increment);
   if (result == (void *) -1)
     return NULL;
 
   return result;
 }
-libc_hidden_def (__default_morecore)
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
+compat_symbol (libc, __glibc_morecore, __default_morecore, GLIBC_2_0);
+#endif
-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 1/8] Move malloc hooks into a compat DSO
  2021-07-05 17:08 ` [PATCH v5 1/8] Move malloc hooks into a compat DSO Siddhesh Poyarekar
@ 2021-07-06 10:17   ` Florian Weimer
  2021-07-06 13:00     ` Siddhesh Poyarekar
  0 siblings, 1 reply; 16+ messages in thread
From: Florian Weimer @ 2021-07-06 10:17 UTC (permalink / raw)
  To: Siddhesh Poyarekar; +Cc: libc-alpha, dj, carlos

* Siddhesh Poyarekar:

> Remove all malloc hook uses from core malloc functions and move it
> into a new library libc_malloc_debug.so.  With this, the hooks now no
> longer have any effect on the core library.

There are still a few references to libmalloc_compathooks.

> diff --git a/elf/Makefile b/elf/Makefile
> index 698a6ab985..b432e78d39 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -156,7 +156,7 @@ $(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force)

> @@ -1561,7 +1558,8 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
>  				   $(objpfx)tst-nodelete-dlclose-plugin.so
>  
>  tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
> -		     LD_HWCAP_MASK=0x1
> +		     LD_HWCAP_MASK=0x1 \
> +		     LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so

I don't think this test needs the debugging allocator, it uses getenv to
see if the environment has been scrubbed.

In general, it looks like it's time to add support for mtrace tests to
the setsuite (that is, tests-mtrace like tests-time64).

Thanks,
Florian


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 1/8] Move malloc hooks into a compat DSO
  2021-07-06 10:17   ` Florian Weimer
@ 2021-07-06 13:00     ` Siddhesh Poyarekar
  2021-07-06 13:12       ` Siddhesh Poyarekar
  2021-07-06 14:29       ` Florian Weimer
  0 siblings, 2 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-06 13:00 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 7/6/21 3:47 PM, Florian Weimer via Libc-alpha wrote:
> * Siddhesh Poyarekar:
> 
>> Remove all malloc hook uses from core malloc functions and move it
>> into a new library libc_malloc_debug.so.  With this, the hooks now no
>> longer have any effect on the core library.
> 
> There are still a few references to libmalloc_compathooks.

Fixed locally.

>> diff --git a/elf/Makefile b/elf/Makefile
>> index 698a6ab985..b432e78d39 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -156,7 +156,7 @@ $(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force)
> 
>> @@ -1561,7 +1558,8 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
>>   				   $(objpfx)tst-nodelete-dlclose-plugin.so
>>   
>>   tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
>> -		     LD_HWCAP_MASK=0x1
>> +		     LD_HWCAP_MASK=0x1 \
>> +		     LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
> 
> I don't think this test needs the debugging allocator, it uses getenv to
> see if the environment has been scrubbed.

You're right, it doesn't.  I'll remove that.

> In general, it looks like it's time to add support for mtrace tests to
> the setsuite (that is, tests-mtrace like tests-time64).

... or tests-mcheck/tests-malloc-check.  Would you be OK with having the 
test driver call mtrace() at all times?  Only the tests in tests-mtrace 
(which for starters we could add all tests in malloc to) will actually 
have any impact.

Thanks,
Siddhesh

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 1/8] Move malloc hooks into a compat DSO
  2021-07-06 13:00     ` Siddhesh Poyarekar
@ 2021-07-06 13:12       ` Siddhesh Poyarekar
  2021-07-06 14:29       ` Florian Weimer
  1 sibling, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-06 13:12 UTC (permalink / raw)
  To: Siddhesh Poyarekar, Florian Weimer; +Cc: libc-alpha

On 7/6/21 6:30 PM, Siddhesh Poyarekar via Libc-alpha wrote:
>> In general, it looks like it's time to add support for mtrace tests to
>> the setsuite (that is, tests-mtrace like tests-time64).
> 
> ... or tests-mcheck/tests-malloc-check.  Would you be OK with having the 
> test driver call mtrace() at all times?  Only the tests in tests-mtrace 
> (which for starters we could add all tests in malloc to) will actually 
> have any impact.


I forgot to ask, would you like that to be part of this patchset or 
would you be OK with the testing enhancement coming in later?  Mtrace 
already has some testing coverage through tst-mtrace for example and 
other tests using mtrace.

Siddhesh

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 1/8] Move malloc hooks into a compat DSO
  2021-07-06 13:00     ` Siddhesh Poyarekar
  2021-07-06 13:12       ` Siddhesh Poyarekar
@ 2021-07-06 14:29       ` Florian Weimer
  2021-07-06 14:40         ` Siddhesh Poyarekar
  1 sibling, 1 reply; 16+ messages in thread
From: Florian Weimer @ 2021-07-06 14:29 UTC (permalink / raw)
  To: Siddhesh Poyarekar; +Cc: libc-alpha

* Siddhesh Poyarekar:

>> In general, it looks like it's time to add support for mtrace tests to
>> the setsuite (that is, tests-mtrace like tests-time64).
>
> ... or tests-mcheck/tests-malloc-check.  Would you be OK with having
> the test driver call mtrace() at all times?

Could we enable mtrace directly via LD_PRELOAD (or static linking),
without calling the function?

There's also the matter of not flagging potentially leaking allocations
from the test harness itself.

> I forgot to ask, would you like that to be part of this patchset or
> would you be OK with the testing enhancement coming in later?  Mtrace 
> already has some testing coverage through tst-mtrace for example and
> other tests using mtrace.

I don't have a strong preference.  Given the open questions, it's
probably best to delay the cleanup.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 1/8] Move malloc hooks into a compat DSO
  2021-07-06 14:29       ` Florian Weimer
@ 2021-07-06 14:40         ` Siddhesh Poyarekar
  0 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-06 14:40 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 7/6/21 7:59 PM, Florian Weimer via Libc-alpha wrote:
> * Siddhesh Poyarekar:
> 
>>> In general, it looks like it's time to add support for mtrace tests to
>>> the setsuite (that is, tests-mtrace like tests-time64).
>>
>> ... or tests-mcheck/tests-malloc-check.  Would you be OK with having
>> the test driver call mtrace() at all times?
> 
> Could we enable mtrace directly via LD_PRELOAD (or static linking),
> without calling the function?
> 
> There's also the matter of not flagging potentially leaking allocations
> from the test harness itself.

We could link tests with an object that calls mtrace through the 
initialization hook like we do for tests-mcheck, but it will be 
equivalent to calling mtrace() in the driver.  If anything, it may end 
up getting called earlier, possibly recording dynamic linker allocations.

>> I forgot to ask, would you like that to be part of this patchset or
>> would you be OK with the testing enhancement coming in later?  Mtrace
>> already has some testing coverage through tst-mtrace for example and
>> other tests using mtrace.
> 
> I don't have a strong preference.  Given the open questions, it's
> probably best to delay the cleanup.

OK thanks.  I won't delay too long, just that I'd like it if it doesn't 
block this patchset.

Thanks,
Siddhesh

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 0/8] malloc hooks removal
  2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
                   ` (7 preceding siblings ...)
  2021-07-05 17:08 ` [PATCH v5 8/8] Remove __morecore and __default_morecore Siddhesh Poyarekar
@ 2021-07-06 19:45 ` DJ Delorie
  2021-07-07  1:31   ` Siddhesh Poyarekar
  8 siblings, 1 reply; 16+ messages in thread
From: DJ Delorie @ 2021-07-06 19:45 UTC (permalink / raw)
  To: Siddhesh Poyarekar; +Cc: libc-alpha


32-bit builds broke...

In file included from mtrace.c:22,
                 from malloc-debug.c:84:
mtrace-impl.c: In function 'tr_where':
mtrace-impl.c:66:37: error: format '%lx' expects argument of type 'long unsigned int', but argument 5 has type 'ptrdiff_t' {aka 'int'} [-Werror=format=]
   66 |               sprintf (buf, "(%s%c%lx)", info->dli_sname, sign, offset);
      |                                   ~~^                           ~~~~~~
      |                                     |                           |
      |                                     long unsigned int           ptrdiff_t {aka int}
      |                                   %x
cc1: all warnings being treated as errors


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 0/8] malloc hooks removal
  2021-07-06 19:45 ` [PATCH v5 0/8] malloc hooks removal DJ Delorie
@ 2021-07-07  1:31   ` Siddhesh Poyarekar
  0 siblings, 0 replies; 16+ messages in thread
From: Siddhesh Poyarekar @ 2021-07-07  1:31 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha

On 7/7/21 1:15 AM, DJ Delorie wrote:
> 
> 32-bit builds broke...
> 
> In file included from mtrace.c:22,
>                   from malloc-debug.c:84:
> mtrace-impl.c: In function 'tr_where':
> mtrace-impl.c:66:37: error: format '%lx' expects argument of type 'long unsigned int', but argument 5 has type 'ptrdiff_t' {aka 'int'} [-Werror=format=]
>     66 |               sprintf (buf, "(%s%c%lx)", info->dli_sname, sign, offset);
>        |                                   ~~^                           ~~~~~~
>        |                                     |                           |
>        |                                     long unsigned int           ptrdiff_t {aka int}
>        |                                   %x
> cc1: all warnings being treated as errors
> 

Ugh, thanks for checking.  I'll fix this locally and also test builds on 
a couple of different architectures this time.

Siddhesh

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2021-07-07  1:31 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-05 17:08 [PATCH v5 0/8] malloc hooks removal Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 1/8] Move malloc hooks into a compat DSO Siddhesh Poyarekar
2021-07-06 10:17   ` Florian Weimer
2021-07-06 13:00     ` Siddhesh Poyarekar
2021-07-06 13:12       ` Siddhesh Poyarekar
2021-07-06 14:29       ` Florian Weimer
2021-07-06 14:40         ` Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 2/8] mcheck: Wean away from malloc hooks Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 3/8] Simplify __malloc_initialized Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 4/8] mtrace: Wean away from malloc hooks Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 5/8] glibc.malloc.check: " Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 6/8] Remove " Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 7/8] Remove __after_morecore_hook Siddhesh Poyarekar
2021-07-05 17:08 ` [PATCH v5 8/8] Remove __morecore and __default_morecore Siddhesh Poyarekar
2021-07-06 19:45 ` [PATCH v5 0/8] malloc hooks removal DJ Delorie
2021-07-07  1:31   ` Siddhesh Poyarekar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).