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
) __P ((__ptr_t ptr
, __const __ptr_t
));
32 static __ptr_t (*old_malloc_hook
) __P ((__malloc_size_t size
, const __ptr_t
));
33 static __ptr_t (*old_realloc_hook
) __P ((__ptr_t ptr
, __malloc_size_t size
,
36 /* Function to call when something awful happens. */
37 static void (*abortfunc
) __P ((enum mcheck_status
));
39 /* Arbitrary magical numbers. */
40 #define MAGICWORD 0xfedabeeb
41 #define MAGICFREE 0xd8675309
42 #define MAGICBYTE ((char) 0xd7)
43 #define MALLOCFLOOD ((char) 0x93)
44 #define FREEFLOOD ((char) 0x95)
48 __malloc_size_t size
; /* Exact size requested by user. */
49 unsigned long int magic
; /* Magic number to check header integrity. */
54 /* This is the beginning of the list of all memory blocks allocated.
55 It is only constructed if the pedantic testing is requested. */
56 static struct hdr
*root
;
58 static int mcheck_used
;
60 /* Nonzero if pedentic checking of all blocks is requested. */
63 #if defined _LIBC || defined STDC_HEADERS || defined USG
67 static void flood
__P ((__ptr_t
, int, __malloc_size_t
));
69 flood (ptr
, val
, size
)
80 static enum mcheck_status checkhdr
__P ((const struct hdr
*));
81 static enum mcheck_status
83 const struct hdr
*hdr
;
85 enum mcheck_status status
;
88 /* Maybe the mcheck used is disabled? This happens when we find
89 an error and report it. */
92 switch (hdr
->magic
^ ((uintptr_t) hdr
->prev
+ (uintptr_t) hdr
->next
))
101 if (((char *) &hdr
[1])[hdr
->size
] != MAGICBYTE
)
102 status
= MCHECK_TAIL
;
107 if (status
!= MCHECK_OK
)
110 (*abortfunc
) (status
);
119 /* Walk through all the active blocks and test whether they were tempered
121 struct hdr
*runp
= root
;
123 /* Temporarily turn off the checks. */
128 (void) checkhdr (runp
);
133 /* Turn checks on again. */
137 libc_hidden_def (mcheck_check_all
)
140 static void unlink_blk
__P ((struct hdr
*ptr
));
145 if (ptr
->next
!= NULL
)
147 ptr
->next
->prev
= ptr
->prev
;
148 ptr
->next
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->next
->prev
149 + (uintptr_t) ptr
->next
->next
);
151 if (ptr
->prev
!= NULL
)
153 ptr
->prev
->next
= ptr
->next
;
154 ptr
->prev
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->prev
->prev
155 + (uintptr_t) ptr
->prev
->next
);
161 static void link_blk
__P ((struct hdr
*ptr
));
169 hdr
->magic
= MAGICWORD
^ (uintptr_t) hdr
->next
;
171 /* And the next block. */
172 if (hdr
->next
!= NULL
)
174 hdr
->next
->prev
= hdr
;
175 hdr
->next
->magic
= MAGICWORD
^ ((uintptr_t) hdr
176 + (uintptr_t) hdr
->next
->next
);
180 static void freehook
__P ((__ptr_t
, const __ptr_t
));
182 freehook (ptr
, caller
)
184 const __ptr_t caller
;
190 struct hdr
*hdr
= ((struct hdr
*) ptr
) - 1;
192 hdr
->magic
= MAGICFREE
;
194 hdr
->prev
= hdr
->next
= NULL
;
195 flood (ptr
, FREEFLOOD
, hdr
->size
);
198 __free_hook
= old_free_hook
;
199 if (old_free_hook
!= NULL
)
200 (*old_free_hook
) (ptr
, caller
);
203 __free_hook
= freehook
;
206 static __ptr_t mallochook
__P ((__malloc_size_t
, const __ptr_t
));
208 mallochook (size
, caller
)
209 __malloc_size_t size
;
210 const __ptr_t caller
;
217 __malloc_hook
= old_malloc_hook
;
218 if (old_malloc_hook
!= NULL
)
219 hdr
= (struct hdr
*) (*old_malloc_hook
) (sizeof (struct hdr
) + size
+ 1,
222 hdr
= (struct hdr
*) malloc (sizeof (struct hdr
) + size
+ 1);
223 __malloc_hook
= mallochook
;
229 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
230 flood ((__ptr_t
) (hdr
+ 1), MALLOCFLOOD
, size
);
231 return (__ptr_t
) (hdr
+ 1);
234 static __ptr_t reallochook
__P ((__ptr_t
, __malloc_size_t
, const __ptr_t
));
236 reallochook (ptr
, size
, caller
)
238 __malloc_size_t size
;
239 const __ptr_t caller
;
242 __malloc_size_t osize
;
249 hdr
= ((struct hdr
*) ptr
) - 1;
255 flood ((char *) ptr
+ size
, FREEFLOOD
, osize
- size
);
262 __free_hook
= old_free_hook
;
263 __malloc_hook
= old_malloc_hook
;
264 __realloc_hook
= old_realloc_hook
;
265 if (old_realloc_hook
!= NULL
)
266 hdr
= (struct hdr
*) (*old_realloc_hook
) ((__ptr_t
) hdr
,
267 sizeof (struct hdr
) + size
+ 1,
270 hdr
= (struct hdr
*) realloc ((__ptr_t
) hdr
,
271 sizeof (struct hdr
) + size
+ 1);
272 __free_hook
= freehook
;
273 __malloc_hook
= mallochook
;
274 __realloc_hook
= reallochook
;
280 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
282 flood ((char *) (hdr
+ 1) + osize
, MALLOCFLOOD
, size
- osize
);
283 return (__ptr_t
) (hdr
+ 1);
286 static void mabort
__P ((enum mcheck_status status
))
287 __attribute__ ((noreturn
));
290 enum mcheck_status status
;
296 msg
= _("memory is consistent, library is buggy\n");
299 msg
= _("memory clobbered before allocated block\n");
302 msg
= _("memory clobbered past end of allocated block\n");
305 msg
= _("block freed twice\n");
308 msg
= _("bogus mcheck_status, library is buggy\n");
314 fprintf (stderr
, "mcheck: %s", msg
);
322 void (*func
) __P ((enum mcheck_status
));
324 abortfunc
= (func
!= NULL
) ? func
: &mabort
;
326 /* These hooks may not be safely inserted if malloc is already in use. */
327 if (__malloc_initialized
<= 0 && !mcheck_used
)
329 /* We call malloc() once here to ensure it is initialized. */
330 void *p
= malloc (0);
333 old_free_hook
= __free_hook
;
334 __free_hook
= freehook
;
335 old_malloc_hook
= __malloc_hook
;
336 __malloc_hook
= mallochook
;
337 old_realloc_hook
= __realloc_hook
;
338 __realloc_hook
= reallochook
;
342 return mcheck_used
? 0 : -1;
345 libc_hidden_def (mcheck
)
349 mcheck_pedantic (func
)
350 void (*func
) __P ((enum mcheck_status
));
352 int res
= mcheck (func
);
361 return mcheck_used
? checkhdr (((struct hdr
*) ptr
) - 1) : MCHECK_DISABLED
;