1 /* Standard debugging hooks for `malloc'.
2 Copyright (C) 1990-1997,99,2000,01,02 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Written May 1989 by Mike Haertel.
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
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
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.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 #ifndef _MALLOC_INTERNAL
22 # define _MALLOC_INTERNAL
30 /* Old hook values. */
31 static void (*old_free_hook
) (__ptr_t ptr
, __const __ptr_t
);
32 static __ptr_t (*old_malloc_hook
) (__malloc_size_t size
, const __ptr_t
);
33 static __ptr_t (*old_memalign_hook
) (__malloc_size_t alignment
,
36 static __ptr_t (*old_realloc_hook
) (__ptr_t ptr
, __malloc_size_t size
,
39 /* Function to call when something awful happens. */
40 static void (*abortfunc
) (enum mcheck_status
);
42 /* Arbitrary magical numbers. */
43 #define MAGICWORD 0xfedabeeb
44 #define MAGICFREE 0xd8675309
45 #define MAGICBYTE ((char) 0xd7)
46 #define MALLOCFLOOD ((char) 0x93)
47 #define FREEFLOOD ((char) 0x95)
51 __malloc_size_t size
; /* Exact size requested by user. */
52 unsigned long int magic
; /* Magic number to check header integrity. */
55 __ptr_t block
; /* Real block allocated, for memalign. */
56 unsigned long int magic2
; /* Extra, keeps us doubleword aligned. */
59 /* This is the beginning of the list of all memory blocks allocated.
60 It is only constructed if the pedantic testing is requested. */
61 static struct hdr
*root
;
63 static int mcheck_used
;
65 /* Nonzero if pedentic checking of all blocks is requested. */
68 #if defined _LIBC || defined STDC_HEADERS || defined USG
72 static void flood (__ptr_t
, int, __malloc_size_t
);
74 flood (ptr
, val
, size
)
85 static enum mcheck_status
86 checkhdr (const struct hdr
*hdr
)
88 enum mcheck_status status
;
91 /* Maybe the mcheck used is disabled? This happens when we find
92 an error and report it. */
95 switch (hdr
->magic
^ ((uintptr_t) hdr
->prev
+ (uintptr_t) hdr
->next
))
101 status
= MCHECK_FREE
;
104 if (((char *) &hdr
[1])[hdr
->size
] != MAGICBYTE
)
105 status
= MCHECK_TAIL
;
106 else if ((hdr
->magic2
^ (uintptr_t) hdr
->block
) != MAGICWORD
)
107 status
= MCHECK_HEAD
;
112 if (status
!= MCHECK_OK
)
115 (*abortfunc
) (status
);
122 mcheck_check_all (void)
124 /* Walk through all the active blocks and test whether they were tempered
126 struct hdr
*runp
= root
;
128 /* Temporarily turn off the checks. */
133 (void) checkhdr (runp
);
138 /* Turn checks on again. */
142 libc_hidden_def (mcheck_check_all
)
146 unlink_blk (struct hdr
*ptr
)
148 if (ptr
->next
!= NULL
)
150 ptr
->next
->prev
= ptr
->prev
;
151 ptr
->next
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->next
->prev
152 + (uintptr_t) ptr
->next
->next
);
154 if (ptr
->prev
!= NULL
)
156 ptr
->prev
->next
= ptr
->next
;
157 ptr
->prev
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->prev
->prev
158 + (uintptr_t) ptr
->prev
->next
);
165 link_blk (struct hdr
*hdr
)
170 hdr
->magic
= MAGICWORD
^ (uintptr_t) hdr
->next
;
172 /* And the next block. */
173 if (hdr
->next
!= NULL
)
175 hdr
->next
->prev
= hdr
;
176 hdr
->next
->magic
= MAGICWORD
^ ((uintptr_t) hdr
177 + (uintptr_t) hdr
->next
->next
);
181 freehook (__ptr_t ptr
, const __ptr_t caller
)
187 struct hdr
*hdr
= ((struct hdr
*) ptr
) - 1;
189 hdr
->magic
= MAGICFREE
;
190 hdr
->magic2
= MAGICFREE
;
192 hdr
->prev
= hdr
->next
= NULL
;
193 flood (ptr
, FREEFLOOD
, hdr
->size
);
196 __free_hook
= old_free_hook
;
197 if (old_free_hook
!= NULL
)
198 (*old_free_hook
) (ptr
, caller
);
201 __free_hook
= freehook
;
205 mallochook (__malloc_size_t size
, const __ptr_t caller
)
212 __malloc_hook
= old_malloc_hook
;
213 if (old_malloc_hook
!= NULL
)
214 hdr
= (struct hdr
*) (*old_malloc_hook
) (sizeof (struct hdr
) + size
+ 1,
217 hdr
= (struct hdr
*) malloc (sizeof (struct hdr
) + size
+ 1);
218 __malloc_hook
= mallochook
;
225 hdr
->magic2
= (uintptr_t) hdr
^ MAGICWORD
;
226 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
227 flood ((__ptr_t
) (hdr
+ 1), MALLOCFLOOD
, size
);
228 return (__ptr_t
) (hdr
+ 1);
232 memalignhook (__malloc_size_t alignment
, __malloc_size_t size
,
233 const __ptr_t caller
)
236 __malloc_size_t slop
;
242 slop
= (sizeof *hdr
+ alignment
- 1) & -alignment
;
244 __memalign_hook
= old_memalign_hook
;
245 if (old_memalign_hook
!= NULL
)
246 block
= (*old_memalign_hook
) (alignment
, slop
+ size
+ 1, caller
);
248 block
= memalign (alignment
, slop
+ size
+ 1);
249 __memalign_hook
= memalignhook
;
253 hdr
= ((struct hdr
*) (block
+ slop
)) - 1;
257 hdr
->block
= (__ptr_t
) block
;
258 hdr
->magic2
= (uintptr_t) block
^ MAGICWORD
;
259 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
260 flood ((__ptr_t
) (hdr
+ 1), MALLOCFLOOD
, size
);
261 return (__ptr_t
) (hdr
+ 1);
265 reallochook (__ptr_t ptr
, __malloc_size_t size
, const __ptr_t caller
)
268 __malloc_size_t osize
;
275 hdr
= ((struct hdr
*) ptr
) - 1;
281 flood ((char *) ptr
+ size
, FREEFLOOD
, osize
- size
);
288 __free_hook
= old_free_hook
;
289 __malloc_hook
= old_malloc_hook
;
290 __memalign_hook
= old_memalign_hook
;
291 __realloc_hook
= old_realloc_hook
;
292 if (old_realloc_hook
!= NULL
)
293 hdr
= (struct hdr
*) (*old_realloc_hook
) ((__ptr_t
) hdr
,
294 sizeof (struct hdr
) + size
+ 1,
297 hdr
= (struct hdr
*) realloc ((__ptr_t
) hdr
,
298 sizeof (struct hdr
) + size
+ 1);
299 __free_hook
= freehook
;
300 __malloc_hook
= mallochook
;
301 __memalign_hook
= memalignhook
;
302 __realloc_hook
= reallochook
;
309 hdr
->magic2
= (uintptr_t) hdr
^ MAGICWORD
;
310 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
312 flood ((char *) (hdr
+ 1) + osize
, MALLOCFLOOD
, size
- osize
);
313 return (__ptr_t
) (hdr
+ 1);
316 __attribute__ ((noreturn
))
318 mabort (enum mcheck_status status
)
324 msg
= _("memory is consistent, library is buggy\n");
327 msg
= _("memory clobbered before allocated block\n");
330 msg
= _("memory clobbered past end of allocated block\n");
333 msg
= _("block freed twice\n");
336 msg
= _("bogus mcheck_status, library is buggy\n");
342 fprintf (stderr
, "mcheck: %s", msg
);
350 void (*func
) (enum mcheck_status
);
352 abortfunc
= (func
!= NULL
) ? func
: &mabort
;
354 /* These hooks may not be safely inserted if malloc is already in use. */
355 if (__malloc_initialized
<= 0 && !mcheck_used
)
357 /* We call malloc() once here to ensure it is initialized. */
358 void *p
= malloc (0);
361 old_free_hook
= __free_hook
;
362 __free_hook
= freehook
;
363 old_malloc_hook
= __malloc_hook
;
364 __malloc_hook
= mallochook
;
365 old_memalign_hook
= __memalign_hook
;
366 __memalign_hook
= memalignhook
;
367 old_realloc_hook
= __realloc_hook
;
368 __realloc_hook
= reallochook
;
372 return mcheck_used
? 0 : -1;
375 libc_hidden_def (mcheck
)
379 mcheck_pedantic (func
)
380 void (*func
) (enum mcheck_status
);
382 int res
= mcheck (func
);
391 return mcheck_used
? checkhdr (((struct hdr
*) ptr
) - 1) : MCHECK_DISABLED
;