/* The malloc headers and source files from the C library follow here. */
/* Declarations for `malloc' and friends.
- Copyright 1990, 91, 92, 93, 95, 96 Free Software Foundation, Inc.
+ Copyright 1990, 91, 92, 93, 95, 96, 99 Free Software Foundation, Inc.
Written May 1989 by Mike Haertel.
This library is free software; you can redistribute it and/or
#include <config.h>
#endif
-#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
-#undef __P
-#define __P(args) args
+#if ((defined __cplusplus || (defined (__STDC__) && __STDC__) \
+ || defined STDC_HEADERS || defined PROTOTYPES) \
+ && ! defined (BROKEN_PROTOTYPES))
+#undef PP
+#define PP(args) args
#undef __ptr_t
#define __ptr_t void *
#else /* Not C++ or ANSI C. */
-#undef __P
-#define __P(args) ()
-#undef const
-#define const
+#undef PP
+#define PP(args) ()
#undef __ptr_t
#define __ptr_t char *
#endif /* C++ or ANSI C. */
#endif
#endif
-#if defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__)
+#ifdef HAVE_LIMITS_H
#include <limits.h>
-#else
+#endif
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
{
#endif
-#if defined (__STDC__) && __STDC__
+#ifdef STDC_HEADERS
#include <stddef.h>
#define __malloc_size_t size_t
#define __malloc_ptrdiff_t ptrdiff_t
#else
+#ifdef __GNUC__
+#include <stddef.h>
+#ifdef __SIZE_TYPE__
+#define __malloc_size_t __SIZE_TYPE__
+#endif
+#endif
+#ifndef __malloc_size_t
#define __malloc_size_t unsigned int
+#endif
#define __malloc_ptrdiff_t int
#endif
#define NULL 0
#endif
+#ifndef FREE_RETURN_TYPE
+#define FREE_RETURN_TYPE void
+#endif
+
/* Allocate SIZE bytes of memory. */
-extern __ptr_t malloc __P ((__malloc_size_t __size));
+extern __ptr_t malloc PP ((__malloc_size_t __size));
/* Re-allocate the previously allocated block
in __ptr_t, making the new block SIZE bytes long. */
-extern __ptr_t realloc __P ((__ptr_t __ptr, __malloc_size_t __size));
+extern __ptr_t realloc PP ((__ptr_t __ptr, __malloc_size_t __size));
/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
-extern __ptr_t calloc __P ((__malloc_size_t __nmemb, __malloc_size_t __size));
+extern __ptr_t calloc PP ((__malloc_size_t __nmemb, __malloc_size_t __size));
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
-extern void free __P ((__ptr_t __ptr));
+extern FREE_RETURN_TYPE free PP ((__ptr_t __ptr));
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
#if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict. */
-extern __ptr_t memalign __P ((__malloc_size_t __alignment,
- __malloc_size_t __size));
+extern __ptr_t memalign PP ((__malloc_size_t __alignment,
+ __malloc_size_t __size));
#endif
/* Allocate SIZE bytes on a page boundary. */
#if ! (defined (_MALLOC_INTERNAL) && defined (GMALLOC_INHIBIT_VALLOC))
-extern __ptr_t valloc __P ((__malloc_size_t __size));
+extern __ptr_t valloc PP ((__malloc_size_t __size));
#endif
/* Internal versions of `malloc', `realloc', and `free'
used when these functions need to call each other.
They are the same but don't call the hooks. */
-extern __ptr_t _malloc_internal __P ((__malloc_size_t __size));
-extern __ptr_t _realloc_internal __P ((__ptr_t __ptr, __malloc_size_t __size));
-extern void _free_internal __P ((__ptr_t __ptr));
+extern __ptr_t _malloc_internal PP ((__malloc_size_t __size));
+extern __ptr_t _realloc_internal PP ((__ptr_t __ptr, __malloc_size_t __size));
+extern void _free_internal PP ((__ptr_t __ptr));
#endif /* _MALLOC_INTERNAL. */
/* Given an address in the middle of a malloc'd object,
return the address of the beginning of the object. */
-extern __ptr_t malloc_find_object_address __P ((__ptr_t __ptr));
+extern __ptr_t malloc_find_object_address PP ((__ptr_t __ptr));
/* Underlying allocation function; successive calls should
return contiguous pieces of memory. */
-extern __ptr_t (*__morecore) __P ((__malloc_ptrdiff_t __size));
+extern __ptr_t (*__morecore) PP ((__malloc_ptrdiff_t __size));
/* Default value of `__morecore'. */
-extern __ptr_t __default_morecore __P ((__malloc_ptrdiff_t __size));
+extern __ptr_t __default_morecore PP ((__malloc_ptrdiff_t __size));
/* If not NULL, this function is called after each time
`__morecore' is called to increase the data size. */
-extern void (*__after_morecore_hook) __P ((void));
+extern void (*__after_morecore_hook) PP ((void));
/* Number of extra blocks to get each time we ask for more core.
This reduces the frequency of calling `(*__morecore)'. */
/* Nonzero if `malloc' has been called and done its initialization. */
extern int __malloc_initialized;
/* Function called to initialize malloc data structures. */
-extern int __malloc_initialize __P ((void));
+extern int __malloc_initialize PP ((void));
/* Hooks for debugging versions. */
-extern void (*__malloc_initialize_hook) __P ((void));
-extern void (*__free_hook) __P ((__ptr_t __ptr));
-extern __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size));
-extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
-extern __ptr_t (*__memalign_hook) __P ((__malloc_size_t __size,
- __malloc_size_t __alignment));
+extern void (*__malloc_initialize_hook) PP ((void));
+extern void (*__free_hook) PP ((__ptr_t __ptr));
+extern __ptr_t (*__malloc_hook) PP ((__malloc_size_t __size));
+extern __ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size));
+extern __ptr_t (*__memalign_hook) PP ((__malloc_size_t __size,
+ __malloc_size_t __alignment));
/* Return values for `mprobe': these are the kinds of inconsistencies that
`mcheck' enables detection of. */
before `malloc' is ever called. ABORTFUNC is called with an error code
(see enum above) when an inconsistency is detected. If ABORTFUNC is
null, the standard function prints on stderr and then calls `abort'. */
-extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status))));
+extern int mcheck PP ((void (*__abortfunc) PP ((enum mcheck_status))));
/* Check for aberrations in a particular malloc'd block. You must have
called `mcheck' already. These are the same checks that `mcheck' does
when you free or reallocate a block. */
-extern enum mcheck_status mprobe __P ((__ptr_t __ptr));
+extern enum mcheck_status mprobe PP ((__ptr_t __ptr));
/* Activate a standard collection of tracing hooks. */
-extern void mtrace __P ((void));
-extern void muntrace __P ((void));
+extern void mtrace PP ((void));
+extern void muntrace PP ((void));
/* Statistics available to the user. */
struct mstats
};
/* Pick up the current statistics. */
-extern struct mstats mstats __P ((void));
+extern struct mstats mstats PP ((void));
/* Call WARNFUN with a warning message when memory usage is high. */
-extern void memory_warnings __P ((__ptr_t __start,
- void (*__warnfun) __P ((const char *))));
+extern void memory_warnings PP ((__ptr_t __start,
+ void (*__warnfun) PP ((const char *))));
/* Relocating allocator. */
/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */
-extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
+extern __ptr_t r_alloc PP ((__ptr_t *__handleptr, __malloc_size_t __size));
/* Free the storage allocated in HANDLEPTR. */
-extern void r_alloc_free __P ((__ptr_t *__handleptr));
+extern void r_alloc_free PP ((__ptr_t *__handleptr));
/* Adjust the block at HANDLEPTR to be SIZE bytes long. */
-extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
+extern __ptr_t r_re_alloc PP ((__ptr_t *__handleptr, __malloc_size_t __size));
#ifdef __cplusplus
#include <errno.h>
/* How to really get more memory. */
-__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
+#if defined(CYGWIN)
+extern __ptr_t bss_sbrk PP ((ptrdiff_t __size));
+extern int bss_sbrk_did_unexec;
+#endif
+__ptr_t (*__morecore) PP ((ptrdiff_t __size)) = __default_morecore;
/* Debugging hook for `malloc'. */
-__ptr_t (*__malloc_hook) __P ((__malloc_size_t __size));
+__ptr_t (*__malloc_hook) PP ((__malloc_size_t __size));
/* Pointer to the base of the first block. */
char *_heapbase;
__malloc_size_t __malloc_extra_blocks;
-void (*__malloc_initialize_hook) __P ((void));
-void (*__after_morecore_hook) __P ((void));
+void (*__malloc_initialize_hook) PP ((void));
+void (*__after_morecore_hook) PP ((void));
+
+#if defined GC_MALLOC_CHECK && defined GC_PROTECT_MALLOC_STATE
+
+/* Some code for hunting a bug writing into _heapinfo.
+
+ Call this macro with argument PROT non-zero to protect internal
+ malloc state against writing to it, call it with a zero argument to
+ make it readable and writable.
+
+ Note that this only works if BLOCKSIZE == page size, which is
+ the case on the i386. */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+static int state_protected_p;
+static __malloc_size_t last_state_size;
+static malloc_info *last_heapinfo;
+
+void
+protect_malloc_state (protect_p)
+ int protect_p;
+{
+ /* If _heapinfo has been relocated, make sure its old location
+ isn't left read-only; it will be reused by malloc. */
+ if (_heapinfo != last_heapinfo
+ && last_heapinfo
+ && state_protected_p)
+ mprotect (last_heapinfo, last_state_size, PROT_READ | PROT_WRITE);
+
+ last_state_size = _heaplimit * sizeof *_heapinfo;
+ last_heapinfo = _heapinfo;
+
+ if (protect_p != state_protected_p)
+ {
+ state_protected_p = protect_p;
+ if (mprotect (_heapinfo, last_state_size,
+ protect_p ? PROT_READ : PROT_READ | PROT_WRITE) != 0)
+ abort ();
+ }
+}
+
+#define PROTECT_MALLOC_STATE(PROT) protect_malloc_state(PROT)
+
+#else
+#define PROTECT_MALLOC_STATE(PROT) /* empty */
+#endif
/* Aligned allocation. */
-static __ptr_t align __P ((__malloc_size_t));
+static __ptr_t align PP ((__malloc_size_t));
static __ptr_t
align (size)
__malloc_size_t size;
__ptr_t result;
unsigned long int adj;
- result = (*__morecore) (size);
+ /* align accepts an unsigned argument, but __morecore accepts a
+ signed one. This could lead to trouble if SIZE overflows a
+ signed int type accepted by __morecore. We just punt in that
+ case, since they are requesting a ludicrous amount anyway. */
+ if ((__malloc_ptrdiff_t)size < 0)
+ result = 0;
+ else
+ result = (*__morecore) (size);
adj = (unsigned long int) ((unsigned long int) ((char *) result -
(char *) NULL)) % BLOCKSIZE;
if (adj != 0)
/* Get SIZE bytes, if we can get them starting at END.
Return the address of the space we got.
If we cannot get space at END, fail and return 0. */
-static __ptr_t get_contiguous_space __P ((__malloc_ptrdiff_t, __ptr_t));
+static __ptr_t get_contiguous_space PP ((__malloc_ptrdiff_t, __ptr_t));
static __ptr_t
get_contiguous_space (size, position)
__malloc_ptrdiff_t size;
/* This is called when `_heapinfo' and `heapsize' have just
been set to describe a new info table. Set up the table
to describe itself and account for it in the statistics. */
-static void register_heapinfo __P ((void));
+static void register_heapinfo PP ((void));
#ifdef __GNUC__
__inline__
#endif
if (__malloc_initialized)
return 0;
+#ifdef GC_MCHECK
+ mcheck (NULL);
+#endif
+
if (__malloc_initialize_hook)
(*__malloc_initialize_hook) ();
register_heapinfo ();
__malloc_initialized = 1;
+ PROTECT_MALLOC_STATE (1);
return 1;
}
/* Get neatly aligned memory, initializing or
growing the heap info table as necessary. */
-static __ptr_t morecore __P ((__malloc_size_t));
+static __ptr_t morecore PP ((__malloc_size_t));
static __ptr_t
morecore (size)
__malloc_size_t size;
if (result == NULL)
return NULL;
+ PROTECT_MALLOC_STATE (0);
+
/* Check if we need to grow the info table. */
if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize)
{
it can relocate or resize the info table. */
_heaplimit = 0;
_free_internal (oldinfo);
+ PROTECT_MALLOC_STATE (0);
/* The new heap limit includes the new table just allocated. */
_heaplimit = BLOCK ((char *) newinfo + heapsize * sizeof (malloc_info));
return NULL;
#endif
+ PROTECT_MALLOC_STATE (0);
+
if (size < sizeof (struct list))
size = sizeof (struct list);
{
/* No free fragments of the desired size, so get a new block
and break it into fragments, returning the first. */
+#ifdef GC_MALLOC_CHECK
+ result = _malloc_internal (BLOCKSIZE);
+ PROTECT_MALLOC_STATE (0);
+#else
result = malloc (BLOCKSIZE);
+#endif
if (result == NULL)
- return NULL;
+ {
+ PROTECT_MALLOC_STATE (1);
+ return NULL;
+ }
/* Link all fragments but the first into the free list. */
next = (struct list *) ((char *) result + (1 << log));
_heapinfo[block + blocks].busy.info.size = -blocks;
}
+ PROTECT_MALLOC_STATE (1);
return result;
}
#define __malloc_safe_bcopy safe_bcopy
#endif
/* This function is defined in realloc.c. */
-extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t));
+extern void __malloc_safe_bcopy PP ((__ptr_t, __ptr_t, __malloc_size_t));
#define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size))
#endif
#endif
/* Debugging hook for free. */
-void (*__free_hook) __P ((__ptr_t __ptr));
+void (*__free_hook) PP ((__ptr_t __ptr));
/* List of blocks allocated by memalign. */
struct alignlist *_aligned_blocks = NULL;
if (ptr == NULL)
return;
+ PROTECT_MALLOC_STATE (0);
+
for (l = _aligned_blocks; l != NULL; l = l->next)
if (l->aligned == ptr)
{
/* Allocate new space for the info table and move its data. */
newinfo = (malloc_info *) _malloc_internal (info_blocks
* BLOCKSIZE);
+ PROTECT_MALLOC_STATE (0);
memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE);
_heapinfo = newinfo;
_chunks_free -= BLOCKSIZE >> type;
_bytes_free -= BLOCKSIZE;
+#ifdef GC_MALLOC_CHECK
+ _free_internal (ADDRESS (block));
+#else
free (ADDRESS (block));
+#endif
}
else if (_heapinfo[block].busy.info.frag.nfree != 0)
{
}
break;
}
+
+ PROTECT_MALLOC_STATE (1);
}
/* Return memory to the heap. */
-void
+
+FREE_RETURN_TYPE
free (ptr)
__ptr_t ptr;
{
#endif /* emacs */
#ifndef memmove
-extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t));
+extern void __malloc_safe_bcopy PP ((__ptr_t, __ptr_t, __malloc_size_t));
#define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size))
#endif
#define min(A, B) ((A) < (B) ? (A) : (B))
/* Debugging hook for realloc. */
-__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
+__ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size));
/* Resize the given region to the new size, returning a pointer
to the (possibly moved) region. This is optimized for speed;
block = BLOCK (ptr);
+ PROTECT_MALLOC_STATE (0);
+
type = _heapinfo[block].busy.type;
switch (type)
{
_heaplimit = 0;
_free_internal (ptr);
result = _malloc_internal (size);
+ PROTECT_MALLOC_STATE (0);
if (_heaplimit == 0)
_heaplimit = oldlimit;
if (result == NULL)
break;
}
+ PROTECT_MALLOC_STATE (1);
return result;
}
systems with potentially hostile include files. */
#include <stddef.h>
-extern __ptr_t __sbrk __P ((ptrdiff_t increment));
+extern __ptr_t __sbrk PP ((ptrdiff_t increment));
#endif
#ifndef NULL
__default_morecore (increment)
__malloc_ptrdiff_t increment;
{
- __ptr_t result = (__ptr_t) __sbrk (increment);
+ __ptr_t result;
+#if defined(CYGWIN)
+ if (!bss_sbrk_did_unexec)
+ {
+ return bss_sbrk (increment);
+ }
+#endif
+ result = (__ptr_t) __sbrk (increment);
if (result == (__ptr_t) -1)
return NULL;
return result;
#else
-__ptr_t (*__memalign_hook) __P ((size_t __size, size_t __alignment));
+__ptr_t (*__memalign_hook) PP ((__malloc_size_t __size,
+ __malloc_size_t __alignment));
__ptr_t
memalign (alignment, size)
#if defined (__GLIBC__) && __GLIBC__ >= 2
/* __getpagesize is already declared in <unistd.h> with return type int */
#else
-extern size_t __getpagesize __P ((void));
+extern size_t __getpagesize PP ((void));
#endif
#else
#include "getpagesize.h"
}
#endif /* Not ELIDE_VALLOC. */
+
+#ifdef GC_MCHECK
+
+/* Standard debugging hooks for `malloc'.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifdef emacs
+#include <stdio.h>
+#else
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#include <stdio.h>
+#endif
+#endif
+
+/* Old hook values. */
+static void (*old_free_hook) __P ((__ptr_t ptr));
+static __ptr_t (*old_malloc_hook) __P ((__malloc_size_t size));
+static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size));
+
+/* Function to call when something awful happens. */
+static void (*abortfunc) __P ((enum mcheck_status));
+
+/* Arbitrary magical numbers. */
+#define MAGICWORD 0xfedabeeb
+#define MAGICFREE 0xd8675309
+#define MAGICBYTE ((char) 0xd7)
+#define MALLOCFLOOD ((char) 0x93)
+#define FREEFLOOD ((char) 0x95)
+
+struct hdr
+ {
+ __malloc_size_t size; /* Exact size requested by user. */
+ unsigned long int magic; /* Magic number to check header integrity. */
+ };
+
+#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
+#define flood memset
+#else
+static void flood __P ((__ptr_t, int, __malloc_size_t));
+static void
+flood (ptr, val, size)
+ __ptr_t ptr;
+ int val;
+ __malloc_size_t size;
+{
+ char *cp = ptr;
+ while (size--)
+ *cp++ = val;
+}
+#endif
+
+static enum mcheck_status checkhdr __P ((const struct hdr *));
+static enum mcheck_status
+checkhdr (hdr)
+ const struct hdr *hdr;
+{
+ enum mcheck_status status;
+ switch (hdr->magic)
+ {
+ default:
+ status = MCHECK_HEAD;
+ break;
+ case MAGICFREE:
+ status = MCHECK_FREE;
+ break;
+ case MAGICWORD:
+ if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+ status = MCHECK_TAIL;
+ else
+ status = MCHECK_OK;
+ break;
+ }
+ if (status != MCHECK_OK)
+ (*abortfunc) (status);
+ return status;
+}
+
+static void freehook __P ((__ptr_t));
+static void
+freehook (ptr)
+ __ptr_t ptr;
+{
+ struct hdr *hdr;
+
+ if (ptr)
+ {
+ hdr = ((struct hdr *) ptr) - 1;
+ checkhdr (hdr);
+ hdr->magic = MAGICFREE;
+ flood (ptr, FREEFLOOD, hdr->size);
+ }
+ else
+ hdr = NULL;
+
+ __free_hook = old_free_hook;
+ free (hdr);
+ __free_hook = freehook;
+}
+
+static __ptr_t mallochook __P ((__malloc_size_t));
+static __ptr_t
+mallochook (size)
+ __malloc_size_t size;
+{
+ struct hdr *hdr;
+
+ __malloc_hook = old_malloc_hook;
+ hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
+ __malloc_hook = mallochook;
+ if (hdr == NULL)
+ return NULL;
+
+ hdr->size = size;
+ hdr->magic = MAGICWORD;
+ ((char *) &hdr[1])[size] = MAGICBYTE;
+ flood ((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
+ return (__ptr_t) (hdr + 1);
+}
+
+static __ptr_t reallochook __P ((__ptr_t, __malloc_size_t));
+static __ptr_t
+reallochook (ptr, size)
+ __ptr_t ptr;
+ __malloc_size_t size;
+{
+ struct hdr *hdr = NULL;
+ __malloc_size_t osize = 0;
+
+ if (ptr)
+ {
+ hdr = ((struct hdr *) ptr) - 1;
+ osize = hdr->size;
+
+ checkhdr (hdr);
+ if (size < osize)
+ flood ((char *) ptr + size, FREEFLOOD, osize - size);
+ }
+
+ __free_hook = old_free_hook;
+ __malloc_hook = old_malloc_hook;
+ __realloc_hook = old_realloc_hook;
+ hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1);
+ __free_hook = freehook;
+ __malloc_hook = mallochook;
+ __realloc_hook = reallochook;
+ if (hdr == NULL)
+ return NULL;
+
+ hdr->size = size;
+ hdr->magic = MAGICWORD;
+ ((char *) &hdr[1])[size] = MAGICBYTE;
+ if (size > osize)
+ flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
+ return (__ptr_t) (hdr + 1);
+}
+
+static void
+mabort (status)
+ enum mcheck_status status;
+{
+ const char *msg;
+ switch (status)
+ {
+ case MCHECK_OK:
+ msg = "memory is consistent, library is buggy";
+ break;
+ case MCHECK_HEAD:
+ msg = "memory clobbered before allocated block";
+ break;
+ case MCHECK_TAIL:
+ msg = "memory clobbered past end of allocated block";
+ break;
+ case MCHECK_FREE:
+ msg = "block freed twice";
+ break;
+ default:
+ msg = "bogus mcheck_status, library is buggy";
+ break;
+ }
+#ifdef __GNU_LIBRARY__
+ __libc_fatal (msg);
+#else
+ fprintf (stderr, "mcheck: %s\n", msg);
+ fflush (stderr);
+ abort ();
+#endif
+}
+
+static int mcheck_used = 0;
+
+int
+mcheck (func)
+ void (*func) __P ((enum mcheck_status));
+{
+ abortfunc = (func != NULL) ? func : &mabort;
+
+ /* These hooks may not be safely inserted if malloc is already in use. */
+ if (!__malloc_initialized && !mcheck_used)
+ {
+ old_free_hook = __free_hook;
+ __free_hook = freehook;
+ old_malloc_hook = __malloc_hook;
+ __malloc_hook = mallochook;
+ old_realloc_hook = __realloc_hook;
+ __realloc_hook = reallochook;
+ mcheck_used = 1;
+ }
+
+ return mcheck_used ? 0 : -1;
+}
+
+enum mcheck_status
+mprobe (__ptr_t ptr)
+{
+ return mcheck_used ? checkhdr (ptr) : MCHECK_DISABLED;
+}
+
+#endif /* GC_MCHECK */
+
+/* arch-tag: 93dce5c0-f49a-41b5-86b1-f91c4169c02e
+ (do not change this comment) */