OSDN Git Service

* common.opt (Wmudflap): New option.
[pf3gnuchains/gcc-fork.git] / libmudflap / mf-hooks1.c
index 7199472..acdbc44 100644 (file)
@@ -1,5 +1,5 @@
 /* Mudflap: narrow-pointer bounds-checking by tree rewriting.
 /* Mudflap: narrow-pointer bounds-checking by tree rewriting.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Frank Ch. Eigler <fche@redhat.com>
    and Graydon Hoare <graydon@redhat.com>
 
    Contributed by Frank Ch. Eigler <fche@redhat.com>
    and Graydon Hoare <graydon@redhat.com>
 
@@ -26,8 +26,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 #include "config.h"
 
 
 #include "config.h"
@@ -42,7 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #if !defined(__FreeBSD__)  && !defined(__APPLE__)
 #define _POSIX_SOURCE
 #endif /* Some BSDs break <sys/socket.h> if this is defined. */
 #if !defined(__FreeBSD__)  && !defined(__APPLE__)
 #define _POSIX_SOURCE
 #endif /* Some BSDs break <sys/socket.h> if this is defined. */
-#define _GNU_SOURCE 
+#define _GNU_SOURCE
 #define _XOPEN_SOURCE
 #define _BSD_TYPES
 #define __EXTENSIONS__
 #define _XOPEN_SOURCE
 #define _BSD_TYPES
 #define __EXTENSIONS__
@@ -74,18 +74,32 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    use plain macros in mf-runtime.h.  */
 
 
    use plain macros in mf-runtime.h.  */
 
 
-#ifdef WRAP_malloc
-
 #if PIC
 #if PIC
+
+enum { BS = 4096, NB=10 };
+static char __mf_0fn_bufs[NB][BS];
+static unsigned __mf_0fn_bufs_used[NB];
+
+
 /* A special bootstrap variant. */
 void *
 __mf_0fn_malloc (size_t c)
 {
 /* A special bootstrap variant. */
 void *
 __mf_0fn_malloc (size_t c)
 {
-  /* fprintf (stderr, "0fn malloc c=%lu\n", c); */
+  unsigned i;
+
+  for (i=0; i<NB; i++)
+    {
+      if (! __mf_0fn_bufs_used[i] && c < BS)
+       {
+         __mf_0fn_bufs_used[i] = 1;
+         return & __mf_0fn_bufs[i][0];
+       }
+    }
   return NULL;
 }
 #endif
 
   return NULL;
 }
 #endif
 
+
 #undef malloc
 WRAPPER(void *, malloc, size_t c)
 {
 #undef malloc
 WRAPPER(void *, malloc, size_t c)
 {
@@ -94,11 +108,13 @@ WRAPPER(void *, malloc, size_t c)
   void *result;
   BEGIN_PROTECT (malloc, c);
 
   void *result;
   BEGIN_PROTECT (malloc, c);
 
-  size_with_crumple_zones = 
+  size_with_crumple_zones =
     CLAMPADD(c,CLAMPADD(__mf_opts.crumple_zone,
                        __mf_opts.crumple_zone));
     CLAMPADD(c,CLAMPADD(__mf_opts.crumple_zone,
                        __mf_opts.crumple_zone));
+  BEGIN_MALLOC_PROTECT ();
   result = (char *) CALL_REAL (malloc, size_with_crumple_zones);
   result = (char *) CALL_REAL (malloc, size_with_crumple_zones);
-  
+  END_MALLOC_PROTECT ();
+
   if (LIKELY(result))
     {
       result += __mf_opts.crumple_zone;
   if (LIKELY(result))
     {
       result += __mf_opts.crumple_zone;
@@ -108,34 +124,18 @@ WRAPPER(void *, malloc, size_t c)
 
   return result;
 }
 
   return result;
 }
-#endif
-
 
 
-#ifdef WRAP_calloc
 
 #ifdef PIC
 /* A special bootstrap variant. */
 void *
 __mf_0fn_calloc (size_t c, size_t n)
 {
 
 #ifdef PIC
 /* A special bootstrap variant. */
 void *
 __mf_0fn_calloc (size_t c, size_t n)
 {
-  enum foo { BS = 4096, NB=10 };
-  static char bufs[NB][BS];
-  static unsigned bufs_used[NB];
-  unsigned i;
-
-  /* fprintf (stderr, "0fn calloc c=%lu n=%lu\n", c, n); */
-  for (i=0; i<NB; i++)
-    {
-      if (! bufs_used[i] && (c*n) < BS)
-       {
-         bufs_used[i] = 1;
-         return & bufs[i][0];
-       }
-    }
-  return NULL;
+  return __mf_0fn_malloc (c * n);
 }
 #endif
 
 }
 #endif
 
+
 #undef calloc
 WRAPPER(void *, calloc, size_t c, size_t n)
 {
 #undef calloc
 WRAPPER(void *, calloc, size_t c, size_t n)
 {
@@ -145,28 +145,28 @@ WRAPPER(void *, calloc, size_t c, size_t n)
   DECLARE(void *, memset, void *, int, size_t);
   char *result;
   BEGIN_PROTECT (calloc, c, n);
   DECLARE(void *, memset, void *, int, size_t);
   char *result;
   BEGIN_PROTECT (calloc, c, n);
-  
-  size_with_crumple_zones = 
+
+  size_with_crumple_zones =
     CLAMPADD((c * n), /* XXX: CLAMPMUL */
             CLAMPADD(__mf_opts.crumple_zone,
     CLAMPADD((c * n), /* XXX: CLAMPMUL */
             CLAMPADD(__mf_opts.crumple_zone,
-                     __mf_opts.crumple_zone));  
+                     __mf_opts.crumple_zone));
+  BEGIN_MALLOC_PROTECT ();
   result = (char *) CALL_REAL (malloc, size_with_crumple_zones);
   result = (char *) CALL_REAL (malloc, size_with_crumple_zones);
-  
+  END_MALLOC_PROTECT ();
+
   if (LIKELY(result))
     memset (result, 0, size_with_crumple_zones);
   if (LIKELY(result))
     memset (result, 0, size_with_crumple_zones);
-  
+
   if (LIKELY(result))
     {
       result += __mf_opts.crumple_zone;
       __mf_register (result, c*n /* XXX: clamp */, __MF_TYPE_HEAP_I, "calloc region");
       /* XXX: register __MF_TYPE_NOACCESS for crumple zones.  */
     }
   if (LIKELY(result))
     {
       result += __mf_opts.crumple_zone;
       __mf_register (result, c*n /* XXX: clamp */, __MF_TYPE_HEAP_I, "calloc region");
       /* XXX: register __MF_TYPE_NOACCESS for crumple zones.  */
     }
-  
+
   return result;
 }
   return result;
 }
-#endif
 
 
-#ifdef WRAP_realloc
 
 #if PIC
 /* A special bootstrap variant. */
 
 #if PIC
 /* A special bootstrap variant. */
@@ -177,6 +177,7 @@ __mf_0fn_realloc (void *buf, size_t c)
 }
 #endif
 
 }
 #endif
 
+
 #undef realloc
 WRAPPER(void *, realloc, void *buf, size_t c)
 {
 #undef realloc
 WRAPPER(void *, realloc, void *buf, size_t c)
 {
@@ -190,21 +191,24 @@ WRAPPER(void *, realloc, void *buf, size_t c)
   if (LIKELY(buf))
     base -= __mf_opts.crumple_zone;
 
   if (LIKELY(buf))
     base -= __mf_opts.crumple_zone;
 
-  size_with_crumple_zones = 
+  size_with_crumple_zones =
     CLAMPADD(c, CLAMPADD(__mf_opts.crumple_zone,
                         __mf_opts.crumple_zone));
     CLAMPADD(c, CLAMPADD(__mf_opts.crumple_zone,
                         __mf_opts.crumple_zone));
+  BEGIN_MALLOC_PROTECT ();
   result = (char *) CALL_REAL (realloc, base, size_with_crumple_zones);
   result = (char *) CALL_REAL (realloc, base, size_with_crumple_zones);
+  END_MALLOC_PROTECT ();
 
   /* Ensure heap wiping doesn't occur during this peculiar
      unregister/reregister pair.  */
   LOCKTH ();
 
   /* Ensure heap wiping doesn't occur during this peculiar
      unregister/reregister pair.  */
   LOCKTH ();
-  __mf_state = reentrant;
+  __mf_set_state (reentrant);
   saved_wipe_heap = __mf_opts.wipe_heap;
   __mf_opts.wipe_heap = 0;
 
   if (LIKELY(buf))
   saved_wipe_heap = __mf_opts.wipe_heap;
   __mf_opts.wipe_heap = 0;
 
   if (LIKELY(buf))
-    __mfu_unregister (buf, 0);
-  
+    __mfu_unregister (buf, 0, __MF_TYPE_HEAP_I);
+  /* NB: underlying region may have been __MF_TYPE_HEAP. */
+
   if (LIKELY(result))
     {
       result += __mf_opts.crumple_zone;
   if (LIKELY(result))
     {
       result += __mf_opts.crumple_zone;
@@ -215,16 +219,13 @@ WRAPPER(void *, realloc, void *buf, size_t c)
   /* Restore previous setting.  */
   __mf_opts.wipe_heap = saved_wipe_heap;
 
   /* Restore previous setting.  */
   __mf_opts.wipe_heap = saved_wipe_heap;
 
-  __mf_state = active;
+  __mf_set_state (active);
   UNLOCKTH ();
 
   return result;
 }
   UNLOCKTH ();
 
   return result;
 }
-#endif
 
 
 
 
-#ifdef WRAP_free
-
 #if PIC
 /* A special bootstrap variant. */
 void
 #if PIC
 /* A special bootstrap variant. */
 void
@@ -241,23 +242,37 @@ WRAPPER(void, free, void *buf)
   static void *free_queue [__MF_FREEQ_MAX];
   static unsigned free_ptr = 0;
   static int freeq_initialized = 0;
   static void *free_queue [__MF_FREEQ_MAX];
   static unsigned free_ptr = 0;
   static int freeq_initialized = 0;
-  DECLARE(void, free, void *);  
+  DECLARE(void, free, void *);
+
   BEGIN_PROTECT (free, buf);
 
   if (UNLIKELY(buf == NULL))
     return;
 
   BEGIN_PROTECT (free, buf);
 
   if (UNLIKELY(buf == NULL))
     return;
 
+#if PIC
+  /* Check whether the given buffer might have come from a
+     __mf_0fn_malloc/calloc call that for whatever reason was not
+     redirected back to __mf_0fn_free.  If so, we just ignore the
+     call. */
+  if (UNLIKELY((uintptr_t) buf >= (uintptr_t) __mf_0fn_bufs &&
+               (uintptr_t) buf < ((uintptr_t) __mf_0fn_bufs + sizeof(__mf_0fn_bufs))))
+  {
+    VERBOSE_TRACE ("skipping free of boot (0fn) alloc buffer %p\n", buf);
+    return;
+  }
+#endif
+
   LOCKTH ();
   if (UNLIKELY(!freeq_initialized))
     {
   LOCKTH ();
   if (UNLIKELY(!freeq_initialized))
     {
-      memset (free_queue, 0, 
+      memset (free_queue, 0,
                     __MF_FREEQ_MAX * sizeof (void *));
       freeq_initialized = 1;
     }
   UNLOCKTH ();
 
                     __MF_FREEQ_MAX * sizeof (void *));
       freeq_initialized = 1;
     }
   UNLOCKTH ();
 
-  __mf_unregister (buf, 0);
+  __mf_unregister (buf, 0, __MF_TYPE_HEAP_I);
+  /* NB: underlying region may have been __MF_TYPE_HEAP. */
 
   if (UNLIKELY(__mf_opts.free_queue_length > 0))
     {
 
   if (UNLIKELY(__mf_opts.free_queue_length > 0))
     {
@@ -275,14 +290,16 @@ WRAPPER(void, free, void *buf)
        {
          if (__mf_opts.trace_mf_calls)
            {
        {
          if (__mf_opts.trace_mf_calls)
            {
-             VERBOSE_TRACE ("freeing deferred pointer %p (crumple %u)\n", 
+             VERBOSE_TRACE ("freeing deferred pointer %p (crumple %u)\n",
                             (void *) freeme,
                             __mf_opts.crumple_zone);
            }
                             (void *) freeme,
                             __mf_opts.crumple_zone);
            }
+         BEGIN_MALLOC_PROTECT ();
          CALL_REAL (free, freeme);
          CALL_REAL (free, freeme);
+         END_MALLOC_PROTECT ();
        }
        }
-    } 
-  else 
+    }
+  else
     {
       /* back pointer up a bit to the beginning of crumple zone */
       char *base = (char *)buf;
     {
       /* back pointer up a bit to the beginning of crumple zone */
       char *base = (char *)buf;
@@ -290,17 +307,20 @@ WRAPPER(void, free, void *buf)
       if (__mf_opts.trace_mf_calls)
        {
          VERBOSE_TRACE ("freeing pointer %p = %p - %u\n",
       if (__mf_opts.trace_mf_calls)
        {
          VERBOSE_TRACE ("freeing pointer %p = %p - %u\n",
-                        (void *) base, 
-                        (void *) buf, 
+                        (void *) base,
+                        (void *) buf,
                         __mf_opts.crumple_zone);
        }
                         __mf_opts.crumple_zone);
        }
+      BEGIN_MALLOC_PROTECT ();
       CALL_REAL (free, base);
       CALL_REAL (free, base);
+      END_MALLOC_PROTECT ();
     }
 }
     }
 }
-#endif
 
 
 
 
-#ifdef WRAP_mmap
+/* We can only wrap mmap if the target supports it.  Likewise for munmap.
+   We assume we have both if we have mmap.  */
+#ifdef HAVE_MMAP
 
 #if PIC
 /* A special bootstrap variant. */
 
 #if PIC
 /* A special bootstrap variant. */
@@ -313,20 +333,20 @@ __mf_0fn_mmap (void *start, size_t l, int prot, int f, int fd, off_t off)
 
 
 #undef mmap
 
 
 #undef mmap
-WRAPPER(void *, mmap, 
-       void  *start,  size_t length, int prot, 
+WRAPPER(void *, mmap,
+       void  *start,  size_t length, int prot,
        int flags, int fd, off_t offset)
 {
        int flags, int fd, off_t offset)
 {
-  DECLARE(void *, mmap, void *, size_t, int, 
+  DECLARE(void *, mmap, void *, size_t, int,
                            int, int, off_t);
   void *result;
   BEGIN_PROTECT (mmap, start, length, prot, flags, fd, offset);
 
                            int, int, off_t);
   void *result;
   BEGIN_PROTECT (mmap, start, length, prot, flags, fd, offset);
 
-  result = CALL_REAL (mmap, start, length, prot, 
+  result = CALL_REAL (mmap, start, length, prot,
                        flags, fd, offset);
 
   /*
                        flags, fd, offset);
 
   /*
-  VERBOSE_TRACE ("mmap (%08lx, %08lx, ...) => %08lx\n", 
+  VERBOSE_TRACE ("mmap (%08lx, %08lx, ...) => %08lx\n",
                 (uintptr_t) start, (uintptr_t) length,
                 (uintptr_t) result);
   */
                 (uintptr_t) start, (uintptr_t) length,
                 (uintptr_t) result);
   */
@@ -353,11 +373,8 @@ WRAPPER(void *, mmap,
 
   return result;
 }
 
   return result;
 }
-#endif
 
 
 
 
-#ifdef WRAP_munmap
-
 #if PIC
 /* A special bootstrap variant. */
 int
 #if PIC
 /* A special bootstrap variant. */
 int
@@ -374,11 +391,11 @@ WRAPPER(int , munmap, void *start, size_t length)
   DECLARE(int, munmap, void *, size_t);
   int result;
   BEGIN_PROTECT (munmap, start, length);
   DECLARE(int, munmap, void *, size_t);
   int result;
   BEGIN_PROTECT (munmap, start, length);
-  
+
   result = CALL_REAL (munmap, start, length);
 
   /*
   result = CALL_REAL (munmap, start, length);
 
   /*
-  VERBOSE_TRACE ("munmap (%08lx, %08lx, ...) => %08lx\n", 
+  VERBOSE_TRACE ("munmap (%08lx, %08lx, ...) => %08lx\n",
                 (uintptr_t) start, (uintptr_t) length,
                 (uintptr_t) result);
   */
                 (uintptr_t) start, (uintptr_t) length,
                 (uintptr_t) result);
   */
@@ -391,17 +408,15 @@ WRAPPER(int , munmap, void *start, size_t length)
       uintptr_t offset;
 
       for (offset=0; offset<length; offset+=ps)
       uintptr_t offset;
 
       for (offset=0; offset<length; offset+=ps)
-       __mf_unregister ((void *) CLAMPADD (base, offset), ps);
+       __mf_unregister ((void *) CLAMPADD (base, offset), ps, __MF_TYPE_HEAP_I);
     }
   return result;
 }
     }
   return result;
 }
-#endif
+#endif /* HAVE_MMAP */
 
 
 
 
-#ifdef WRAP_alloca
-
 /* This wrapper is a little different, as it's called indirectly from
 /* This wrapper is a little different, as it's called indirectly from
-   __mf_fini also to clean up pending allocations.  */ 
+   __mf_fini also to clean up pending allocations.  */
 void *
 __mf_wrap_alloca_indirect (size_t c)
 {
 void *
 __mf_wrap_alloca_indirect (size_t c)
 {
@@ -428,14 +443,18 @@ __mf_wrap_alloca_indirect (size_t c)
 
   /* Free any previously alloca'd blocks that belong to deeper-nested functions,
      which must therefore have exited by now.  */
 
   /* Free any previously alloca'd blocks that belong to deeper-nested functions,
      which must therefore have exited by now.  */
-#define DEEPER_THAN < /* for x86 */
+
+#define DEEPER_THAN < /* XXX: for x86; steal find_stack_direction() from libiberty/alloca.c */
+
   while (alloca_history &&
         ((uintptr_t) alloca_history->stack DEEPER_THAN (uintptr_t) stack))
     {
       struct alloca_tracking *next = alloca_history->next;
   while (alloca_history &&
         ((uintptr_t) alloca_history->stack DEEPER_THAN (uintptr_t) stack))
     {
       struct alloca_tracking *next = alloca_history->next;
-      __mf_unregister (alloca_history->ptr, 0);
+      __mf_unregister (alloca_history->ptr, 0, __MF_TYPE_HEAP);
+      BEGIN_MALLOC_PROTECT ();
       CALL_REAL (free, alloca_history->ptr);
       CALL_REAL (free, alloca_history);
       CALL_REAL (free, alloca_history->ptr);
       CALL_REAL (free, alloca_history);
+      END_MALLOC_PROTECT ();
       alloca_history = next;
     }
 
       alloca_history = next;
     }
 
@@ -443,14 +462,20 @@ __mf_wrap_alloca_indirect (size_t c)
   result = NULL;
   if (LIKELY (c > 0)) /* alloca(0) causes no allocation.  */
     {
   result = NULL;
   if (LIKELY (c > 0)) /* alloca(0) causes no allocation.  */
     {
-      track = (struct alloca_tracking *) CALL_REAL (malloc, 
+      BEGIN_MALLOC_PROTECT ();
+      track = (struct alloca_tracking *) CALL_REAL (malloc,
                                                    sizeof (struct alloca_tracking));
                                                    sizeof (struct alloca_tracking));
+      END_MALLOC_PROTECT ();
       if (LIKELY (track != NULL))
        {
       if (LIKELY (track != NULL))
        {
+         BEGIN_MALLOC_PROTECT ();
          result = CALL_REAL (malloc, c);
          result = CALL_REAL (malloc, c);
+         END_MALLOC_PROTECT ();
          if (UNLIKELY (result == NULL))
            {
          if (UNLIKELY (result == NULL))
            {
+             BEGIN_MALLOC_PROTECT ();
              CALL_REAL (free, track);
              CALL_REAL (free, track);
+             END_MALLOC_PROTECT ();
              /* Too bad.  XXX: What about errno?  */
            }
          else
              /* Too bad.  XXX: What about errno?  */
            }
          else
@@ -463,7 +488,7 @@ __mf_wrap_alloca_indirect (size_t c)
            }
        }
     }
            }
        }
     }
-  
+
   return result;
 }
 
   return result;
 }
 
@@ -474,5 +499,3 @@ WRAPPER(void *, alloca, size_t c)
   return __mf_wrap_alloca_indirect (c);
 }
 
   return __mf_wrap_alloca_indirect (c);
 }
 
-#endif
-