/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2009 Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
and Graydon Hoare <graydon@redhat.com>
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file. (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
GCC 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 General Public License
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
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#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__
use plain macros in mf-runtime.h. */
-#ifdef WRAP_malloc
-
#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)
{
- /* 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
+
#undef malloc
WRAPPER(void *, malloc, size_t 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));
+ BEGIN_MALLOC_PROTECT ();
result = (char *) CALL_REAL (malloc, size_with_crumple_zones);
-
+ END_MALLOC_PROTECT ();
+
if (LIKELY(result))
{
result += __mf_opts.crumple_zone;
return result;
}
-#endif
-#ifdef WRAP_calloc
-
#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
+
#undef calloc
WRAPPER(void *, calloc, size_t c, size_t 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,
- __mf_opts.crumple_zone));
+ __mf_opts.crumple_zone));
+ BEGIN_MALLOC_PROTECT ();
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))
{
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;
}
-#endif
-#ifdef WRAP_realloc
#if PIC
/* A special bootstrap variant. */
}
#endif
+
#undef realloc
WRAPPER(void *, realloc, void *buf, size_t c)
{
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));
+ BEGIN_MALLOC_PROTECT ();
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 ();
- __mf_state = reentrant;
+ __mf_set_state (reentrant);
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;
/* Restore previous setting. */
__mf_opts.wipe_heap = saved_wipe_heap;
- __mf_state = active;
+ __mf_set_state (active);
UNLOCKTH ();
return result;
}
-#endif
-#ifdef WRAP_free
-
#if PIC
/* A special bootstrap variant. */
void
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;
+#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))
{
- memset (free_queue, 0,
+ memset (free_queue, 0,
__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 (__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);
}
+ BEGIN_MALLOC_PROTECT ();
CALL_REAL (free, freeme);
+ END_MALLOC_PROTECT ();
}
- }
- else
+ }
+ else
{
/* back pointer up a bit to the beginning of crumple zone */
char *base = (char *)buf;
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);
}
+ BEGIN_MALLOC_PROTECT ();
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. */
#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)
{
- 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);
- result = CALL_REAL (mmap, start, length, prot,
+ result = CALL_REAL (mmap, start, length, prot,
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);
*/
return result;
}
-#endif
-#ifdef WRAP_munmap
-
#if PIC
/* A special bootstrap variant. */
int
DECLARE(int, munmap, void *, size_t);
int result;
BEGIN_PROTECT (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 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;
}
-#endif
+#endif /* HAVE_MMAP */
-#ifdef WRAP_alloca
-
/* 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)
{
/* 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;
- __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);
+ END_MALLOC_PROTECT ();
alloca_history = next;
}
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));
+ END_MALLOC_PROTECT ();
if (LIKELY (track != NULL))
{
+ BEGIN_MALLOC_PROTECT ();
result = CALL_REAL (malloc, c);
+ END_MALLOC_PROTECT ();
if (UNLIKELY (result == NULL))
{
+ BEGIN_MALLOC_PROTECT ();
CALL_REAL (free, track);
+ END_MALLOC_PROTECT ();
/* Too bad. XXX: What about errno? */
}
else
}
}
}
-
+
return result;
}
return __mf_wrap_alloca_indirect (c);
}
-#endif
-