]> git.eshelyaron.com Git - emacs.git/commitdiff
(state_protected_p, last_state_size, last_heapinfo)
authorGerd Moellmann <gerd@gnu.org>
Tue, 24 Oct 2000 12:41:23 +0000 (12:41 +0000)
committerGerd Moellmann <gerd@gnu.org>
Tue, 24 Oct 2000 12:41:23 +0000 (12:41 +0000)
[GC_MALLOC_CHECK && GC_PROTECT_MALLOC_STATE]: New variables.
(protect_malloc_state) [GC_MALLOC_CHECK &&
GC_PROTECT_MALLOC_STATE]: New function.
(PROTECT_MALLOC_STATE): New macro.
(__malloc_initialize, morecore, _malloc_internal)
(_free_internal) _realloc_internal): Use it to make _heapinfo
read-only outside of gmalloc.

src/ChangeLog
src/gmalloc.c

index dbe7e11c6f5ae8e9d6ca5a5e9de85015b11eb515..6f4ba7a5b093bc7ffc64b624fc8d5ae6a1347d47 100644 (file)
@@ -1,5 +1,14 @@
 2000-10-24  Gerd Moellmann  <gerd@gnu.org>
 
+       * gmalloc.c (state_protected_p, last_state_size, last_heapinfo)
+       [GC_MALLOC_CHECK && GC_PROTECT_MALLOC_STATE]: New variables.
+       (protect_malloc_state) [GC_MALLOC_CHECK &&
+       GC_PROTECT_MALLOC_STATE]: New function.
+       (PROTECT_MALLOC_STATE): New macro.
+       (__malloc_initialize, morecore, _malloc_internal)
+       (_free_internal) _realloc_internal): Use it to make _heapinfo
+       read-only outside of gmalloc.
+
        * keymap.c: Update copyright.
 
        * .gdbinit (xbacktrace): Handle case that $bt->function isn't
index 2ce168c71c8a748e983a1d6938d986bc984a6de7..e7cc2c3947eb7cd58a77dd8e211f1b165b16f73b 100644 (file)
@@ -380,6 +380,53 @@ __malloc_size_t __malloc_extra_blocks;
 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 PP ((__malloc_size_t));
@@ -492,6 +539,7 @@ __malloc_initialize ()
   register_heapinfo ();
 
   __malloc_initialized = 1;
+  PROTECT_MALLOC_STATE (1);
   return 1;
 }
 
@@ -516,6 +564,8 @@ morecore (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)
     {
@@ -599,6 +649,7 @@ morecore (size)
         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));
@@ -632,6 +683,8 @@ _malloc_internal (size)
     return NULL;
 #endif
 
+  PROTECT_MALLOC_STATE (0);
+
   if (size < sizeof (struct list))
     size = sizeof (struct list);
 
@@ -680,11 +733,15 @@ _malloc_internal (size)
             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));
@@ -803,6 +860,7 @@ _malloc_internal (size)
        _heapinfo[block + blocks].busy.info.size = -blocks;
     }
 
+  PROTECT_MALLOC_STATE (1);
   return result;
 }
 
@@ -913,6 +971,8 @@ _free_internal (ptr)
   if (ptr == NULL)
     return;
 
+  PROTECT_MALLOC_STATE (0);
+  
   for (l = _aligned_blocks; l != NULL; l = l->next)
     if (l->aligned == ptr)
       {
@@ -1035,6 +1095,7 @@ _free_internal (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;
 
@@ -1133,6 +1194,8 @@ _free_internal (ptr)
        }
       break;
     }
+  
+  PROTECT_MALLOC_STATE (1);
 }
 
 /* Return memory to the heap.  */
@@ -1296,6 +1359,8 @@ _realloc_internal (ptr, size)
 
   block = BLOCK (ptr);
 
+  PROTECT_MALLOC_STATE (0);
+  
   type = _heapinfo[block].busy.type;
   switch (type)
     {
@@ -1344,6 +1409,7 @@ _realloc_internal (ptr, size)
          _heaplimit = 0;
          _free_internal (ptr);
          result = _malloc_internal (size);
+         PROTECT_MALLOC_STATE (0);
          if (_heaplimit == 0)
            _heaplimit = oldlimit;
          if (result == NULL)
@@ -1387,6 +1453,7 @@ _realloc_internal (ptr, size)
       break;
     }
 
+  PROTECT_MALLOC_STATE (1);
   return result;
 }