diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2002-07-15 20:16:32 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2002-07-15 20:16:32 +0000 |
commit | edba3282e8c83ef5e9e821fb158183886913be13 (patch) | |
tree | 19ab6ac7d819dc75966dfbfa5150fe57d742ef40 /newlib/libc/sys/linux/mcheck.c | |
parent | 315fb3afb0197ff082ac5f7ec7a4b0ed71802f55 (diff) | |
download | newlib-edba3282e8c83ef5e9e821fb158183886913be13.zip newlib-edba3282e8c83ef5e9e821fb158183886913be13.tar.gz newlib-edba3282e8c83ef5e9e821fb158183886913be13.tar.bz2 |
2002-07-15 Jeff Johnston <jjohnstn@redhat.com>
* libc/sys/linux/Makefile.am: Add new files.
* libc/sys/linux/Makefile.in: Regenerated.
* libc/sys/linux/bp-sym.h: Moved to include directory.
* libc/sys/linux/mmap.c: Add weak aliases: __mmap, __munmap, __mremap.
* libc/sys/linux/inode.c: Set _LIBC to 1.
* libc/sys/linux/mq_close.c: Ditto.
* libc/sys/linux/mq_getattr.c: Ditto.
* libc/sys/linux/mq_open.c: Ditto.
* libc/sys/linux/mq_receive.c: Ditto.
* libc/sys/linux/mq_send.c: Ditto.
* libc/sys/linux/mq_setattr.c: Ditto.
* libc/sys/linux/mq_unlink.c: Ditto.
* libc/sys/linux/calloc.c: New file.
* libc/sys/linux/callocr.c: Ditto.
* libc/sys/linux/cfreer.c: Ditto.
* libc/sys/linux/config.h: Ditto.
* libc/sys/linux/free.c: Ditto.
* libc/sys/linux/freer.c: Ditto.
* libc/sys/linux/msize.c: Ditto.
* libc/sys/linux/msizer.c: Ditto.
* libc/sys/linux/mstats.c: Ditto.
* libc/sys/linux/mtrim.c: Ditto.
* libc/sys/linux/mtrimr.c: Ditto.
* libc/sys/linux/pvallocr.c: Ditto.
* libc/sys/linux/realloc.c: Ditto.
* libc/sys/linux/reallocr.c: Ditto.
* libc/sys/linux/thread-m.h: Ditto.
* libc/sys/linux/vallocr.c: Ditto.
* libc/sys/linux/bp-checks.h: Ditto.
* libc/sys/linux/libc-symbols.h: Ditto.
* libc/sys/linux/libc-tsd.h: Ditto.
* libc/sys/linux/libintl.h: Ditto.
* libc/sys/linux/malign.c: Ditto.
* libc/sys/linux/malignr.c: Ditto.
* libc/sys/linux/mallinfor.c: Ditto.
* libc/sys/linux/malloc.c: Ditto.
* libc/sys/linux/mallocr.c: Ditto.
* libc/sys/linux/malloptr.c: Ditto.
* libc/sys/linux/mallstatsr.c: Ditto.
* libc/sys/linux/mcheck.c: Ditto.
* libc/sys/linux/mhooks.h: Ditto.
* libc/sys/linux/include/bp-sym.h: Ditto.
* libc/sys/linux/include/malloc.h: Ditto.
* libc/sys/linux/include/mcheck.h: Ditto.
* libc/sys/linux/machine/i386/getpagesize.c: New file.
* libc/sys/linux/machine/i386/Makefile.am: Add getpagesize.c.
* libc/sys/linux/machine/i386/Makefile.in: Regenerated.
* libc/sys/linux/machine/i386/sysdep.h: New file.
* libc/sys/linux/machine/i386/weakalias.h: Add weak_function support.
* libc/sys/linux/sys/dirent.h: Set _LIBC to 1.
* libc/sys/linux/sys/types.h: Add new types.
Diffstat (limited to 'newlib/libc/sys/linux/mcheck.c')
-rw-r--r-- | newlib/libc/sys/linux/mcheck.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/newlib/libc/sys/linux/mcheck.c b/newlib/libc/sys/linux/mcheck.c new file mode 100644 index 0000000..9e42dcc --- /dev/null +++ b/newlib/libc/sys/linux/mcheck.c @@ -0,0 +1,356 @@ +/* Standard debugging hooks for `malloc'. + Copyright (C) 1990-1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written May 1989 by Mike Haertel. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Modified for newlib, July 9, 2002 by Jeff Johnston */ + +#ifndef _MALLOC_INTERNAL +# define _MALLOC_INTERNAL +# include <malloc.h> +# include <mcheck.h> +# include <stdint.h> +# include <stdio.h> +# include <stdlib.h> +# include <libintl.h> +# include <sys/cdefs.h> +#endif + +/* Old hook values. */ +static void (*old_free_hook) __P ((__ptr_t ptr, __const __ptr_t)); +static __ptr_t (*old_malloc_hook) __P ((__malloc_size_t size, const __ptr_t)); +static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size, + __const __ptr_t)); + +/* 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. */ + struct hdr *prev; + struct hdr *next; + }; + +/* This is the beginning of the list of all memory blocks allocated. + It is only constructed if the pedantic testing is requested. */ +static struct hdr *root; + +static int mcheck_used; + +/* Nonzero if pedentic checking of all blocks is requested. */ +static int pedantic; + +#if defined _LIBC || defined STDC_HEADERS || defined USG +# include <string.h> +# 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; + + if (!mcheck_used) + /* Maybe the mcheck used is disabled? This happens when we find + an error and report it. */ + return MCHECK_OK; + + switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next)) + { + 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) + { + mcheck_used = 0; + (*abortfunc) (status); + mcheck_used = 1; + } + return status; +} + +void +mcheck_check_all () +{ + /* Walk through all the active blocks and test whether they were tempered + with. */ + struct hdr *runp = root; + + /* Temporarily turn off the checks. */ + pedantic = 0; + + while (runp != NULL) + { + (void) checkhdr (runp); + + runp = runp->next; + } + + /* Turn checks on again. */ + pedantic = 1; +} + +static void unlink_blk __P ((struct hdr *ptr)); +static void +unlink_blk (ptr) + struct hdr *ptr; +{ + if (ptr->next != NULL) + { + ptr->next->prev = ptr->prev; + ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev + + (uintptr_t) ptr->next->next); + } + if (ptr->prev != NULL) + { + ptr->prev->next = ptr->next; + ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev + + (uintptr_t) ptr->prev->next); + } + else + root = ptr->next; +} + +static void link_blk __P ((struct hdr *ptr)); +static void +link_blk (hdr) + struct hdr *hdr; +{ + hdr->prev = NULL; + hdr->next = root; + root = hdr; + hdr->magic = MAGICWORD ^ (uintptr_t) hdr->next; + + /* And the next block. */ + if (hdr->next != NULL) + { + hdr->next->prev = hdr; + hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr + + (uintptr_t) hdr->next->next); + } +} + +static void freehook __P ((__ptr_t, const __ptr_t)); +static void +freehook (ptr, caller) + __ptr_t ptr; + const __ptr_t caller; +{ + if (pedantic) + mcheck_check_all (); + if (ptr) + { + struct hdr *hdr = ((struct hdr *) ptr) - 1; + checkhdr (hdr); + hdr->magic = MAGICFREE; + unlink_blk (hdr); + hdr->prev = hdr->next = NULL; + flood (ptr, FREEFLOOD, hdr->size); + ptr = (__ptr_t) hdr; + } + __free_hook = old_free_hook; + if (old_free_hook != NULL) + (*old_free_hook) (ptr, caller); + else + free (ptr); + __free_hook = freehook; +} + +static __ptr_t mallochook __P ((__malloc_size_t, const __ptr_t)); +static __ptr_t +mallochook (size, caller) + __malloc_size_t size; + const __ptr_t caller; +{ + struct hdr *hdr; + + if (pedantic) + mcheck_check_all (); + + __malloc_hook = old_malloc_hook; + if (old_malloc_hook != NULL) + hdr = (struct hdr *) (*old_malloc_hook) (sizeof (struct hdr) + size + 1, + caller); + else + hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1); + __malloc_hook = mallochook; + if (hdr == NULL) + return NULL; + + hdr->size = size; + link_blk (hdr); + ((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, const __ptr_t)); +static __ptr_t +reallochook (ptr, size, caller) + __ptr_t ptr; + __malloc_size_t size; + const __ptr_t caller; +{ + struct hdr *hdr; + __malloc_size_t osize; + + if (pedantic) + mcheck_check_all (); + + if (ptr) + { + hdr = ((struct hdr *) ptr) - 1; + osize = hdr->size; + + checkhdr (hdr); + unlink_blk (hdr); + if (size < osize) + flood ((char *) ptr + size, FREEFLOOD, osize - size); + } + else + { + osize = 0; + hdr = NULL; + } + __free_hook = old_free_hook; + __malloc_hook = old_malloc_hook; + __realloc_hook = old_realloc_hook; + if (old_realloc_hook != NULL) + hdr = (struct hdr *) (*old_realloc_hook) ((__ptr_t) hdr, + sizeof (struct hdr) + size + 1, + caller); + else + 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; + link_blk (hdr); + ((char *) &hdr[1])[size] = MAGICBYTE; + if (size > osize) + flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize); + return (__ptr_t) (hdr + 1); +} + +static void mabort __P ((enum mcheck_status status)) + __attribute__ ((noreturn)); +static void +mabort (status) + enum mcheck_status status; +{ + const char *msg; + switch (status) + { + case MCHECK_OK: + msg = _("memory is consistent, library is buggy\n"); + break; + case MCHECK_HEAD: + msg = _("memory clobbered before allocated block\n"); + break; + case MCHECK_TAIL: + msg = _("memory clobbered past end of allocated block\n"); + break; + case MCHECK_FREE: + msg = _("block freed twice\n"); + break; + default: + msg = _("bogus mcheck_status, library is buggy\n"); + break; + } + fprintf (stderr, "mcheck: %s", msg); + fflush (stderr); + abort (); +} + +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 <= 0 && !mcheck_used) + { + /* We call malloc() once here to ensure it is initialized. */ + void *p = malloc (0); + free (p); + + 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; +} + +int +mcheck_pedantic (func) + void (*func) __P ((enum mcheck_status)); +{ + int res = mcheck (func); + if (res == 0) + pedantic = 1; + return res; +} + +enum mcheck_status +mprobe (__ptr_t ptr) +{ + return mcheck_used ? checkhdr (((struct hdr *) ptr) - 1) : MCHECK_DISABLED; +} |