1# Copyright (C) 1991-2022 Free Software Foundation, Inc.
2# This file is part of the GNU C Library.
3
4# The GNU C Library is free software; you can redistribute it and/or
5# modify it under the terms of the GNU Lesser General Public
6# License as published by the Free Software Foundation; either
7# version 2.1 of the License, or (at your option) any later version.
8
9# The GNU C Library is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12# Lesser General Public License for more details.
13
14# You should have received a copy of the GNU Lesser General Public
15# License along with the GNU C Library; if not, see
16# <https://www.gnu.org/licenses/>.
17
18#
19#	Makefile for malloc routines
20#
21subdir	:= malloc
22
23include ../Makeconfig
24
25dist-headers := malloc.h
26headers := $(dist-headers) obstack.h mcheck.h
27tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
28	 tst-malloc-check tst-mallocfork tst-trim1 \
29	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
30	 tst-pvalloc tst-pvalloc-fortify tst-memalign tst-mallopt \
31	 tst-malloc-backtrace tst-malloc-thread-exit \
32	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
33	 tst-mallocfork2 \
34	 tst-mallocfork3 \
35	 tst-interpose-nothread \
36	 tst-interpose-thread \
37	 tst-alloc_buffer \
38	 tst-free-errno \
39	 tst-malloc-tcache-leak \
40	 tst-malloc_info tst-mallinfo2 \
41	 tst-malloc-too-large \
42	 tst-malloc-stats-cancellation \
43	 tst-tcfree1 tst-tcfree2 tst-tcfree3 \
44	 tst-safe-linking \
45	 tst-mallocalign1 \
46
47tests-static := \
48	 tst-interpose-static-nothread \
49	 tst-interpose-static-thread
50
51# Test for the malloc_set_state symbol removed in glibc 2.25.
52ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
53tests += tst-mallocstate tst-compathooks-off tst-compathooks-on
54endif
55
56tests-internal := tst-scratch_buffer
57
58# The dynarray framework is only available inside glibc.
59tests-internal += \
60	 tst-dynarray \
61	 tst-dynarray-fail \
62	 tst-dynarray-at-fail \
63
64ifneq (no,$(have-tunables))
65tests += tst-malloc-usable-tunables tst-mxfast
66endif
67
68tests += $(tests-static)
69test-srcs = tst-mtrace
70
71# These tests either are run with MALLOC_CHECK_=3 by default or do not work
72# with MALLOC_CHECK_=3 because they expect a specific failure.
73tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \
74	tst-mxfast tst-safe-linking \
75	tst-compathooks-off tst-compathooks-on
76
77# Run all tests with MALLOC_CHECK_=3
78tests-malloc-check = $(filter-out $(tests-exclude-malloc-check) \
79				  $(tests-static),$(tests))
80
81# Run all tests with GLIBC_TUNABLES=glibc.malloc.hugetlb={1,2} which check
82# the Transparent Huge Pages support (1) or automatic huge page support (2).
83# We need exclude some tests that define the ENV vars.
84tests-exclude-hugetlb1 = \
85	tst-compathooks-off \
86	tst-compathooks-on \
87	tst-interpose-nothread \
88	tst-interpose-thread \
89	tst-interpose-static-nothread \
90	tst-interpose-static-thread \
91	tst-malloc-usable \
92	tst-malloc-usable-tunables \
93	tst-mallocstate
94# The tst-free-errno relies on the used malloc page size to mmap an
95# overlapping region.
96tests-exclude-hugetlb2 = \
97	$(tests-exclude-hugetlb1) \
98	tst-free-errno
99tests-malloc-hugetlb1 = \
100	$(filter-out $(tests-exclude-hugetlb1), $(tests))
101tests-malloc-hugetlb2 = \
102	$(filter-out $(tests-exclude-hugetlb2), $(tests))
103
104# -lmcheck needs __malloc_initialize_hook, which was deprecated in 2.24.
105ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
106# Tests that don't play well with mcheck.  They are either bugs in mcheck or
107# the tests expect specific internal behavior that is changed due to linking to
108# libmcheck.a.
109tests-exclude-mcheck = tst-mallocstate \
110	tst-safe-linking \
111	tst-malloc-backtrace \
112	tst-malloc-fork-deadlock \
113	tst-malloc-stats-cancellation \
114	tst-malloc-tcache-leak \
115	tst-malloc-thread-exit \
116	tst-malloc-thread-fail \
117	tst-malloc-usable-tunables \
118	tst-malloc_info \
119	tst-compathooks-off tst-compathooks-on \
120	tst-mxfast
121
122tests-mcheck = $(filter-out $(tests-exclude-mcheck) $(tests-static), $(tests))
123endif
124
125routines = malloc mcheck mtrace obstack reallocarray \
126  scratch_buffer_dupfree \
127  scratch_buffer_grow scratch_buffer_grow_preserve \
128  scratch_buffer_set_array_size \
129  dynarray_at_failure \
130  dynarray_emplace_enlarge \
131  dynarray_finalize \
132  dynarray_resize \
133  dynarray_resize_clear \
134  alloc_buffer_alloc_array \
135  alloc_buffer_allocate \
136  alloc_buffer_copy_bytes  \
137  alloc_buffer_copy_string \
138  alloc_buffer_create_failure \
139
140install-lib := libmcheck.a
141non-lib.a := libmcheck.a
142
143# Additional libraries.
144extra-libs = libmemusage libc_malloc_debug
145extra-libs-others = $(extra-libs)
146
147# Helper objects for some tests.
148extra-test-objs += \
149  tst-interpose-aux-nothread.o \
150  tst-interpose-aux-thread.o \
151
152test-extras = \
153  tst-interpose-aux-nothread \
154  tst-interpose-aux-thread \
155
156libmemusage-routines = memusage
157libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
158
159libc_malloc_debug-routines = malloc-debug $(sysdep_malloc_debug_routines)
160libc_malloc_debug-inhibit-o = $(filter-out .os,$(object-suffixes))
161
162$(objpfx)tst-malloc-backtrace: $(shared-thread-library)
163$(objpfx)tst-malloc-thread-exit: $(shared-thread-library)
164$(objpfx)tst-malloc-thread-fail: $(shared-thread-library)
165$(objpfx)tst-mallocfork3: $(shared-thread-library)
166$(objpfx)tst-mallocfork3-mcheck: $(shared-thread-library)
167$(objpfx)tst-malloc-fork-deadlock: $(shared-thread-library)
168$(objpfx)tst-malloc-stats-cancellation: $(shared-thread-library)
169$(objpfx)tst-malloc-backtrace-mcheck: $(shared-thread-library)
170$(objpfx)tst-malloc-thread-exit-mcheck: $(shared-thread-library)
171$(objpfx)tst-malloc-thread-fail-mcheck: $(shared-thread-library)
172$(objpfx)tst-malloc-fork-deadlock-mcheck: $(shared-thread-library)
173$(objpfx)tst-malloc-stats-cancellation-mcheck: $(shared-thread-library)
174$(objpfx)tst-mallocfork3-malloc-check: $(shared-thread-library)
175$(objpfx)tst-malloc-backtrace-malloc-check: $(shared-thread-library)
176$(objpfx)tst-malloc-thread-exit-malloc-check: $(shared-thread-library)
177$(objpfx)tst-malloc-thread-fail-malloc-check: $(shared-thread-library)
178$(objpfx)tst-malloc-fork-deadlock-malloc-check: $(shared-thread-library)
179$(objpfx)tst-malloc-stats-cancellation-malloc-check: $(shared-thread-library)
180$(objpfx)tst-malloc-thread-exit-malloc-hugetlb1: $(shared-thread-library)
181$(objpfx)tst-malloc-thread-fail-malloc-hugetlb1: $(shared-thread-library)
182$(objpfx)tst-mallocfork2-malloc-hugetlb1: $(shared-thread-library)
183$(objpfx)tst-mallocfork3-malloc-hugetlb1: $(shared-thread-library)
184$(objpfx)tst-malloc-fork-deadlock-malloc-hugetlb1: $(shared-thread-library)
185$(objpfx)tst-malloc-stats-cancellation-malloc-hugetlb1: $(shared-thread-library)
186$(objpfx)tst-malloc-thread-exit-malloc-hugetlb2: $(shared-thread-library)
187$(objpfx)tst-malloc-thread-fail-malloc-hugetlb2: $(shared-thread-library)
188$(objpfx)tst-mallocfork2-malloc-hugetlb2: $(shared-thread-library)
189$(objpfx)tst-mallocfork3-malloc-hugetlb2: $(shared-thread-library)
190$(objpfx)tst-malloc-fork-deadlock-malloc-hugetlb2: $(shared-thread-library)
191$(objpfx)tst-malloc-stats-cancellation-malloc-hugetlb2: $(shared-thread-library)
192
193# These should be removed by `make clean'.
194extra-objs = mcheck-init.o libmcheck.a
195others-extras = mcheck-init.o
196
197# Include the cleanup handler.
198aux := set-freeres thread-freeres
199
200# The Perl script to analyze the output of the mtrace functions.
201ifneq ($(PERL),no)
202install-bin-script = mtrace
203generated += mtrace
204
205# The Perl script will print addresses and to do this nicely we must know
206# whether we are on a 32 or 64 bit machine.
207ifneq ($(findstring wordsize-32,$(config-sysdirs)),)
208address-width=10
209else
210address-width=18
211endif
212endif
213
214# Unless we get a test for the availability of libgd which also works
215# for cross-compiling we disable the memusagestat generation in this
216# situation.
217ifneq ($(cross-compiling),yes)
218# If the gd library is available we build the `memusagestat' program.
219ifneq ($(LIBGD),no)
220others: $(objpfx)memusage
221others += memusagestat
222install-bin = memusagestat
223install-bin-script += memusage
224generated += memusagestat memusage
225extra-objs += memusagestat.o
226
227# The configure.ac check for libgd and its headers did not use $SYSINCLUDES.
228# The directory specified by --with-headers usually contains only the basic
229# kernel interface headers, not something like libgd.  So the simplest thing
230# is to presume that the standard system headers will be ok for this file.
231$(objpfx)memusagestat.o: sysincludes = # nothing
232endif
233endif
234
235# Another goal which can be used to override the configure decision.
236.PHONY: do-memusagestat
237do-memusagestat: $(objpfx)memusagestat
238
239memusagestat-modules = memusagestat
240
241cpp-srcs-left := $(memusagestat-modules)
242lib := memusagestat
243include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
244
245LDLIBS-memusagestat = $(libgd-LDFLAGS) -lgd -lpng -lz -lm
246
247ifeq ($(run-built-tests),yes)
248ifeq (yes,$(build-shared))
249ifneq ($(PERL),no)
250tests-special += $(objpfx)tst-mtrace.out
251tests-special += $(objpfx)tst-dynarray-mem.out
252tests-special += $(objpfx)tst-dynarray-fail-mem.out
253endif
254endif
255endif
256
257include ../Rules
258
259CFLAGS-mcheck-init.c += $(PIC-ccflag)
260CFLAGS-obstack.c += $(uses-callbacks)
261
262$(objpfx)libmcheck.a: $(objpfx)mcheck-init.o
263	-rm -f $@
264	$(patsubst %/,cd % &&,$(objpfx)) \
265	$(LN_S) $(<F) $(@F)
266
267lib: $(objpfx)libmcheck.a
268
269ifeq ($(run-built-tests),yes)
270ifeq (yes,$(build-shared))
271ifneq ($(PERL),no)
272$(objpfx)tst-mtrace.out: tst-mtrace.sh $(objpfx)tst-mtrace
273	$(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
274		 '$(run-program-env)' '$(test-program-prefix-after-env)'; \
275	$(evaluate-test)
276endif
277endif
278endif
279
280tst-malloc-check-ENV = MALLOC_CHECK_=3 \
281		       LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
282tst-malloc-usable-ENV = MALLOC_CHECK_=3 \
283		       LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
284tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 \
285				 LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
286
287tst-mxfast-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=0:glibc.malloc.mxfast=0
288
289CPPFLAGS-malloc-debug.c += -DUSE_TCACHE=0
290ifeq ($(experimental-malloc),yes)
291CPPFLAGS-malloc.c += -DUSE_TCACHE=1
292else
293CPPFLAGS-malloc.c += -DUSE_TCACHE=0
294endif
295# Uncomment this for test releases.  For public releases it is too expensive.
296#CPPFLAGS-malloc.o += -DMALLOC_DEBUG=1
297
298sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,')
299
300$(objpfx)mtrace: mtrace.pl
301	rm -f $@.new
302	sed -e 's|@PERL@|$(PERL)|' -e 's|@XXX@|$(address-width)|' \
303	    -e 's|@VERSION@|$(version)|' \
304	    -e 's|@PKGVERSION@|$(PKGVERSION)|' \
305	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \
306	&& rm -f $@ && mv $@.new $@ && chmod +x $@
307
308$(objpfx)memusage: memusage.sh
309	rm -f $@.new
310	sed -e 's|@VERSION@|$(version)|' -e 's|@SLIBDIR@|$(sLIBdir)|' \
311	    -e 's|@BINDIR@|$(bindir)|' -e 's|@PKGVERSION@|$(PKGVERSION)|' \
312	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \
313	&& rm -f $@ && mv $@.new $@ && chmod +x $@
314
315# Compile the tests with a flag which suppresses the mallopt call in
316# the test skeleton.
317$(tests:%=$(objpfx)%.o): CPPFLAGS += -DTEST_NO_MALLOPT
318
319$(objpfx)tst-interpose-nothread: $(objpfx)tst-interpose-aux-nothread.o
320$(objpfx)tst-interpose-nothread-mcheck: $(objpfx)tst-interpose-aux-nothread.o
321$(objpfx)tst-interpose-nothread-malloc-check: \
322	$(objpfx)tst-interpose-aux-nothread.o
323$(objpfx)tst-interpose-thread: \
324  $(objpfx)tst-interpose-aux-thread.o $(shared-thread-library)
325$(objpfx)tst-interpose-thread-mcheck: \
326  $(objpfx)tst-interpose-aux-thread.o $(shared-thread-library)
327$(objpfx)tst-interpose-thread-malloc-check: \
328  $(objpfx)tst-interpose-aux-thread.o $(shared-thread-library)
329$(objpfx)tst-interpose-static-nothread: $(objpfx)tst-interpose-aux-nothread.o
330$(objpfx)tst-interpose-static-thread: \
331  $(objpfx)tst-interpose-aux-thread.o $(static-thread-library)
332
333tst-dynarray-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace \
334		   LD_PRELOAD=$(objpfx)libc_malloc_debug.so
335$(objpfx)tst-dynarray-mem.out: $(objpfx)tst-dynarray.out
336	$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray.mtrace > $@; \
337	$(evaluate-test)
338
339tst-dynarray-fail-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace \
340			LD_PRELOAD=$(objpfx)libc_malloc_debug.so
341$(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out
342	$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray-fail.mtrace > $@; \
343	$(evaluate-test)
344
345$(objpfx)tst-malloc-tcache-leak: $(shared-thread-library)
346$(objpfx)tst-malloc_info: $(shared-thread-library)
347$(objpfx)tst-mallocfork2: $(shared-thread-library)
348$(objpfx)tst-malloc-tcache-leak-mcheck: $(shared-thread-library)
349$(objpfx)tst-malloc_info-mcheck: $(shared-thread-library)
350$(objpfx)tst-mallocfork2-mcheck: $(shared-thread-library)
351$(objpfx)tst-malloc-tcache-leak-malloc-check: $(shared-thread-library)
352$(objpfx)tst-malloc_info-malloc-check: $(shared-thread-library)
353$(objpfx)tst-mallocfork2-malloc-check: $(shared-thread-library)
354$(objpfx)tst-malloc-tcache-leak-malloc-hugetlb1: $(shared-thread-library)
355$(objpfx)tst-malloc-tcache-leak-malloc-hugetlb2: $(shared-thread-library)
356$(objpfx)tst-malloc_info-malloc-hugetlb1: $(shared-thread-library)
357$(objpfx)tst-malloc_info-malloc-hugetlb2: $(shared-thread-library)
358
359tst-compathooks-on-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
360tst-compathooks-on-mcheck-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
361tst-compathooks-on-malloc-check-ENV = \
362	LD_PRELOAD=$(objpfx)libc_malloc_debug.so
363tst-mallocstate-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
364tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
365
366# The test needs malloc_get_state/malloc_set_state which is in
367# libc_malloc_debug.so.
368$(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
369$(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
370