diff options
Diffstat (limited to 'malloc')
-rw-r--r-- | malloc/Makefile | 47 | ||||
-rw-r--r-- | malloc/Versions | 20 | ||||
-rw-r--r-- | malloc/arena.c | 7 | ||||
-rw-r--r-- | malloc/hooks.c | 64 | ||||
-rw-r--r-- | malloc/malloc-debug.c | 189 | ||||
-rw-r--r-- | malloc/malloc.c | 85 | ||||
-rw-r--r-- | malloc/mcheck.c | 1 | ||||
-rw-r--r-- | malloc/mtrace.c | 1 | ||||
-rw-r--r-- | malloc/tst-compathooks-off.c | 145 | ||||
-rw-r--r-- | malloc/tst-compathooks-on.c | 2 | ||||
-rw-r--r-- | malloc/tst-malloc-usable-static-tunables.c | 1 | ||||
-rw-r--r-- | malloc/tst-malloc-usable-static.c | 1 | ||||
-rwxr-xr-x | malloc/tst-mtrace.sh | 1 |
13 files changed, 453 insertions, 111 deletions
diff --git a/malloc/Makefile b/malloc/Makefile index bbb70f6f87..cafe427097 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -46,12 +46,11 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tests-static := \ tst-interpose-static-nothread \ - tst-interpose-static-thread \ - tst-malloc-usable-static \ + tst-interpose-static-thread # Test for the malloc_set_state symbol removed in glibc 2.25. -ifeq ($(have-GLIBC_2.24)$(build-shared),yesyes) -tests += tst-mallocstate +ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes) +tests += tst-mallocstate tst-compathooks-off tst-compathooks-on endif tests-internal := tst-scratch_buffer @@ -64,7 +63,6 @@ tests-internal += \ ifneq (no,$(have-tunables)) tests += tst-malloc-usable-tunables tst-mxfast -tests-static += tst-malloc-usable-static-tunables endif tests += $(tests-static) @@ -73,7 +71,8 @@ test-srcs = tst-mtrace # These tests either are run with MALLOC_CHECK_=3 by default or do not work # with MALLOC_CHECK_=3 because they expect a specific failure. tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \ - tst-mxfast tst-safe-linking + tst-mxfast tst-safe-linking \ + tst-compathooks-off tst-compathooks-on # Run all tests with MALLOC_CHECK_=3 tests-malloc-check = $(filter-out $(tests-exclude-malloc-check),$(tests)) @@ -91,15 +90,14 @@ tests-exclude-mcheck = tst-mallocstate \ tst-malloc-tcache-leak \ tst-malloc-thread-exit \ tst-malloc-thread-fail \ - tst-malloc-usable-static \ - tst-malloc-usable-static-tunables \ tst-malloc-usable-tunables \ tst-malloc_info \ tst-memalign \ tst-posix_memalign \ tst-realloc \ tst-pvalloc-fortify \ - tst-reallocarray + tst-reallocarray \ + tst-compathooks-off tst-compathooks-on tests-mcheck = $(filter-out $(tests-exclude-mcheck), $(tests)) endif @@ -122,8 +120,8 @@ routines = malloc mcheck mtrace obstack reallocarray \ install-lib := libmcheck.a non-lib.a := libmcheck.a -# Additional library. -extra-libs = libmemusage +# Additional libraries. +extra-libs = libmemusage libc_malloc_debug extra-libs-others = $(extra-libs) # Helper objects for some tests. @@ -138,6 +136,9 @@ test-extras = \ libmemusage-routines = memusage libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes)) +libc_malloc_debug-routines = malloc-debug +libc_malloc_debug-inhibit-o = $(filter-out .os,$(object-suffixes)) + $(objpfx)tst-malloc-backtrace: $(shared-thread-library) $(objpfx)tst-malloc-thread-exit: $(shared-thread-library) $(objpfx)tst-malloc-thread-fail: $(shared-thread-library) @@ -244,11 +245,12 @@ endif endif endif -tst-malloc-check-ENV = MALLOC_CHECK_=3 -tst-malloc-usable-ENV = MALLOC_CHECK_=3 -tst-malloc-usable-static-ENV = $(tst-malloc-usable-ENV) -tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 -tst-malloc-usable-static-tunables-ENV = $(tst-malloc-usable-tunables-ENV) +tst-malloc-check-ENV = MALLOC_CHECK_=3 \ + LD_PRELOAD=$(objpfx)/libc_malloc_debug.so +tst-malloc-usable-ENV = MALLOC_CHECK_=3 \ + LD_PRELOAD=$(objpfx)/libc_malloc_debug.so +tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 \ + LD_PRELOAD=$(objpfx)/libc_malloc_debug.so tst-mxfast-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=0:glibc.malloc.mxfast=0 @@ -303,12 +305,14 @@ $(objpfx)tst-interpose-static-thread-mcheck: \ $(objpfx)tst-interpose-static-thread-malloc-check: \ $(objpfx)tst-interpose-aux-thread.o $(static-thread-library) -tst-dynarray-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace +tst-dynarray-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace \ + LD_PRELOAD=$(objpfx)libc_malloc_debug.so $(objpfx)tst-dynarray-mem.out: $(objpfx)tst-dynarray.out $(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray.mtrace > $@; \ $(evaluate-test) -tst-dynarray-fail-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace +tst-dynarray-fail-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace \ + LD_PRELOAD=$(objpfx)libc_malloc_debug.so $(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out $(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray-fail.mtrace > $@; \ $(evaluate-test) @@ -322,3 +326,10 @@ $(objpfx)tst-mallocfork2-mcheck: $(shared-thread-library) $(objpfx)tst-malloc-tcache-leak-malloc-check: $(shared-thread-library) $(objpfx)tst-malloc_info-malloc-check: $(shared-thread-library) $(objpfx)tst-mallocfork2-malloc-check: $(shared-thread-library) + +tst-compathooks-on-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so +tst-compathooks-on-mcheck-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so +tst-compathooks-on-malloc-check-ENV = \ + LD_PRELOAD=$(objpfx)libc_malloc_debug.so +tst-mallocstate-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so +tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so diff --git a/malloc/Versions b/malloc/Versions index 470a940666..c87f6df8ca 100644 --- a/malloc/Versions +++ b/malloc/Versions @@ -98,3 +98,23 @@ libc { __libc_alloc_buffer_create_failure; } } + +# Keep in sync with symbols in libc. +libc_malloc_debug { + GLIBC_2.0 { + calloc; + free; + malloc; + memalign; + pvalloc; + realloc; + valloc; + + } + GLIBC_2.2 { + posix_memalign; + } + GLIBC_2.16 { + aligned_alloc; + } +} diff --git a/malloc/arena.c b/malloc/arena.c index f1693ed48f..9111b49589 100644 --- a/malloc/arena.c +++ b/malloc/arena.c @@ -404,13 +404,6 @@ ptmalloc_init (void) if (s && s[0] != '\0' && s[0] != '0') __malloc_check_init (); #endif - -#if HAVE_MALLOC_INIT_HOOK - void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook); - if (hook != NULL) - (*hook)(); -#endif - __malloc_initialized = 1; } /* Managing heaps and arenas (for concurrent threads) */ diff --git a/malloc/hooks.c b/malloc/hooks.c index 4aa6dadcff..3cd44eeb84 100644 --- a/malloc/hooks.c +++ b/malloc/hooks.c @@ -1,4 +1,4 @@ -/* Malloc implementation for multiple threads without lock contention. +/* Compatibility code for malloc debugging and state management. Copyright (C) 2001-2021 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger <wg@malloc.de>, 2001. @@ -17,6 +17,16 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, see <https://www.gnu.org/licenses/>. */ +#ifndef weak_variable +# define weak_variable weak_function +#endif + +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24) +void (*__malloc_initialize_hook) (void); +compat_symbol (libc, __malloc_initialize_hook, + __malloc_initialize_hook, GLIBC_2_0); +#endif + #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34) void weak_variable (*__after_morecore_hook) (void) = NULL; compat_symbol (libc, __after_morecore_hook, __after_morecore_hook, GLIBC_2_0); @@ -24,32 +34,64 @@ void *(*__morecore)(ptrdiff_t); compat_symbol (libc, __morecore, __morecore, GLIBC_2_0); #endif +static void *malloc_hook_ini (size_t, const void *) __THROW; +static void *realloc_hook_ini (void *, size_t, const void *) __THROW; +static void *memalign_hook_ini (size_t, size_t, const void *) __THROW; + +void weak_variable (*__free_hook) (void *, const void *) = NULL; +void *weak_variable (*__malloc_hook) + (size_t, const void *) = malloc_hook_ini; +void *weak_variable (*__realloc_hook) + (void *, size_t, const void *) = realloc_hook_ini; +void *weak_variable (*__memalign_hook) + (size_t, size_t, const void *) = memalign_hook_ini; + /* Hooks for debugging versions. The initial hooks just call the initialization routine, then do the normal work. */ -static void * -malloc_hook_ini (size_t sz, const void *caller) +/* These hooks will get executed only through the interposed allocator + functions in libc_malloc_debug.so. This means that the calls to malloc, + realloc, etc. will lead back into the interposed functions, which is what we + want. + + These initial hooks are assumed to be called in a single-threaded context, + so it is safe to reset all hooks at once upon initialization. */ + +static void +generic_hook_ini (void) { __malloc_hook = NULL; + __realloc_hook = NULL; + __memalign_hook = NULL; ptmalloc_init (); - return __libc_malloc (sz); + +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24) + void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook); + if (hook != NULL) + (*hook)(); +#endif + __malloc_initialized = 1; +} + +static void * +malloc_hook_ini (size_t sz, const void *caller) +{ + generic_hook_ini (); + return malloc (sz); } static void * realloc_hook_ini (void *ptr, size_t sz, const void *caller) { - __malloc_hook = NULL; - __realloc_hook = NULL; - ptmalloc_init (); - return __libc_realloc (ptr, sz); + generic_hook_ini (); + return realloc (ptr, sz); } static void * memalign_hook_ini (size_t alignment, size_t sz, const void *caller) { - __memalign_hook = NULL; - ptmalloc_init (); - return __libc_memalign (alignment, sz); + generic_hook_ini (); + return memalign (alignment, sz); } #include "malloc-check.c" diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c new file mode 100644 index 0000000000..41dfcd3369 --- /dev/null +++ b/malloc/malloc-debug.c @@ -0,0 +1,189 @@ +/* Malloc debug DSO. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see <https://www.gnu.org/licenses/>. */ + +#include <atomic.h> +#include <libc-symbols.h> +#include <shlib-compat.h> +#include <string.h> +#include <unistd.h> +#include <sys/param.h> + +/* Support only the glibc allocators. */ +extern void *__libc_malloc (size_t); +extern void __libc_free (void *); +extern void *__libc_realloc (void *, size_t); +extern void *__libc_memalign (size_t, size_t); +extern void *__libc_valloc (size_t); +extern void *__libc_pvalloc (size_t); +extern void *__libc_calloc (size_t, size_t); + +#define DEBUG_FN(fn) \ + static __typeof (__libc_ ## fn) __debug_ ## fn + +DEBUG_FN(malloc); +DEBUG_FN(free); +DEBUG_FN(realloc); +DEBUG_FN(memalign); +DEBUG_FN(valloc); +DEBUG_FN(pvalloc); +DEBUG_FN(calloc); + +extern void (*__free_hook) (void *, const void *); +compat_symbol_reference (libc, __free_hook, __free_hook, GLIBC_2_0); +extern void * (*__malloc_hook) (size_t, const void *); +compat_symbol_reference (libc, __malloc_hook, __malloc_hook, GLIBC_2_0); +extern void * (*__realloc_hook) (void *, size_t, const void *); +compat_symbol_reference (libc, __realloc_hook, __realloc_hook, GLIBC_2_0); +extern void * (*__memalign_hook) (size_t, size_t, const void *); +compat_symbol_reference (libc, __memalign_hook, __memalign_hook, GLIBC_2_0); + +static size_t pagesize; + +/* The allocator functions. */ + +static void * +__debug_malloc (size_t bytes) +{ + void *(*hook) (size_t, const void *) = atomic_forced_read (__malloc_hook); + if (__builtin_expect (hook != NULL, 0)) + return (*hook)(bytes, RETURN_ADDRESS (0)); + + return __libc_malloc (bytes); +} +strong_alias (__debug_malloc, malloc) + +static void +__debug_free (void *mem) +{ + void (*hook) (void *, const void *) = atomic_forced_read (__free_hook); + if (__builtin_expect (hook != NULL, 0)) + { + (*hook)(mem, RETURN_ADDRESS (0)); + return; + } + __libc_free (mem); +} +strong_alias (__debug_free, free) + +static void * +__debug_realloc (void *oldmem, size_t bytes) +{ + void *(*hook) (void *, size_t, const void *) = + atomic_forced_read (__realloc_hook); + if (__builtin_expect (hook != NULL, 0)) + return (*hook)(oldmem, bytes, RETURN_ADDRESS (0)); + + return __libc_realloc (oldmem, bytes); +} +strong_alias (__debug_realloc, realloc) + +static void * +_debug_mid_memalign (size_t alignment, size_t bytes, const void *address) +{ + void *(*hook) (size_t, size_t, const void *) = + atomic_forced_read (__memalign_hook); + if (__builtin_expect (hook != NULL, 0)) + return (*hook)(alignment, bytes, address); + + return __libc_memalign (alignment, bytes); +} + +static void * +__debug_memalign (size_t alignment, size_t bytes) +{ + return _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0)); +} +strong_alias (__debug_memalign, memalign) +strong_alias (__debug_memalign, aligned_alloc) + +static void * +__debug_pvalloc (size_t bytes) +{ + size_t rounded_bytes; + + if (!pagesize) + pagesize = sysconf (_SC_PAGESIZE); + + /* ALIGN_UP with overflow check. */ + if (__glibc_unlikely (__builtin_add_overflow (bytes, + pagesize - 1, + &rounded_bytes))) + { + errno = ENOMEM; + return NULL; + } + rounded_bytes = rounded_bytes & -(pagesize - 1); + + return _debug_mid_memalign (pagesize, rounded_bytes, RETURN_ADDRESS (0)); +} +strong_alias (__debug_pvalloc, pvalloc) + +static void * +__debug_valloc (size_t bytes) +{ + if (!pagesize) + pagesize = sysconf (_SC_PAGESIZE); + + return _debug_mid_memalign (pagesize, bytes, RETURN_ADDRESS (0)); +} +strong_alias (__debug_valloc, valloc) + +static int +__debug_posix_memalign (void **memptr, size_t alignment, size_t bytes) +{ + /* Test whether the SIZE argument is valid. It must be a power of + two multiple of sizeof (void *). */ + if (alignment % sizeof (void *) != 0 + || !powerof2 (alignment / sizeof (void *)) + || alignment == 0) + return EINVAL; + + *memptr = _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0)); + + if (*memptr == NULL) + return ENOMEM; + + return 0; +} +strong_alias (__debug_posix_memalign, posix_memalign) + +static void * +__debug_calloc (size_t nmemb, size_t size) +{ + void *(*hook) (size_t, const void *) = atomic_forced_read (__malloc_hook); + if (__builtin_expect (hook != NULL, 0)) + { + size_t bytes; + + if (__glibc_unlikely (__builtin_mul_overflow (nmemb, size, &bytes))) + { + errno = ENOMEM; + return NULL; + } + + void *mem = (*hook)(bytes, RETURN_ADDRESS (0)); + + if (mem != NULL) + memset (mem, 0, bytes); + + return mem; + } + + return __libc_calloc (nmemb, size); +} +strong_alias (__debug_calloc, calloc) diff --git a/malloc/malloc.c b/malloc/malloc.c index 6e8fa9e424..cf71314b2b 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -573,16 +573,6 @@ tag_at (void *ptr) #define HAVE_MREMAP 0 #endif -/* We may need to support __malloc_initialize_hook for backwards - compatibility. */ - -#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24) -# define HAVE_MALLOC_INIT_HOOK 1 -#else -# define HAVE_MALLOC_INIT_HOOK 0 -#endif - - /* This version of malloc supports the standard SVID/XPG mallinfo routine that returns a struct containing usage properties and @@ -2008,38 +1998,6 @@ static void malloc_consolidate (mstate); /* -------------- Early definitions for debugging hooks ---------------- */ -/* Define and initialize the hook variables. These weak definitions must - appear before any use of the variables in a function (arena.c uses one). */ -#ifndef weak_variable -/* In GNU libc we want the hook variables to be weak definitions to - avoid a problem with Emacs. */ -# define weak_variable weak_function -#endif - -/* Forward declarations. */ -static void *malloc_hook_ini (size_t sz, - const void *caller) __THROW; -static void *realloc_hook_ini (void *ptr, size_t sz, - const void *caller) __THROW; -static void *memalign_hook_ini (size_t alignment, size_t sz, - const void *caller) __THROW; - -#if HAVE_MALLOC_INIT_HOOK -void (*__malloc_initialize_hook) (void); -compat_symbol (libc, __malloc_initialize_hook, - __malloc_initialize_hook, GLIBC_2_0); -#endif - -void weak_variable (*__free_hook) (void *__ptr, - const void *) = NULL; -void *weak_variable (*__malloc_hook) - (size_t __size, const void *) = malloc_hook_ini; -void *weak_variable (*__realloc_hook) - (void *__ptr, size_t __size, const void *) - = realloc_hook_ini; -void *weak_variable (*__memalign_hook) - (size_t __alignment, size_t __size, const void *) - = memalign_hook_ini; /* This function is called from the arena shutdown hook, to free the thread cache (if it exists). */ static void tcache_thread_shutdown (void); @@ -3237,10 +3195,8 @@ __libc_malloc (size_t bytes) _Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2, "PTRDIFF_MAX is not more than half of SIZE_MAX"); - void *(*hook) (size_t, const void *) - = atomic_forced_read (__malloc_hook); - if (__builtin_expect (hook != NULL, 0)) - return (*hook)(bytes, RETURN_ADDRESS (0)); + if (__malloc_initialized < 0) + ptmalloc_init (); #if USE_TCACHE /* int_free also calls request2size, be careful to not pad twice. */ size_t tbytes; @@ -3301,14 +3257,6 @@ __libc_free (void *mem) mstate ar_ptr; mchunkptr p; /* chunk corresponding to mem */ - void (*hook) (void *, const void *) - = atomic_forced_read (__free_hook); - if (__builtin_expect (hook != NULL, 0)) - { - (*hook)(mem, RETURN_ADDRESS (0)); - return; - } - if (mem == 0) /* free(0) has no effect */ return; @@ -3360,10 +3308,8 @@ __libc_realloc (void *oldmem, size_t bytes) void *newp; /* chunk to return */ - void *(*hook) (void *, size_t, const void *) = - atomic_forced_read (__realloc_hook); - if (__builtin_expect (hook != NULL, 0)) - return (*hook)(oldmem, bytes, RETURN_ADDRESS (0)); + if (__malloc_initialized < 0) + ptmalloc_init (); #if REALLOC_ZERO_BYTES_FREES if (bytes == 0 && oldmem != NULL) @@ -3498,6 +3444,9 @@ libc_hidden_def (__libc_realloc) void * __libc_memalign (size_t alignment, size_t bytes) { + if (__malloc_initialized < 0) + ptmalloc_init (); + void *address = RETURN_ADDRESS (0); return _mid_memalign (alignment, bytes, address); } @@ -3508,11 +3457,6 @@ _mid_memalign (size_t alignment, size_t bytes, void *address) mstate ar_ptr; void *p; - void *(*hook) (size_t, size_t, const void *) = - atomic_forced_read (__memalign_hook); - if (__builtin_expect (hook != NULL, 0)) - return (*hook)(alignment, bytes, address); - /* If we need less alignment than we give anyway, just relay to malloc. */ if (alignment <= MALLOC_ALIGNMENT) return __libc_malloc (bytes); @@ -3621,16 +3565,8 @@ __libc_calloc (size_t n, size_t elem_size) sz = bytes; - void *(*hook) (size_t, const void *) = - atomic_forced_read (__malloc_hook); - if (__builtin_expect (hook != NULL, 0)) - { - mem = (*hook)(sz, RETURN_ADDRESS (0)); - if (mem == 0) - return 0; - - return memset (mem, 0, sz); - } + if (__malloc_initialized < 0) + ptmalloc_init (); MAYBE_INIT_TCACHE (); @@ -5659,6 +5595,9 @@ __posix_memalign (void **memptr, size_t alignment, size_t size) { void *mem; + if (__malloc_initialized < 0) + ptmalloc_init (); + /* Test whether the SIZE argument is valid. It must be a power of two multiple of sizeof (void *). */ if (alignment % sizeof (void *) != 0 diff --git a/malloc/mcheck.c b/malloc/mcheck.c index d2efcfb742..1e68cedbf5 100644 --- a/malloc/mcheck.c +++ b/malloc/mcheck.c @@ -26,6 +26,7 @@ # include <stdio.h> # include <libintl.h> # include <errno.h> +# include <malloc-internal.h> #endif /* Old hook values. */ diff --git a/malloc/mtrace.c b/malloc/mtrace.c index 6c2c58b706..fb58413d39 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -22,6 +22,7 @@ # define _MALLOC_INTERNAL # include <malloc.h> # include <mcheck.h> +# include <malloc-internal.h> # include <libc-lock.h> #endif diff --git a/malloc/tst-compathooks-off.c b/malloc/tst-compathooks-off.c new file mode 100644 index 0000000000..7b3722d8b3 --- /dev/null +++ b/malloc/tst-compathooks-off.c @@ -0,0 +1,145 @@ +/* Minimal tests to verify libc_malloc_debug.so functionality. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <malloc.h> +#include <shlib-compat.h> +#include <libc-diag.h> + +#include <support/check.h> +#include <support/support.h> + +extern void (*volatile __free_hook) (void *, const void *); +extern void *(*volatile __malloc_hook)(size_t, const void *); +extern void *(*volatile __realloc_hook)(void *, size_t, const void *); +extern void *(*volatile __memalign_hook)(size_t, size_t, const void *); + +int hook_count, call_count; + +DIAG_PUSH_NEEDS_COMMENT; +DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations"); + +void +free_called (void *mem, const void *address) +{ + hook_count++; + __free_hook = NULL; + free (mem); + __free_hook = free_called; +} + +void * +malloc_called (size_t bytes, const void *address) +{ + hook_count++; + __malloc_hook = NULL; + void *mem = malloc (bytes); + __malloc_hook = malloc_called; + return mem; +} + +void * +realloc_called (void *oldptr, size_t bytes, const void *address) +{ + hook_count++; + __realloc_hook = NULL; + void *mem = realloc (oldptr, bytes); + __realloc_hook = realloc_called; + return mem; +} + +void * +calloc_called (size_t n, size_t size, const void *address) +{ + hook_count++; + __malloc_hook = NULL; + void *mem = calloc (n, size); + __malloc_hook = malloc_called; + return mem; +} + +void * +memalign_called (size_t align, size_t size, const void *address) +{ + hook_count++; + __memalign_hook = NULL; + void *mem = memalign (align, size); + __memalign_hook = memalign_called; + return mem; +} + +static void initialize_hooks (void) +{ + __free_hook = free_called; + __malloc_hook = malloc_called; + __realloc_hook = realloc_called; + __memalign_hook = memalign_called; +} +void (*__malloc_initialize_hook) (void) = initialize_hooks; +compat_symbol_reference (libc, __malloc_initialize_hook, + __malloc_initialize_hook, GLIBC_2_0); +compat_symbol_reference (libc, __free_hook, + __free_hook, GLIBC_2_0); +compat_symbol_reference (libc, __malloc_hook, + __malloc_hook, GLIBC_2_0); +compat_symbol_reference (libc, __realloc_hook, + __realloc_hook, GLIBC_2_0); +compat_symbol_reference (libc, __memalign_hook, + __memalign_hook, GLIBC_2_0); + +DIAG_POP_NEEDS_COMMENT; + +static int +do_test (void) +{ + void *p; + p = malloc (0); + TEST_VERIFY_EXIT (p != NULL); + call_count++; + + p = realloc (p, 0); + TEST_VERIFY_EXIT (p == NULL); + call_count++; + + p = calloc (512, 1); + TEST_VERIFY_EXIT (p != NULL); + call_count++; + + free (p); + call_count++; + + p = memalign (0x100, 0x100); + TEST_VERIFY_EXIT (p != NULL); + call_count++; + + free (p); + call_count++; + + printf ("call_count: %d, hook_count: %d\n", call_count, hook_count); + +#ifdef HOOKS_ENABLED + TEST_VERIFY_EXIT (call_count == hook_count); +#else + TEST_VERIFY_EXIT (hook_count == 0); +#endif + + exit (0); +} + +#include <support/test-driver.c> diff --git a/malloc/tst-compathooks-on.c b/malloc/tst-compathooks-on.c new file mode 100644 index 0000000000..4da183687a --- /dev/null +++ b/malloc/tst-compathooks-on.c @@ -0,0 +1,2 @@ +#define HOOKS_ENABLED 1 +#include "tst-compathooks-off.c" diff --git a/malloc/tst-malloc-usable-static-tunables.c b/malloc/tst-malloc-usable-static-tunables.c deleted file mode 100644 index 8907db01a5..0000000000 --- a/malloc/tst-malloc-usable-static-tunables.c +++ /dev/null @@ -1 +0,0 @@ -#include <malloc/tst-malloc-usable.c> diff --git a/malloc/tst-malloc-usable-static.c b/malloc/tst-malloc-usable-static.c deleted file mode 100644 index 8907db01a5..0000000000 --- a/malloc/tst-malloc-usable-static.c +++ /dev/null @@ -1 +0,0 @@ -#include <malloc/tst-malloc-usable.c> diff --git a/malloc/tst-mtrace.sh b/malloc/tst-mtrace.sh index 9295683aff..a830204d5e 100755 --- a/malloc/tst-mtrace.sh +++ b/malloc/tst-mtrace.sh @@ -30,6 +30,7 @@ trap "rm -f ${common_objpfx}malloc/tst-mtrace.leak; exit 1" 1 2 15 ${test_program_prefix_before_env} \ ${run_program_env} \ MALLOC_TRACE=${common_objpfx}malloc/tst-mtrace.leak \ +LD_PRELOAD=${common_objpfx}malloc/libc_malloc_debug.so \ ${test_program_prefix_after_env} \ ${common_objpfx}malloc/tst-mtrace || status=1 |