]> code.delx.au - gnu-emacs/blobdiff - src/gmalloc.c
* macfns.c (Fx_display_color_cells): Do not limit return value to 256.
[gnu-emacs] / src / gmalloc.c
index e7cc2c3947eb7cd58a77dd8e211f1b165b16f73b..eae83a74eb6944c96354015895caf0e151ef4487 100644 (file)
@@ -36,8 +36,9 @@ Cambridge, MA 02139, USA.
 #include <config.h>
 #endif
 
-#if defined __cplusplus || (defined (__STDC__) && __STDC__) || \
-  defined STDC_HEADERS || defined PROTOTYPES
+#if ((defined __cplusplus || (defined (__STDC__) && __STDC__) \
+      || defined STDC_HEADERS || defined PROTOTYPES) \
+     && ! defined (BROKEN_PROTOTYPES))
 #undef PP
 #define        PP(args)        args
 #undef __ptr_t
@@ -84,7 +85,15 @@ extern "C"
 #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
 
@@ -343,6 +352,10 @@ Cambridge, MA 02139, USA.
 #include <errno.h>
 
 /* How to really get more memory.  */
+#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'.  */
@@ -411,7 +424,7 @@ protect_malloc_state (protect_p)
 
   last_state_size = _heaplimit * sizeof *_heapinfo;
   last_heapinfo   = _heapinfo;
-  
+
   if (protect_p != state_protected_p)
     {
       state_protected_p = protect_p;
@@ -437,7 +450,14 @@ align (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)
@@ -522,6 +542,10 @@ __malloc_initialize ()
   if (__malloc_initialized)
     return 0;
 
+#ifdef GC_MCHECK
+  mcheck (NULL);
+#endif
+
   if (__malloc_initialize_hook)
     (*__malloc_initialize_hook) ();
 
@@ -972,7 +996,7 @@ _free_internal (ptr)
     return;
 
   PROTECT_MALLOC_STATE (0);
-  
+
   for (l = _aligned_blocks; l != NULL; l = l->next)
     if (l->aligned == ptr)
       {
@@ -1194,7 +1218,7 @@ _free_internal (ptr)
        }
       break;
     }
-  
+
   PROTECT_MALLOC_STATE (1);
 }
 
@@ -1360,7 +1384,7 @@ _realloc_internal (ptr, size)
   block = BLOCK (ptr);
 
   PROTECT_MALLOC_STATE (0);
-  
+
   type = _heapinfo[block].busy.type;
   switch (type)
     {
@@ -1552,7 +1576,14 @@ __ptr_t
 __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;
@@ -1586,7 +1617,8 @@ Cambridge, MA 02139, USA.  */
 
 #else
 
-__ptr_t (*__memalign_hook) PP ((size_t __size, size_t __alignment));
+__ptr_t (*__memalign_hook) PP ((__malloc_size_t __size,
+                               __malloc_size_t __alignment));
 
 __ptr_t
 memalign (alignment, size)
@@ -1718,3 +1750,245 @@ valloc (size)
 }
 
 #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) */