aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/sys/linux/mcheck.c
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2002-07-15 20:16:32 +0000
committerJeff Johnston <jjohnstn@redhat.com>2002-07-15 20:16:32 +0000
commitedba3282e8c83ef5e9e821fb158183886913be13 (patch)
tree19ab6ac7d819dc75966dfbfa5150fe57d742ef40 /newlib/libc/sys/linux/mcheck.c
parent315fb3afb0197ff082ac5f7ec7a4b0ed71802f55 (diff)
downloadnewlib-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.c356
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;
+}