1 /* Standard debugging hooks for `malloc'.
2 Copyright (C) 1990-1997, 1999, 2000, 2001 Free Software Foundation, Inc.
3 Written May 1989 by Mike Haertel.
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
20 The author may be reached (Email) at the address mike@ai.mit.edu,
21 or (US mail) as Mike Haertel c/o Free Software Foundation. */
23 #ifndef _MALLOC_INTERNAL
24 # define _MALLOC_INTERNAL
32 /* Old hook values. */
33 static void (*old_free_hook
) __P ((__ptr_t ptr
, __const __ptr_t
));
34 static __ptr_t (*old_malloc_hook
) __P ((__malloc_size_t size
, const __ptr_t
));
35 static __ptr_t (*old_realloc_hook
) __P ((__ptr_t ptr
, __malloc_size_t size
,
38 /* Function to call when something awful happens. */
39 static void (*abortfunc
) __P ((enum mcheck_status
));
41 /* Arbitrary magical numbers. */
42 #define MAGICWORD 0xfedabeeb
43 #define MAGICFREE 0xd8675309
44 #define MAGICBYTE ((char) 0xd7)
45 #define MALLOCFLOOD ((char) 0x93)
46 #define FREEFLOOD ((char) 0x95)
50 __malloc_size_t size
; /* Exact size requested by user. */
51 unsigned long int magic
; /* Magic number to check header integrity. */
56 /* This is the beginning of the list of all memory blocks allocated.
57 It is only constructed if the pedantic testing is requested. */
58 static struct hdr
*root
;
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
;
86 switch (hdr
->magic
^ ((uintptr_t) hdr
->prev
+ (uintptr_t) hdr
->next
))
95 if (((char *) &hdr
[1])[hdr
->size
] != MAGICBYTE
)
101 if (status
!= MCHECK_OK
)
102 (*abortfunc
) (status
);
109 /* Walk through all the active blocks and test whether they were tempered
111 struct hdr
*runp
= root
;
113 /* Temporarily turn off the checks. */
118 (void) checkhdr (runp
);
123 /* Turn checks on again. */
127 static void unlink_blk
__P ((struct hdr
*ptr
));
132 if (ptr
->next
!= NULL
)
134 ptr
->next
->prev
= ptr
->prev
;
135 ptr
->next
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->next
->prev
136 + (uintptr_t) ptr
->next
->next
);
138 if (ptr
->prev
!= NULL
)
140 ptr
->prev
->next
= ptr
->next
;
141 ptr
->prev
->magic
= MAGICWORD
^ ((uintptr_t) ptr
->prev
->prev
142 + (uintptr_t) ptr
->prev
->next
);
148 static void link_blk
__P ((struct hdr
*ptr
));
156 hdr
->magic
= MAGICWORD
^ (uintptr_t) hdr
->next
;
158 /* And the next block. */
159 if (hdr
->next
!= NULL
)
161 hdr
->next
->prev
= hdr
;
162 hdr
->next
->magic
= MAGICWORD
^ ((uintptr_t) hdr
163 + (uintptr_t) hdr
->next
->next
);
167 static void freehook
__P ((__ptr_t
, const __ptr_t
));
169 freehook (ptr
, caller
)
171 const __ptr_t caller
;
177 struct hdr
*hdr
= ((struct hdr
*) ptr
) - 1;
179 hdr
->magic
= MAGICFREE
;
181 hdr
->prev
= hdr
->next
= NULL
;
182 flood (ptr
, FREEFLOOD
, hdr
->size
);
185 __free_hook
= old_free_hook
;
186 if (old_free_hook
!= NULL
)
187 (*old_free_hook
) (ptr
, caller
);
190 __free_hook
= freehook
;
193 static __ptr_t mallochook
__P ((__malloc_size_t
, const __ptr_t
));
195 mallochook (size
, caller
)
196 __malloc_size_t size
;
197 const __ptr_t caller
;
204 __malloc_hook
= old_malloc_hook
;
205 if (old_malloc_hook
!= NULL
)
206 hdr
= (struct hdr
*) (*old_malloc_hook
) (sizeof (struct hdr
) + size
+ 1,
209 hdr
= (struct hdr
*) malloc (sizeof (struct hdr
) + size
+ 1);
210 __malloc_hook
= mallochook
;
216 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
217 flood ((__ptr_t
) (hdr
+ 1), MALLOCFLOOD
, size
);
218 return (__ptr_t
) (hdr
+ 1);
221 static __ptr_t reallochook
__P ((__ptr_t
, __malloc_size_t
, const __ptr_t
));
223 reallochook (ptr
, size
, caller
)
225 __malloc_size_t size
;
226 const __ptr_t caller
;
229 __malloc_size_t osize
;
236 hdr
= ((struct hdr
*) ptr
) - 1;
242 flood ((char *) ptr
+ size
, FREEFLOOD
, osize
- size
);
249 __free_hook
= old_free_hook
;
250 __malloc_hook
= old_malloc_hook
;
251 __realloc_hook
= old_realloc_hook
;
252 if (old_realloc_hook
!= NULL
)
253 hdr
= (struct hdr
*) (*old_realloc_hook
) ((__ptr_t
) hdr
,
254 sizeof (struct hdr
) + size
+ 1,
257 hdr
= (struct hdr
*) realloc ((__ptr_t
) hdr
,
258 sizeof (struct hdr
) + size
+ 1);
259 __free_hook
= freehook
;
260 __malloc_hook
= mallochook
;
261 __realloc_hook
= reallochook
;
267 ((char *) &hdr
[1])[size
] = MAGICBYTE
;
269 flood ((char *) (hdr
+ 1) + osize
, MALLOCFLOOD
, size
- osize
);
270 return (__ptr_t
) (hdr
+ 1);
273 static void mabort
__P ((enum mcheck_status status
))
274 __attribute__ ((noreturn
));
277 enum mcheck_status status
;
283 msg
= _("memory is consistent, library is buggy\n");
286 msg
= _("memory clobbered before allocated block\n");
289 msg
= _("memory clobbered past end of allocated block\n");
292 msg
= _("block freed twice\n");
295 msg
= _("bogus mcheck_status, library is buggy\n");
301 fprintf (stderr
, "mcheck: %s", msg
);
307 static int mcheck_used
;
311 void (*func
) __P ((enum mcheck_status
));
313 abortfunc
= (func
!= NULL
) ? func
: &mabort
;
315 /* These hooks may not be safely inserted if malloc is already in use. */
316 if (__malloc_initialized
<= 0 && !mcheck_used
)
318 /* We call malloc() once here to ensure it is initialized. */
319 void *p
= malloc (0);
322 old_free_hook
= __free_hook
;
323 __free_hook
= freehook
;
324 old_malloc_hook
= __malloc_hook
;
325 __malloc_hook
= mallochook
;
326 old_realloc_hook
= __realloc_hook
;
327 __realloc_hook
= reallochook
;
331 return mcheck_used
? 0 : -1;
335 mcheck_pedantic (func
)
336 void (*func
) __P ((enum mcheck_status
));
338 int res
= mcheck (func
);
347 return mcheck_used
? checkhdr (((struct hdr
*) ptr
) - 1) : MCHECK_DISABLED
;