1 /* Standard debugging hooks for `malloc'.
2 Copyright (C) 1990-1997,1999,2000-2002,2007,2010
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Written May 1989 by Mike Haertel.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #ifndef _MALLOC_INTERNAL
23 # define _MALLOC_INTERNAL
34 extern __typeof (malloc
) __libc_malloc
;
35 extern __typeof (free
) __libc_free
;
36 extern __typeof (realloc
) __libc_realloc
;
37 libc_hidden_proto (__libc_malloc
)
38 libc_hidden_proto (__libc_realloc
)
39 libc_hidden_proto (__libc_free
)
40 libc_hidden_proto (__libc_memalign
)
42 # define __libc_malloc(sz) malloc (sz)
43 # define __libc_free(ptr) free (ptr)
44 # define __libc_realloc(ptr, sz) realloc (ptr, sz)
45 # define __libc_memalign(al, sz) memalign (al, sz)
48 /* Old hook values. */
49 static void (*old_free_hook
) (__ptr_t ptr
, __const __ptr_t
);
50 static __ptr_t (*old_malloc_hook
) (__malloc_size_t size
, const __ptr_t
);
51 static __ptr_t (*old_memalign_hook
) (__malloc_size_t alignment
,
54 static __ptr_t (*old_realloc_hook
) (__ptr_t ptr
, __malloc_size_t size
,
57 /* Function to call when something awful happens. */
58 static void (*abortfunc
) (enum mcheck_status
);
60 /* Arbitrary magical numbers. */
61 #define MAGICWORD 0xfedabeeb
62 #define MAGICFREE 0xd8675309
63 #define MAGICBYTE ((char) 0xd7)
64 #define MALLOCFLOOD ((char) 0x93)
65 #define FREEFLOOD ((char) 0x95)
69 __malloc_size_t size
; /* Exact size requested by user. */
70 unsigned long int magic
; /* Magic number to check header integrity. */
73 __ptr_t block
; /* Real block allocated, for memalign. */
74 unsigned long int magic2
; /* Extra, keeps us doubleword aligned. */
77 /* This is the beginning of the list of all memory blocks allocated.
78 It is only constructed if the pedantic testing is requested. */
79 static struct hdr
*root
;
81 static int mcheck_used
;
83 /* Nonzero if pedentic checking of all blocks is requested. */
86 #if defined _LIBC || defined STDC_HEADERS || defined USG
90 static void flood (__ptr_t
, int, __malloc_size_t
);
92 flood (ptr
, val
, size
)
103 static enum mcheck_status
104 checkhdr (const struct hdr
*hdr
)
106 enum mcheck_status status
;
109 /* Maybe the mcheck used is disabled? This happens when we find
110 an error and report it. */
113 switch (hdr
->magic
^ ((uintptr_t) hdr
->prev
+ (uintptr_t) hdr
->next
))
116 status
= MCHECK_HEAD
;
119 status
= MCHECK_FREE
;
122 if (((char *) &hdr
[1])[hdr
->size
] != MAGICBYTE
)
123 status
= MCHECK_TAIL
;
124 else if ((hdr
->magic2
^ (uintptr_t) hdr
->block
) != MAGICWORD
)
125 status
= MCHECK_HEAD
;
130 if (status
!= MCHECK_OK
)
133 (*abortfunc
) (status
);
140 mcheck_check_all (void)
142 /* Walk through all the active blocks and test whether they were tempered
144 struct hdr
*runp
= root
;
146 /* Temporarily turn off the checks. */
151 (void) checkhdr (runp
);
156 /* Turn checks on again. */
160 libc_hidden_def (mcheck_check_all
)
164 unlink_blk (struct hdr
*ptr
)
166 if (ptr
->next
!= NULL
)
168 ptr
->next
->prev
= ptr
->prev
;
169 ptr
->next
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->next
->prev
170 + (uintptr_t) ptr
->next
->next
);
172 if (ptr
->prev
!= NULL
)
174 ptr
->prev
->next
= ptr
->next
;
175 ptr
->prev
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->prev
->prev
176 + (uintptr_t) ptr
->prev
->next
);
183 link_blk (struct hdr
*hdr
)
188 hdr
->magic
= MAGICWORD
^ (uintptr_t) hdr
->next
;
190 /* And the next block. */
191 if (hdr
->next
!= NULL
)
193 hdr
->next
->prev
= hdr
;
194 hdr
->next
->magic
= MAGICWORD
^ ((uintptr_t) hdr
195 + (uintptr_t) hdr
->next
->next
);
199 freehook (__ptr_t ptr
, const __ptr_t caller
)
205 struct hdr
*hdr
= ((struct hdr
*) ptr
) - 1;
207 hdr
->magic
= MAGICFREE
;
208 hdr
->magic2
= MAGICFREE
;
210 hdr
->prev
= hdr
->next
= NULL
;
211 flood (ptr
, FREEFLOOD
, hdr
->size
);
214 __free_hook
= old_free_hook
;
215 if (old_free_hook
!= NULL
)
216 (*old_free_hook
) (ptr
, caller
);
219 __free_hook
= freehook
;
223 mallochook (__malloc_size_t size
, const __ptr_t caller
)
230 if (size
> ~((size_t) 0) - (sizeof (struct hdr
) + 1))
232 __set_errno (ENOMEM
);
236 __malloc_hook
= old_malloc_hook
;
237 if (old_malloc_hook
!= NULL
)
238 hdr
= (struct hdr
*) (*old_malloc_hook
) (sizeof (struct hdr
) + size
+ 1,
241 hdr
= (struct hdr
*) __libc_malloc (sizeof (struct hdr
) + size
+ 1);
242 __malloc_hook
= mallochook
;
249 hdr
->magic2
= (uintptr_t) hdr
^ MAGICWORD
;
250 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
251 flood ((__ptr_t
) (hdr
+ 1), MALLOCFLOOD
, size
);
252 return (__ptr_t
) (hdr
+ 1);
256 memalignhook (__malloc_size_t alignment
, __malloc_size_t size
,
257 const __ptr_t caller
)
260 __malloc_size_t slop
;
266 slop
= (sizeof *hdr
+ alignment
- 1) & -alignment
;
268 if (size
> ~((size_t) 0) - (slop
+ 1))
270 __set_errno (ENOMEM
);
274 __memalign_hook
= old_memalign_hook
;
275 if (old_memalign_hook
!= NULL
)
276 block
= (*old_memalign_hook
) (alignment
, slop
+ size
+ 1, caller
);
278 block
= __libc_memalign (alignment
, slop
+ size
+ 1);
279 __memalign_hook
= memalignhook
;
283 hdr
= ((struct hdr
*) (block
+ slop
)) - 1;
287 hdr
->block
= (__ptr_t
) block
;
288 hdr
->magic2
= (uintptr_t) block
^ MAGICWORD
;
289 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
290 flood ((__ptr_t
) (hdr
+ 1), MALLOCFLOOD
, size
);
291 return (__ptr_t
) (hdr
+ 1);
295 reallochook (__ptr_t ptr
, __malloc_size_t size
, const __ptr_t caller
)
299 freehook (ptr
, caller
);
304 __malloc_size_t osize
;
309 if (size
> ~((size_t) 0) - (sizeof (struct hdr
) + 1))
311 __set_errno (ENOMEM
);
317 hdr
= ((struct hdr
*) ptr
) - 1;
323 flood ((char *) ptr
+ size
, FREEFLOOD
, osize
- size
);
330 __free_hook
= old_free_hook
;
331 __malloc_hook
= old_malloc_hook
;
332 __memalign_hook
= old_memalign_hook
;
333 __realloc_hook
= old_realloc_hook
;
334 if (old_realloc_hook
!= NULL
)
335 hdr
= (struct hdr
*) (*old_realloc_hook
) ((__ptr_t
) hdr
,
336 sizeof (struct hdr
) + size
+ 1,
339 hdr
= (struct hdr
*) __libc_realloc ((__ptr_t
) hdr
,
340 sizeof (struct hdr
) + size
+ 1);
341 __free_hook
= freehook
;
342 __malloc_hook
= mallochook
;
343 __memalign_hook
= memalignhook
;
344 __realloc_hook
= reallochook
;
351 hdr
->magic2
= (uintptr_t) hdr
^ MAGICWORD
;
352 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
354 flood ((char *) (hdr
+ 1) + osize
, MALLOCFLOOD
, size
- osize
);
355 return (__ptr_t
) (hdr
+ 1);
358 __attribute__ ((noreturn
))
360 mabort (enum mcheck_status status
)
366 msg
= _("memory is consistent, library is buggy\n");
369 msg
= _("memory clobbered before allocated block\n");
372 msg
= _("memory clobbered past end of allocated block\n");
375 msg
= _("block freed twice\n");
378 msg
= _("bogus mcheck_status, library is buggy\n");
384 fprintf (stderr
, "mcheck: %s", msg
);
392 void (*func
) (enum mcheck_status
);
394 abortfunc
= (func
!= NULL
) ? func
: &mabort
;
396 /* These hooks may not be safely inserted if malloc is already in use. */
397 if (__malloc_initialized
<= 0 && !mcheck_used
)
399 /* We call malloc() once here to ensure it is initialized. */
400 void *p
= __libc_malloc (0);
403 old_free_hook
= __free_hook
;
404 __free_hook
= freehook
;
405 old_malloc_hook
= __malloc_hook
;
406 __malloc_hook
= mallochook
;
407 old_memalign_hook
= __memalign_hook
;
408 __memalign_hook
= memalignhook
;
409 old_realloc_hook
= __realloc_hook
;
410 __realloc_hook
= reallochook
;
414 return mcheck_used
? 0 : -1;
417 libc_hidden_def (mcheck
)
421 mcheck_pedantic (func
)
422 void (*func
) (enum mcheck_status
);
424 int res
= mcheck (func
);
433 return mcheck_used
? checkhdr (((struct hdr
*) ptr
) - 1) : MCHECK_DISABLED
;