]> git.ipfire.org Git - thirdparty/glibc.git/blob - malloc/malloc-debug.c
aarch64/fpu: Add vector variants of atanh
[thirdparty/glibc.git] / malloc / malloc-debug.c
1 /* Malloc debug DSO.
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
3 Copyright The GNU Toolchain Authors.
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If
18 not, see <https://www.gnu.org/licenses/>. */
19
20 #include <atomic.h>
21 #include <libc-symbols.h>
22 #include <shlib-compat.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/param.h>
26
27 /* Support only the glibc allocators. */
28 extern void *__libc_malloc (size_t);
29 extern void __libc_free (void *);
30 extern void *__libc_realloc (void *, size_t);
31 extern void *__libc_memalign (size_t, size_t);
32 extern void *__libc_valloc (size_t);
33 extern void *__libc_pvalloc (size_t);
34 extern void *__libc_calloc (size_t, size_t);
35
36 #define DEBUG_FN(fn) \
37 static __typeof (__libc_ ## fn) __debug_ ## fn
38
39 DEBUG_FN(malloc);
40 DEBUG_FN(free);
41 DEBUG_FN(realloc);
42 DEBUG_FN(memalign);
43 DEBUG_FN(valloc);
44 DEBUG_FN(pvalloc);
45 DEBUG_FN(calloc);
46
47 static int debug_initialized = -1;
48
49 enum malloc_debug_hooks
50 {
51 MALLOC_NONE_HOOK = 0,
52 MALLOC_MCHECK_HOOK = 1 << 0, /* mcheck() */
53 MALLOC_MTRACE_HOOK = 1 << 1, /* mtrace() */
54 MALLOC_CHECK_HOOK = 1 << 2, /* MALLOC_CHECK_ or glibc.malloc.check. */
55 };
56 static unsigned __malloc_debugging_hooks;
57
58 static __always_inline bool
59 __is_malloc_debug_enabled (enum malloc_debug_hooks flag)
60 {
61 return __malloc_debugging_hooks & flag;
62 }
63
64 static __always_inline void
65 __malloc_debug_enable (enum malloc_debug_hooks flag)
66 {
67 __malloc_debugging_hooks |= flag;
68 }
69
70 static __always_inline void
71 __malloc_debug_disable (enum malloc_debug_hooks flag)
72 {
73 __malloc_debugging_hooks &= ~flag;
74 }
75
76 #include "mcheck.c"
77 #include "mtrace.c"
78 #include "malloc-check.c"
79
80 #if SHLIB_COMPAT (libc_malloc_debug, GLIBC_2_0, GLIBC_2_24)
81 extern void (*__malloc_initialize_hook) (void);
82 compat_symbol_reference (libc, __malloc_initialize_hook,
83 __malloc_initialize_hook, GLIBC_2_0);
84 #endif
85
86 static void *malloc_hook_ini (size_t, const void *) __THROW;
87 static void *realloc_hook_ini (void *, size_t, const void *) __THROW;
88 static void *memalign_hook_ini (size_t, size_t, const void *) __THROW;
89
90 void (*__free_hook) (void *, const void *) = NULL;
91 void *(*__malloc_hook) (size_t, const void *) = malloc_hook_ini;
92 void *(*__realloc_hook) (void *, size_t, const void *) = realloc_hook_ini;
93 void *(*__memalign_hook) (size_t, size_t, const void *) = memalign_hook_ini;
94
95 /* Hooks for debugging versions. The initial hooks just call the
96 initialization routine, then do the normal work. */
97
98 /* These hooks will get executed only through the interposed allocator
99 functions in libc_malloc_debug.so. This means that the calls to malloc,
100 realloc, etc. will lead back into the interposed functions, which is what we
101 want.
102
103 These initial hooks are assumed to be called in a single-threaded context,
104 so it is safe to reset all hooks at once upon initialization. */
105
106 static void
107 generic_hook_ini (void)
108 {
109 debug_initialized = 0;
110 __malloc_hook = NULL;
111 __realloc_hook = NULL;
112 __memalign_hook = NULL;
113
114 /* malloc check does not quite co-exist with libc malloc, so initialize
115 either on or the other. */
116 if (!initialize_malloc_check ())
117 /* The compiler does not know that these functions are allocators, so it
118 will not try to optimize it away. */
119 __libc_free (__libc_malloc (0));
120
121 #if SHLIB_COMPAT (libc_malloc_debug, GLIBC_2_0, GLIBC_2_24)
122 void (*hook) (void) = __malloc_initialize_hook;
123 if (hook != NULL)
124 (*hook)();
125 #endif
126
127 debug_initialized = 1;
128 }
129
130 static void *
131 malloc_hook_ini (size_t sz, const void *caller)
132 {
133 generic_hook_ini ();
134 return __debug_malloc (sz);
135 }
136
137 static void *
138 realloc_hook_ini (void *ptr, size_t sz, const void *caller)
139 {
140 generic_hook_ini ();
141 return __debug_realloc (ptr, sz);
142 }
143
144 static void *
145 memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
146 {
147 generic_hook_ini ();
148 return __debug_memalign (alignment, sz);
149 }
150
151 static size_t pagesize;
152
153 /* These variables are used for undumping support. Chunked are marked
154 as using mmap, but we leave them alone if they fall into this
155 range. NB: The chunk size for these chunks only includes the
156 initial size field (of SIZE_SZ bytes), there is no trailing size
157 field (unlike with regular mmapped chunks). */
158 static mchunkptr dumped_main_arena_start; /* Inclusive. */
159 static mchunkptr dumped_main_arena_end; /* Exclusive. */
160
161 /* True if the pointer falls into the dumped arena. Use this after
162 chunk_is_mmapped indicates a chunk is mmapped. */
163 #define DUMPED_MAIN_ARENA_CHUNK(p) \
164 ((p) >= dumped_main_arena_start && (p) < dumped_main_arena_end)
165
166 /* The allocator functions. */
167
168 static void *
169 __debug_malloc (size_t bytes)
170 {
171 void *(*hook) (size_t, const void *) = atomic_forced_read (__malloc_hook);
172 if (__builtin_expect (hook != NULL, 0))
173 return (*hook)(bytes, RETURN_ADDRESS (0));
174
175 void *victim = NULL;
176 size_t orig_bytes = bytes;
177 if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
178 || !malloc_mcheck_before (&bytes, &victim)))
179 {
180 victim = (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
181 ? malloc_check (bytes) : __libc_malloc (bytes));
182 }
183 if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
184 victim = malloc_mcheck_after (victim, orig_bytes);
185 if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
186 malloc_mtrace_after (victim, orig_bytes, RETURN_ADDRESS (0));
187
188 return victim;
189 }
190 strong_alias (__debug_malloc, malloc)
191
192 static void
193 __debug_free (void *mem)
194 {
195 void (*hook) (void *, const void *) = atomic_forced_read (__free_hook);
196 if (__builtin_expect (hook != NULL, 0))
197 {
198 (*hook)(mem, RETURN_ADDRESS (0));
199 return;
200 }
201
202 if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
203 mem = free_mcheck (mem);
204
205 if (DUMPED_MAIN_ARENA_CHUNK (mem2chunk (mem)))
206 /* Do nothing. */;
207 else if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
208 free_check (mem);
209 else
210 __libc_free (mem);
211 if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
212 free_mtrace (mem, RETURN_ADDRESS (0));
213 }
214 strong_alias (__debug_free, free)
215
216 static void *
217 __debug_realloc (void *oldmem, size_t bytes)
218 {
219 void *(*hook) (void *, size_t, const void *) =
220 atomic_forced_read (__realloc_hook);
221 if (__builtin_expect (hook != NULL, 0))
222 return (*hook)(oldmem, bytes, RETURN_ADDRESS (0));
223
224 size_t orig_bytes = bytes, oldsize = 0;
225 void *victim = NULL;
226
227 if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
228 || !realloc_mcheck_before (&oldmem, &bytes, &oldsize, &victim)))
229 {
230 mchunkptr oldp = mem2chunk (oldmem);
231
232 /* If this is a faked mmapped chunk from the dumped main arena,
233 always make a copy (and do not free the old chunk). */
234 if (DUMPED_MAIN_ARENA_CHUNK (oldp))
235 {
236 if (bytes == 0 && oldmem != NULL)
237 victim = NULL;
238 else
239 {
240 const INTERNAL_SIZE_T osize = chunksize (oldp);
241 /* Must alloc, copy, free. */
242 victim = __debug_malloc (bytes);
243 /* Copy as many bytes as are available from the old chunk
244 and fit into the new size. NB: The overhead for faked
245 mmapped chunks is only SIZE_SZ, not CHUNK_HDR_SZ as for
246 regular mmapped chunks. */
247 if (victim != NULL)
248 {
249 if (bytes > osize - SIZE_SZ)
250 bytes = osize - SIZE_SZ;
251 memcpy (victim, oldmem, bytes);
252 }
253 }
254 }
255 else if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
256 victim = realloc_check (oldmem, bytes);
257 else
258 victim = __libc_realloc (oldmem, bytes);
259 }
260 if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
261 victim = realloc_mcheck_after (victim, oldmem, orig_bytes,
262 oldsize);
263 if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
264 realloc_mtrace_after (victim, oldmem, orig_bytes, RETURN_ADDRESS (0));
265
266 return victim;
267 }
268 strong_alias (__debug_realloc, realloc)
269
270 static void *
271 _debug_mid_memalign (size_t alignment, size_t bytes, const void *address)
272 {
273 void *(*hook) (size_t, size_t, const void *) =
274 atomic_forced_read (__memalign_hook);
275 if (__builtin_expect (hook != NULL, 0))
276 return (*hook)(alignment, bytes, address);
277
278 void *victim = NULL;
279 size_t orig_bytes = bytes;
280
281 if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
282 || !memalign_mcheck_before (alignment, &bytes, &victim)))
283 {
284 victim = (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
285 ? memalign_check (alignment, bytes)
286 : __libc_memalign (alignment, bytes));
287 }
288 if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && victim != NULL)
289 victim = memalign_mcheck_after (victim, alignment, orig_bytes);
290 if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
291 memalign_mtrace_after (victim, orig_bytes, address);
292
293 return victim;
294 }
295
296 static void *
297 __debug_memalign (size_t alignment, size_t bytes)
298 {
299 return _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0));
300 }
301 strong_alias (__debug_memalign, memalign)
302 static void *
303 __debug_aligned_alloc (size_t alignment, size_t bytes)
304 {
305 if (!powerof2 (alignment) || alignment == 0)
306 return NULL;
307 return _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0));
308 }
309 strong_alias (__debug_aligned_alloc, aligned_alloc)
310
311 static void *
312 __debug_pvalloc (size_t bytes)
313 {
314 size_t rounded_bytes;
315
316 if (!pagesize)
317 pagesize = sysconf (_SC_PAGESIZE);
318
319 /* ALIGN_UP with overflow check. */
320 if (__glibc_unlikely (__builtin_add_overflow (bytes,
321 pagesize - 1,
322 &rounded_bytes)))
323 {
324 errno = ENOMEM;
325 return NULL;
326 }
327 rounded_bytes = rounded_bytes & -(pagesize - 1);
328
329 return _debug_mid_memalign (pagesize, rounded_bytes, RETURN_ADDRESS (0));
330 }
331 strong_alias (__debug_pvalloc, pvalloc)
332
333 static void *
334 __debug_valloc (size_t bytes)
335 {
336 if (!pagesize)
337 pagesize = sysconf (_SC_PAGESIZE);
338
339 return _debug_mid_memalign (pagesize, bytes, RETURN_ADDRESS (0));
340 }
341 strong_alias (__debug_valloc, valloc)
342
343 static int
344 __debug_posix_memalign (void **memptr, size_t alignment, size_t bytes)
345 {
346 /* Test whether the SIZE argument is valid. It must be a power of
347 two multiple of sizeof (void *). */
348 if (alignment % sizeof (void *) != 0
349 || !powerof2 (alignment / sizeof (void *))
350 || alignment == 0)
351 return EINVAL;
352
353 *memptr = _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0));
354
355 if (*memptr == NULL)
356 return ENOMEM;
357
358 return 0;
359 }
360 strong_alias (__debug_posix_memalign, posix_memalign)
361
362 static void *
363 __debug_calloc (size_t nmemb, size_t size)
364 {
365 size_t bytes;
366
367 if (__glibc_unlikely (__builtin_mul_overflow (nmemb, size, &bytes)))
368 {
369 errno = ENOMEM;
370 return NULL;
371 }
372
373 void *(*hook) (size_t, const void *) = atomic_forced_read (__malloc_hook);
374 if (__builtin_expect (hook != NULL, 0))
375 {
376 void *mem = (*hook)(bytes, RETURN_ADDRESS (0));
377
378 if (mem != NULL)
379 memset (mem, 0, bytes);
380
381 return mem;
382 }
383
384 size_t orig_bytes = bytes;
385 void *victim = NULL;
386
387 if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
388 || !malloc_mcheck_before (&bytes, &victim)))
389 {
390 victim = (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)
391 ? malloc_check (bytes) : __libc_malloc (bytes));
392 }
393 if (victim != NULL)
394 {
395 if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
396 victim = malloc_mcheck_after (victim, orig_bytes);
397 memset (victim, 0, orig_bytes);
398 }
399 if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
400 malloc_mtrace_after (victim, orig_bytes, RETURN_ADDRESS (0));
401
402 return victim;
403 }
404 strong_alias (__debug_calloc, calloc)
405
406 size_t
407 malloc_usable_size (void *mem)
408 {
409 if (mem == NULL)
410 return 0;
411
412 if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
413 return mcheck_usable_size (mem);
414 if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
415 return malloc_check_get_size (mem);
416
417 mchunkptr p = mem2chunk (mem);
418 if (DUMPED_MAIN_ARENA_CHUNK (p))
419 return chunksize (p) - SIZE_SZ;
420
421 return musable (mem);
422 }
423
424 #define LIBC_SYMBOL(sym) libc_ ## sym
425 #define SYMHANDLE(sym) sym ## _handle
426
427 #define LOAD_SYM(sym) ({ \
428 static void *SYMHANDLE (sym); \
429 if (SYMHANDLE (sym) == NULL) \
430 SYMHANDLE (sym) = dlsym (RTLD_NEXT, #sym); \
431 SYMHANDLE (sym); \
432 })
433
434 int
435 malloc_info (int options, FILE *fp)
436 {
437 if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
438 return __malloc_info (options, fp);
439
440 int (*LIBC_SYMBOL (malloc_info)) (int, FILE *) = LOAD_SYM (malloc_info);
441 if (LIBC_SYMBOL (malloc_info) == NULL)
442 return -1;
443
444 return LIBC_SYMBOL (malloc_info) (options, fp);
445 }
446
447 int
448 mallopt (int param_number, int value)
449 {
450 if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
451 return __libc_mallopt (param_number, value);
452
453 int (*LIBC_SYMBOL (mallopt)) (int, int) = LOAD_SYM (mallopt);
454 if (LIBC_SYMBOL (mallopt) == NULL)
455 return 0;
456
457 return LIBC_SYMBOL (mallopt) (param_number, value);
458 }
459
460 void
461 malloc_stats (void)
462 {
463 if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
464 return __malloc_stats ();
465
466 void (*LIBC_SYMBOL (malloc_stats)) (void) = LOAD_SYM (malloc_stats);
467 if (LIBC_SYMBOL (malloc_stats) == NULL)
468 return;
469
470 LIBC_SYMBOL (malloc_stats) ();
471 }
472
473 struct mallinfo2
474 mallinfo2 (void)
475 {
476 if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
477 return __libc_mallinfo2 ();
478
479 struct mallinfo2 (*LIBC_SYMBOL (mallinfo2)) (void) = LOAD_SYM (mallinfo2);
480 if (LIBC_SYMBOL (mallinfo2) == NULL)
481 {
482 struct mallinfo2 ret = {0};
483 return ret;
484 }
485
486 return LIBC_SYMBOL (mallinfo2) ();
487 }
488
489 struct mallinfo
490 mallinfo (void)
491 {
492 if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
493 return __libc_mallinfo ();
494
495 struct mallinfo (*LIBC_SYMBOL (mallinfo)) (void) = LOAD_SYM (mallinfo);
496 if (LIBC_SYMBOL (mallinfo) == NULL)
497 {
498 struct mallinfo ret = {0};
499 return ret;
500 }
501
502 return LIBC_SYMBOL (mallinfo) ();
503 }
504
505 int
506 malloc_trim (size_t s)
507 {
508 if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
509 return __malloc_trim (s);
510
511 int (*LIBC_SYMBOL (malloc_trim)) (size_t) = LOAD_SYM (malloc_trim);
512 if (LIBC_SYMBOL (malloc_trim) == NULL)
513 return 0;
514
515 return LIBC_SYMBOL (malloc_trim) (s);
516 }
517
518 #if SHLIB_COMPAT (libc_malloc_debug, GLIBC_2_0, GLIBC_2_25)
519
520 /* Support for restoring dumped heaps contained in historic Emacs
521 executables. The heap saving feature (malloc_get_state) is no
522 longer implemented in this version of glibc, but we have a heap
523 rewriter in malloc_set_state which transforms the heap into a
524 version compatible with current malloc. */
525
526 #define MALLOC_STATE_MAGIC 0x444c4541l
527 #define MALLOC_STATE_VERSION (0 * 0x100l + 5l) /* major*0x100 + minor */
528
529 struct malloc_save_state
530 {
531 long magic;
532 long version;
533 mbinptr av[NBINS * 2 + 2];
534 char *sbrk_base;
535 int sbrked_mem_bytes;
536 unsigned long trim_threshold;
537 unsigned long top_pad;
538 unsigned int n_mmaps_max;
539 unsigned long mmap_threshold;
540 int check_action;
541 unsigned long max_sbrked_mem;
542 unsigned long max_total_mem; /* Always 0, for backwards compatibility. */
543 unsigned int n_mmaps;
544 unsigned int max_n_mmaps;
545 unsigned long mmapped_mem;
546 unsigned long max_mmapped_mem;
547 int using_malloc_checking;
548 unsigned long max_fast;
549 unsigned long arena_test;
550 unsigned long arena_max;
551 unsigned long narenas;
552 };
553
554 /* Dummy implementation which always fails. We need to provide this
555 symbol so that existing Emacs binaries continue to work with
556 BIND_NOW. */
557 void *
558 malloc_get_state (void)
559 {
560 __set_errno (ENOSYS);
561 return NULL;
562 }
563 compat_symbol (libc_malloc_debug, malloc_get_state, malloc_get_state,
564 GLIBC_2_0);
565
566 int
567 malloc_set_state (void *msptr)
568 {
569 struct malloc_save_state *ms = (struct malloc_save_state *) msptr;
570
571 if (ms->magic != MALLOC_STATE_MAGIC)
572 return -1;
573
574 /* Must fail if the major version is too high. */
575 if ((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl))
576 return -2;
577
578 if (debug_initialized == 1)
579 return -1;
580
581 bool check_was_enabled = __is_malloc_debug_enabled (MALLOC_CHECK_HOOK);
582
583 /* It's not too late, so disable MALLOC_CHECK_ and all of the hooks. */
584 __malloc_hook = NULL;
585 __realloc_hook = NULL;
586 __free_hook = NULL;
587 __memalign_hook = NULL;
588 __malloc_debug_disable (MALLOC_CHECK_HOOK);
589
590 /* We do not need to perform locking here because malloc_set_state
591 must be called before the first call into the malloc subsystem (usually via
592 __malloc_initialize_hook). pthread_create always calls calloc and thus
593 must be called only afterwards, so there cannot be more than one thread
594 when we reach this point. Also handle initialization if either we ended
595 up being called before the first malloc or through the hook when
596 malloc-check was enabled. */
597 if (debug_initialized < 0)
598 generic_hook_ini ();
599 else if (check_was_enabled)
600 __libc_free (__libc_malloc (0));
601
602 /* Patch the dumped heap. We no longer try to integrate into the
603 existing heap. Instead, we mark the existing chunks as mmapped.
604 Together with the update to dumped_main_arena_start and
605 dumped_main_arena_end, realloc and free will recognize these
606 chunks as dumped fake mmapped chunks and never free them. */
607
608 /* Find the chunk with the lowest address with the heap. */
609 mchunkptr chunk = NULL;
610 {
611 size_t *candidate = (size_t *) ms->sbrk_base;
612 size_t *end = (size_t *) (ms->sbrk_base + ms->sbrked_mem_bytes);
613 while (candidate < end)
614 if (*candidate != 0)
615 {
616 chunk = mem2chunk ((void *) (candidate + 1));
617 break;
618 }
619 else
620 ++candidate;
621 }
622 if (chunk == NULL)
623 return 0;
624
625 /* Iterate over the dumped heap and patch the chunks so that they
626 are treated as fake mmapped chunks. */
627 mchunkptr top = ms->av[2];
628 while (chunk < top)
629 {
630 if (inuse (chunk))
631 {
632 /* Mark chunk as mmapped, to trigger the fallback path. */
633 size_t size = chunksize (chunk);
634 set_head (chunk, size | IS_MMAPPED);
635 }
636 chunk = next_chunk (chunk);
637 }
638
639 /* The dumped fake mmapped chunks all lie in this address range. */
640 dumped_main_arena_start = (mchunkptr) ms->sbrk_base;
641 dumped_main_arena_end = top;
642
643 return 0;
644 }
645 compat_symbol (libc_malloc_debug, malloc_set_state, malloc_set_state,
646 GLIBC_2_0);
647 #endif
648
649 /* Do not allow linking against the library. */
650 compat_symbol (libc_malloc_debug, aligned_alloc, aligned_alloc, GLIBC_2_16);
651 compat_symbol (libc_malloc_debug, calloc, calloc, GLIBC_2_0);
652 compat_symbol (libc_malloc_debug, free, free, GLIBC_2_0);
653 compat_symbol (libc_malloc_debug, mallinfo2, mallinfo2, GLIBC_2_33);
654 compat_symbol (libc_malloc_debug, mallinfo, mallinfo, GLIBC_2_0);
655 compat_symbol (libc_malloc_debug, malloc_info, malloc_info, GLIBC_2_10);
656 compat_symbol (libc_malloc_debug, malloc, malloc, GLIBC_2_0);
657 compat_symbol (libc_malloc_debug, malloc_stats, malloc_stats, GLIBC_2_0);
658 compat_symbol (libc_malloc_debug, malloc_trim, malloc_trim, GLIBC_2_0);
659 compat_symbol (libc_malloc_debug, malloc_usable_size, malloc_usable_size,
660 GLIBC_2_0);
661 compat_symbol (libc_malloc_debug, mallopt, mallopt, GLIBC_2_0);
662 compat_symbol (libc_malloc_debug, mcheck_check_all, mcheck_check_all,
663 GLIBC_2_2);
664 compat_symbol (libc_malloc_debug, mcheck, mcheck, GLIBC_2_0);
665 compat_symbol (libc_malloc_debug, mcheck_pedantic, mcheck_pedantic, GLIBC_2_2);
666 compat_symbol (libc_malloc_debug, memalign, memalign, GLIBC_2_0);
667 compat_symbol (libc_malloc_debug, mprobe, mprobe, GLIBC_2_0);
668 compat_symbol (libc_malloc_debug, mtrace, mtrace, GLIBC_2_0);
669 compat_symbol (libc_malloc_debug, muntrace, muntrace, GLIBC_2_0);
670 compat_symbol (libc_malloc_debug, posix_memalign, posix_memalign, GLIBC_2_2);
671 compat_symbol (libc_malloc_debug, pvalloc, pvalloc, GLIBC_2_0);
672 compat_symbol (libc_malloc_debug, realloc, realloc, GLIBC_2_0);
673 compat_symbol (libc_malloc_debug, valloc, valloc, GLIBC_2_0);
674 compat_symbol (libc_malloc_debug, __free_hook, __free_hook, GLIBC_2_0);
675 compat_symbol (libc_malloc_debug, __malloc_hook, __malloc_hook, GLIBC_2_0);
676 compat_symbol (libc_malloc_debug, __realloc_hook, __realloc_hook, GLIBC_2_0);
677 compat_symbol (libc_malloc_debug, __memalign_hook, __memalign_hook, GLIBC_2_0);