This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa mudflap] bug fixes and new stack heuristic
- From: graydon at redhat dot com
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 20 Aug 2002 17:09:17 -0400
- Subject: [tree-ssa mudflap] bug fixes and new stack heuristic
- Reply-to: graydon at redhat dot com
Just committed:
[ libmudflap/ChangeLog ]
2002-08-20 Graydon Hoare <graydon@redhat.com>
* mf-runtime.h: New option: stack_bound (heuristic).
Move some macros out of implementation files.
* mf-runtime.c: New option string: -stack-bound.
Unify recursion protection with hooks.
Add more logging.
(__mf_check): Call __mf_heuristic_check.
(__mf_process_opts): Fix "no-" processing.
* mf-heuristics.c (__mf_heuristic_check): New function.
* mf-hooks.c: Much off-by-one fixing, recursion protection.
Index: libmudflap/mf-heuristics.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-heuristics.c,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 mf-heuristics.c
--- libmudflap/mf-heuristics.c 20 Aug 2002 16:56:01 -0000 1.1.2.2
+++ libmudflap/mf-heuristics.c 20 Aug 2002 21:04:50 -0000
@@ -12,6 +12,10 @@
#include <stdio.h>
#include "mf-runtime.h"
+#ifdef _MUDFLAP
+#error "Do not compile this file with -fmudflap!"
+#endif
+
extern char _end;
static void
@@ -25,40 +29,43 @@
TRACE_IN;
- fp = fopen ("/proc/self/maps", "r");
- if (!fp)
+ if (LIKELY (__mf_opts.heur_proc_map == 1))
{
- if (__mf_opts.trace_mf_calls)
+ fp = fopen ("/proc/self/maps", "r");
+ if (!fp)
{
- fprintf (stderr, "mf: (heuristics) cannot open /proc/self/maps\n");
- fprintf (stderr, "mf: (heuristics) registering 00-%p\n", &_end);
+ if (__mf_opts.trace_mf_calls)
+ {
+ fprintf (stderr, "mf: (heuristics) cannot open /proc/self/maps\n");
+ fprintf (stderr, "mf: (heuristics) registering 00-%p\n", &_end);
+ }
+ __mf_register ((uintptr_t) 0, (uintptr_t) &_end,
+ __MF_TYPE_GUESS,
+ "(heuristic) static 0-__end region");
+ TRACE_OUT;
+ return;
}
- __mf_register ((uintptr_t) 0, (uintptr_t) &_end,
- __MF_TYPE_GUESS,
- "(heuristic) static 0-__end region");
- return;
- }
-
- while (fgets (buf, sizeof(buf), fp))
- {
- if (sscanf (buf, "%p-%p %4c", &low, &high, flags) == 3)
+
+ while (fgets (buf, sizeof(buf), fp))
{
- if (flags[0] == 'r' &&
- flags[1] == '-')
+ if (sscanf (buf, "%p-%p %4c", &low, &high, flags) == 3)
{
- if (__mf_opts.trace_mf_calls)
+ if (flags[0] == 'r' &&
+ flags[1] == '-')
{
- fprintf (stderr, "mf: (heuristics) registering static region %p-%p\n",
- low, high);
- }
- __mf_register ((uintptr_t) low, (uintptr_t) (high-low),
- __MF_TYPE_GUESS,
- "(heuristic) static read-only segment");
- }
-
- /* This clause will register the stack as a guess. Splitting regions in the
- stack is much more delicate than in the heap. We will not do it yet. */
- /*
+ if (__mf_opts.trace_mf_calls)
+ {
+ fprintf (stderr, "mf: (heuristics) registering static region %p-%p\n",
+ low, high);
+ }
+ __mf_register ((uintptr_t) low, (uintptr_t) (high-low),
+ __MF_TYPE_GUESS,
+ "(heuristic) static read-only segment");
+ }
+
+ /* This clause will register the stack as a guess. Splitting regions in the
+ stack is much more delicate than in the heap. We will not do it yet. */
+ /*
else if (flags[2] == 'x')
{
if (__mf_opts.trace_mf_calls)
@@ -70,19 +77,61 @@
"(heuristic) static executable segment");
}
*/
- else
- {
- if (__mf_opts.trace_mf_calls)
- {
- fprintf (stderr, "mf: (heuristics) skipping region %s",buf);
+ else
+ {
+ if (__mf_opts.trace_mf_calls)
+ {
+ fprintf (stderr, "mf: (heuristics) skipping region %s",buf);
+ }
}
}
}
+ fclose (fp);
}
- fclose (fp);
TRACE_OUT;
}
+
+int
+__mf_heuristic_check (uintptr_t ptr, uintptr_t ptr_high)
+{
+
+ /* First heuristic is to check stack bounds */
+
+ if (__mf_opts.stack_bound)
+ {
+ TRACE ("mf: stack bound check on %p - %p\n",
+ ptr, ptr_high);
+
+ uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0);
+ const uintptr_t stack_segment_base = 0xC0000000;
+ const uintptr_t stack_segment_top = 0xBFFFC000;
+
+ TRACE ("mf: stack estimated as %p - %p\n",
+ stack_top_guess, stack_segment_base);
+
+ if (LIKELY(ptr >= stack_segment_top &&
+ ptr <= stack_segment_base))
+ {
+ if (UNLIKELY(ptr_high > stack_segment_base))
+ {
+ TRACE ("mf: ptr_high %p off bottom of stack %p\n",
+ ptr_high, stack_segment_base);
+ return 0;
+ }
+ if (UNLIKELY(ptr < stack_top_guess))
+ {
+ TRACE ("mf: ptr %p off top of stack %p\n",
+ ptr_high, stack_top_guess);
+ return 0;
+ }
+ return (ptr_high >= ptr);
+ }
+ }
+ TRACE ("mf: no heuristics validate extent %p - %p\n",
+ ptr, ptr_high);
+ return 0;
+}
void
__mf_init_heuristics ()
Index: libmudflap/mf-hooks.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-hooks.c,v
retrieving revision 1.1.2.6
diff -u -r1.1.2.6 mf-hooks.c
--- libmudflap/mf-hooks.c 17 Aug 2002 00:52:35 -0000 1.1.2.6
+++ libmudflap/mf-hooks.c 20 Aug 2002 21:04:51 -0000
@@ -28,78 +28,130 @@
/* XXX: if -DPIC, use dlsym-style wrapping instead */
+
+#define UNLIKELY(e) (__builtin_expect (!!(e), 0))
+#define LIKELY(e) (__builtin_expect (!!(e), 1))
+
+#define MF_VALIDATE_EXTENT(value,size) \
+ { \
+ struct __mf_cache * elem = \
+ & __mf_lookup_cache [((unsigned)value >> __mf_lc_shift) & \
+ __mf_lc_mask]; \
+ if (UNLIKELY ((elem->low > (unsigned)value) || \
+ (elem->high < (unsigned)value+size))) \
+ { \
+ mf_state resume_state = old_state; \
+ __mf_state = old_state; \
+ __mf_check ((unsigned)value, size); \
+ old_state = resume_state; \
+ } \
+ }
+
+
+#define BEGIN_PROTECT(ty, fname, ...) \
+ ty result; \
+ mf_state old_state; \
+ if (UNLIKELY (__mf_state != active)) \
+ return __real_ ## fname (__VA_ARGS__); \
+ else \
+ { \
+ TRACE_IN; \
+ old_state = __mf_state; \
+ __mf_state = reentrant; \
+ }
+
+#define END_PROTECT(ty, fname, ...) \
+ result = (ty) __real_ ## fname (__VA_ARGS__); \
+ __mf_state = old_state; \
+ TRACE_OUT; \
+ return result;
+
+
+
/* {{{ malloc/free etc. */
void *
__wrap_malloc (size_t c)
{
- char *buf;
extern void * __real_malloc (size_t);
size_t size_with_crumple_zomes;
- if (UNLIKELY (!__mf_active_p))
- return __real_malloc (c);
+ BEGIN_PROTECT (void *, malloc, c);
size_with_crumple_zomes = c + (2 * __mf_opts.crumple_zone);
- buf = (char *) __real_malloc (size_with_crumple_zomes);
+ result = (char *) __real_malloc (size_with_crumple_zomes);
+
+ __mf_state = old_state;
- if (buf)
+ if (LIKELY(result))
{
- buf += __mf_opts.crumple_zone;
- __mf_register ((uintptr_t) buf, c,
+ result += __mf_opts.crumple_zone;
+ __mf_register ((uintptr_t) result, c,
__MF_TYPE_HEAP, "malloc region");
}
-
- return buf;
+
+ TRACE_OUT;
+ return result;
}
void *
__wrap_calloc (size_t c, size_t n)
{
- char *buf;
extern void * __real_calloc (size_t c, size_t);
extern void * __real_malloc (size_t c);
extern void *__real_memset (void *s, int c, size_t n);
size_t size_with_crumple_zones;
- if (UNLIKELY (!__mf_active_p))
- return __real_calloc (c,n);
+ BEGIN_PROTECT (char *, calloc, c, n);
size_with_crumple_zones = (c * n) + (2 * __mf_opts.crumple_zone);
- buf = (char *) __real_malloc (size_with_crumple_zones);
-
- if (buf)
+ result = (char *) __real_malloc (size_with_crumple_zones);
+
+ if (LIKELY(result))
+ __real_memset (result, 0, size_with_crumple_zones);
+
+ __mf_state = old_state;
+
+ if (LIKELY(result))
{
- __real_memset (buf, 0, size_with_crumple_zones);
- buf += __mf_opts.crumple_zone;
- __mf_register ((uintptr_t) buf, c*n,
+ result += __mf_opts.crumple_zone;
+ __mf_register ((uintptr_t) result, c*n,
__MF_TYPE_HEAP, "calloc region");
}
- return buf;
+
+ TRACE_OUT;
+ return result;
}
void *
__wrap_realloc (void *buf, size_t c)
{
- char *buf2;
extern void * __real_realloc (void *, size_t);
size_t size_with_crumple_zones;
+ char *base = buf;
+
+ BEGIN_PROTECT (char *, realloc, buf, c);
- if (UNLIKELY (!__mf_active_p))
- return __real_realloc (buf,c);
+ if (LIKELY(buf))
+ base -= __mf_opts.crumple_zone;
size_with_crumple_zones = c + (2 * __mf_opts.crumple_zone);
- buf2 = (void *) __real_realloc (buf, size_with_crumple_zones);
- if (buf)
+ result = (char *) __real_realloc (base, size_with_crumple_zones);
+
+ __mf_state = old_state;
+
+ if (LIKELY(buf))
__mf_unregister ((uintptr_t) buf, 0);
- if (buf2)
+
+ if (LIKELY(result))
{
- buf2 += __mf_opts.crumple_zone;
- __mf_register ((uintptr_t) buf2, c,
+ result += __mf_opts.crumple_zone;
+ __mf_register ((uintptr_t) result, c,
__MF_TYPE_HEAP, "realloc region");
}
- return buf2;
+ TRACE_OUT;
+ return result;
}
@@ -109,21 +161,26 @@
/* Use a circular queue to delay some number (__mf_opts.free_queue_length) of free()s. */
static void *free_queue [__MF_FREEQ_MAX];
static unsigned free_ptr;
-
+ mf_state old_state;
extern void * __real_free (void *);
- if (UNLIKELY (!__mf_active_p))
+ if (UNLIKELY (__mf_state != active))
{
__real_free (buf);
return;
}
- if (buf == NULL)
+ if (UNLIKELY(buf == NULL))
return;
+ TRACE_IN;
+
__mf_unregister ((uintptr_t) buf, 0);
+
+ old_state = __mf_state;
+ __mf_state = reentrant;
- if (__mf_opts.free_queue_length > 0)
+ if (UNLIKELY(__mf_opts.free_queue_length > 0))
{
if (free_queue [free_ptr] != NULL)
@@ -153,32 +210,23 @@
}
__real_free (base);
}
+
+ __mf_state = old_state;
+ TRACE_OUT;
}
/* }}} */
/* {{{ str*,mem*,b* */
-#define UNLIKELY(e) (__builtin_expect (!!(e), 0))
-#define LIKELY(e) (__builtin_expect (!!(e), 1))
-
-#define MF_VALIDATE_EXTENT(value,size) \
- { \
- struct __mf_cache * elem = \
- & __mf_lookup_cache [((unsigned)value >> __mf_lc_shift) & \
- __mf_lc_mask]; \
- if (UNLIKELY ((elem->low > (unsigned)value) || \
- (elem->high < (unsigned)value+size))) \
- __mf_check ((unsigned)value, size); \
- }
-
void *
__wrap_memcpy (void *dest, const void *src, size_t n)
{
extern void *__real_memcpy (void *dest, const void *src, size_t n);
+ BEGIN_PROTECT(void *, memcpy, dest, src, n);
MF_VALIDATE_EXTENT(src, n);
MF_VALIDATE_EXTENT(dest, n);
- return __real_memcpy (dest, src, n);
+ END_PROTECT (void *, memcpy, dest, src, n);
}
@@ -187,9 +235,10 @@
__wrap_memmove (void *dest, const void *src, size_t n)
{
extern void *__real_memmove (void *dest, const void *src, size_t n);
+ BEGIN_PROTECT(void *, memmove, dest, src, n);
MF_VALIDATE_EXTENT(src, n);
MF_VALIDATE_EXTENT(dest, n);
- return __real_memmove (dest, src, n);
+ END_PROTECT(void *, memmove, dest, src, n);
}
@@ -197,33 +246,37 @@
__wrap_memset (void *s, int c, size_t n)
{
extern void *__real_memset (void *s, int c, size_t n);
+ BEGIN_PROTECT(void *, memset, s, c, n);
MF_VALIDATE_EXTENT(s, n);
- return __real_memset (s, c, n);
+ END_PROTECT(void *, memset, s, c, n);
}
int
__wrap_memcmp (const void *s1, const void *s2, size_t n)
{
extern int __real_memcmp (const void *s1, const void *s2, size_t n);
+ BEGIN_PROTECT(int, memcmp, s1, s2, n);
MF_VALIDATE_EXTENT(s1, n);
MF_VALIDATE_EXTENT(s2, n);
- return __real_memcmp (s1, s2, n);
+ END_PROTECT(int, memcmp, s1, s2, n);
}
void *
__wrap_memchr (const void *s, int c, size_t n)
{
extern void *__real_memchr (const void *s, int c, size_t n);
+ BEGIN_PROTECT(void *, memchr, s, c, n);
MF_VALIDATE_EXTENT(s, n);
- return __real_memchr (s, c, n);
+ END_PROTECT(void *, memchr, s, c, n);
}
void *
__wrap_memrchr (const void *s, int c, size_t n)
{
extern void *__real_memrchr (const void *s, int c, size_t n);
+ BEGIN_PROTECT(void *, memrchr, s, c, n);
MF_VALIDATE_EXTENT(s, n);
- return __real_memrchr (s, c, n);
+ END_PROTECT(void *, memrchr, s, c, n);
}
@@ -231,42 +284,52 @@
__wrap_strcpy (char *dest, const char *src)
{
extern char *__real_strcpy (char *dest, const char *src);
- int n = __real_strlen (src);
+ int n;
/* nb: just because strlen(src) == n doesn't mean (src + n) or (src + n +
1) are valid pointers. the allocated object might have size < n.
check anyways. */
+ BEGIN_PROTECT(char *, strcpy, dest, src);
+ TRACE("mf: strcpy %p %s-> %p\n", src, dest);
+ n = __real_strlen (src);
MF_VALIDATE_EXTENT(src, (n + 1));
MF_VALIDATE_EXTENT(dest, (n + 1));
- return __real_strcpy (dest, src);
+ END_PROTECT(char *, strcpy, dest, src);
}
char *
__wrap_strncpy (char *dest, const char *src, size_t n)
{
extern char *__real_strncpy (char *dest, const char *src, size_t n);
- int len = __real_strnlen (src, n);
+ int len;
+
+ BEGIN_PROTECT(char *, strncpy, dest, src, n);
+ TRACE("mf: strncpy %d chars %p %s -> %p\n", n, src, dest);
+ len = __real_strnlen (src, n);
MF_VALIDATE_EXTENT(src, len);
- MF_VALIDATE_EXTENT(dest, (len + 1));
- return __real_strncpy (dest, src, n);
+ MF_VALIDATE_EXTENT(dest, len); /* nb: strNcpy */
+ END_PROTECT(char *, strncpy, dest, src, n);
}
char *
__wrap_strcat (char *dest, const char *src)
{
extern char *__real_strcat (char *dest, const char *src);
- int dest_sz = __real_strlen (dest);
- int src_sz = __real_strlen (src);
+ int dest_sz;
+ int src_sz;
+
+ BEGIN_PROTECT(char *, strcat, dest, src);
+ dest_sz = __real_strlen (dest);
+ src_sz = __real_strlen (src);
MF_VALIDATE_EXTENT(src, (src_sz + 1));
MF_VALIDATE_EXTENT(dest, (dest_sz + src_sz + 1));
- return __real_strcat (dest, src);
+ END_PROTECT(char *, strcat, dest, src);
}
char *
__wrap_strncat (char *dest, const char *src, size_t n)
{
- extern char *__real_strncat (char *dest, const char *src, size_t n);
/* nb: validating the extents (s,n) might be a mistake for two reasons.
@@ -288,66 +351,105 @@
this same logic applies to further uses of strnlen later down in this
file. */
- int src_sz = __real_strnlen (src, n);
- int dest_sz = __real_strnlen (dest, n);
+ extern char *__real_strncat (char *dest, const char *src, size_t n);
+ int src_sz;
+ int dest_sz;
+
+ BEGIN_PROTECT(char *, strncat, dest, src, n);
+ src_sz = __real_strnlen (src, n);
+ dest_sz = __real_strnlen (dest, n);
MF_VALIDATE_EXTENT(src, src_sz);
MF_VALIDATE_EXTENT(dest, (dest_sz + src_sz + 1));
- return __real_strncat (dest, src, n);
+ END_PROTECT(char *, strncat, dest, src, n);
}
int
__wrap_strcmp (const char *s1, const char *s2)
{
extern int __real_strcmp (const char *s1, const char *s2);
- int s1_sz = __real_strlen (s1);
- int s2_sz = __real_strlen (s2);
+ int s1_sz;
+ int s2_sz;
+
+ BEGIN_PROTECT(int, strcmp, s1, s2);
+ s1_sz = __real_strlen (s1);
+ s2_sz = __real_strlen (s2);
MF_VALIDATE_EXTENT(s1, s1_sz+1);
MF_VALIDATE_EXTENT(s2, s2_sz+1);
- return __real_strcmp (s1, s2);
+ END_PROTECT(int, strcmp, s1, s2);
}
int
__wrap_strcasecmp (const char *s1, const char *s2)
{
extern int __real_strcasecmp (const char *s1, const char *s2);
- int s1_sz = __real_strlen (s1);
- int s2_sz = __real_strlen (s2);
+ int s1_sz;
+ int s2_sz;
+
+ BEGIN_PROTECT(int, strcasecmp, s1, s2);
+ s1_sz = __real_strlen (s1);
+ s2_sz = __real_strlen (s2);
MF_VALIDATE_EXTENT(s1, s1_sz+1);
MF_VALIDATE_EXTENT(s2, s2_sz+1);
- return __real_strcasecmp (s1, s2);
+ END_PROTECT(int, strcasecmp, s1, s2);
}
int
__wrap_strncmp (const char *s1, const char *s2, size_t n)
{
extern int __real_strncmp (const char *s1, const char *s2, size_t n);
- int s1_sz = __real_strnlen (s1, n);
- int s2_sz = __real_strnlen (s2, n);
+ int s1_sz;
+ int s2_sz;
+
+ BEGIN_PROTECT(int, strncmp, s1, s2, n);
+ s1_sz = __real_strnlen (s1, n);
+ s2_sz = __real_strnlen (s2, n);
MF_VALIDATE_EXTENT(s1, s1_sz);
MF_VALIDATE_EXTENT(s2, s2_sz);
- return __real_strncmp (s1, s2, n);
+ END_PROTECT(int, strncmp, s1, s2, n);
}
int
__wrap_strncasecmp (const char *s1, const char *s2, size_t n)
{
extern int __real_strncasecmp (const char *s1, const char *s2, size_t n);
- int s1_sz = __real_strnlen (s1, n);
- int s2_sz = __real_strnlen (s2, n);
+ int s1_sz;
+ int s2_sz;
+
+ BEGIN_PROTECT(int, strncasecmp, s1, s2, n);
+ s1_sz = __real_strnlen (s1, n);
+ s2_sz = __real_strnlen (s2, n);
MF_VALIDATE_EXTENT(s1, s1_sz);
MF_VALIDATE_EXTENT(s2, s2_sz);
- return __real_strncasecmp (s1, s2, n);
+ END_PROTECT(int, strncasecmp, s1, s2, n);
}
char *
__wrap_strdup (const char *s)
{
extern char *__real_strdup (const char *s);
- int n = __real_strlen (s);
- char *result;
+ extern void *__real_malloc (size_t sz);
+ int n;
+
+ BEGIN_PROTECT(char *, strdup, s);
+ n = __real_strlen (s);
MF_VALIDATE_EXTENT(s, n+1);
- result = __real_strdup (s);
- __mf_register ((uintptr_t) result, n, __MF_TYPE_HEAP, "strdup region");
+
+ result = (char *)__real_malloc (n+1 + 2*(__mf_opts.crumple_zone));
+
+ if (UNLIKELY(!result))
+ {
+ __mf_state = old_state;
+ TRACE_OUT;
+ return result;
+ }
+
+ result += __mf_opts.crumple_zone;
+ __real_memcpy (result, s, n);
+ result[n] = '\0';
+
+ __mf_register ((uintptr_t) result, n+1, __MF_TYPE_HEAP, "strdup region");
+ __mf_state = old_state;
+ TRACE_OUT;
return result;
}
@@ -355,11 +457,30 @@
__wrap_strndup (const char *s, size_t n)
{
extern char *__real_strndup (const char *s, size_t n);
- char *result;
- int sz = __real_strnlen (s, n);
- MF_VALIDATE_EXTENT(s, sz);
- result = __real_strndup (s, n);
- __mf_register ((uintptr_t) result, sz, __MF_TYPE_HEAP, "strndup region");
+ extern void *__real_malloc (size_t sz);
+ int sz;
+
+ BEGIN_PROTECT(char *, strndup, s, n);
+ sz = __real_strnlen (s, n);
+ MF_VALIDATE_EXTENT(s, sz); /* nb: strNdup */
+
+ /* note: strndup still adds a \0, even with the N limit! */
+ result = (char *)__real_malloc (n+1 + 2*(__mf_opts.crumple_zone));
+
+ if (UNLIKELY(!result))
+ {
+ __mf_state = old_state;
+ TRACE_OUT;
+ return result;
+ }
+
+ result += __mf_opts.crumple_zone;
+ __real_memcpy (result, s, n);
+ result[n] = '\0';
+
+ __mf_register ((uintptr_t) result, n+1, __MF_TYPE_HEAP, "strndup region");
+ __mf_state = old_state;
+ TRACE_OUT;
return result;
}
@@ -368,18 +489,24 @@
__wrap_strchr (const char *s, int c)
{
extern char *__real_strchr (const char *s, int c);
- int n = __real_strlen (s);
+ int n;
+
+ BEGIN_PROTECT(char *, strchr, s, c);
+ n = __real_strlen (s);
MF_VALIDATE_EXTENT(s, n+1);
- return __real_strchr (s, c);
+ END_PROTECT(char *, strchr, s, c);
}
char *
__wrap_strrchr (const char *s, int c)
{
extern char *__real_strrchr (const char *s, int c);
- int n = __real_strlen (s);
+ int n;
+
+ BEGIN_PROTECT(char *, strrchr, s, c);
+ n = __real_strlen (s);
MF_VALIDATE_EXTENT(s, n+1);
- return __real_strrchr (s, c);
+ END_PROTECT(char *, strrchr, s, c);
}
@@ -387,11 +514,15 @@
__wrap_strstr (const char *haystack, const char *needle)
{
extern char *__real_strstr (const char *haystack, const char *needle);
- int haystack_sz = __real_strlen (haystack);
- int needle_sz = __real_strlen (needle);
+ int haystack_sz;
+ int needle_sz;
+
+ BEGIN_PROTECT(char *, strstr, haystack, needle);
+ haystack_sz = __real_strlen (haystack);
+ needle_sz = __real_strlen (needle);
MF_VALIDATE_EXTENT(haystack, haystack_sz+1);
MF_VALIDATE_EXTENT(needle, needle_sz+1);
- return __real_strstr (haystack, needle);
+ END_PROTECT(char *, strstr, haystack, needle);
}
@@ -401,71 +532,115 @@
{
extern void *__real_memmem (const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
+
+ BEGIN_PROTECT(void *, memmem, haystack, haystacklen, needle, needlelen);
MF_VALIDATE_EXTENT(haystack, haystacklen);
MF_VALIDATE_EXTENT(needle, needlelen);
- return __real_memmem (haystack, haystacklen, needle, needlelen);
+ END_PROTECT(char *, memmem, haystack, haystacklen, needle, needlelen);
}
int
__wrap_strlen (const char *s)
{
extern int __real_strlen (const char *s);
- int n = __real_strlen (s);
- MF_VALIDATE_EXTENT(s, n+1);
- return n;
+
+ BEGIN_PROTECT(int, strlen, s);
+ result = __real_strlen (s);
+ MF_VALIDATE_EXTENT(s, result+1);
+ __mf_state = old_state;
+ TRACE_OUT;
+ return result;
}
int
__wrap_strnlen (const char *s, size_t n)
{
extern int __real_strnlen (const char *s, size_t n);
- int m = __real_strnlen (s, n);
- MF_VALIDATE_EXTENT(s, m);
- return m;
+
+ BEGIN_PROTECT(int, strnlen, s, n);
+ result = __real_strnlen (s, n);
+ MF_VALIDATE_EXTENT(s, result);
+ __mf_state = old_state;
+ TRACE_OUT;
+ return result;
}
void
__wrap_bzero (void *s, size_t n)
{
extern void __real_bzero (void *s, size_t n);
+ mf_state old_state;
+
+ if (UNLIKELY (__mf_state != active))
+ {
+ __real_bzero (s, n);
+ return;
+ }
+ TRACE_IN;
+ old_state = __mf_state;
+ __mf_state = reentrant;
MF_VALIDATE_EXTENT(s, n);
- return __real_bzero (s, n);
+ __real_bzero (s, n);
+ __mf_state = old_state;
+ TRACE_OUT;
}
void
__wrap_bcopy (const void *src, void *dest, size_t n)
{
extern void __real_bcopy (const void *src, void *dest, size_t n);
+ mf_state old_state;
+
+ if (UNLIKELY (__mf_state != active))
+ {
+ __real_bcopy (src, dest, n);
+ return;
+ }
+ TRACE_IN;
+ old_state = __mf_state;
+ __mf_state = reentrant;
MF_VALIDATE_EXTENT(src, n);
MF_VALIDATE_EXTENT(dest, n);
- return __real_bcopy (src, dest, n);
+ __real_bcopy (src, dest, n);
+ __mf_state = old_state;
+ TRACE_OUT;
}
int
__wrap_bcmp (const void *s1, const void *s2, size_t n)
{
extern int __real_bcmp (const void *s1, const void *s2, size_t n);
+
+ BEGIN_PROTECT(int, bcmp, s1, s2, n);
MF_VALIDATE_EXTENT(s1, n);
MF_VALIDATE_EXTENT(s2, n);
- return __real_bcmp (s1, s2, n);
+ END_PROTECT(int, bcmp, s1, s2, n);
}
char *
__wrap_index (const char *s, int c)
{
extern char *__real_index (const char *s, int c);
- int n = __real_strlen (s);
+ int n;
+
+ BEGIN_PROTECT(char *, index, s, c);
+ n = __real_strlen (s);
MF_VALIDATE_EXTENT(s, n+1);
- return __real_index (s, c);
+ END_PROTECT(char *, index, s, c);
}
+
+
char *
__wrap_rindex (const char *s, int c)
{
extern char *__real_rindex (const char *s, int c);
- int n = __real_strlen (s);
+ int n;
+
+ BEGIN_PROTECT(char *, rindex, s, c);
+ n = __real_strlen (s);
MF_VALIDATE_EXTENT(s, n+1);
- return __real_rindex (s, c);
+ END_PROTECT(char *, rindex, s, c);
}
/*
@@ -477,7 +652,9 @@
{
extern void __real_ ();
MF_VALIDATE_EXTENT();
- return __real_ ();
+ result = __real_ ();
+ __mf_state = old_state;
+ return result;
}
*/
Index: libmudflap/mf-runtime.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-runtime.c,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 mf-runtime.c
--- libmudflap/mf-runtime.c 20 Aug 2002 16:56:01 -0000 1.1.2.5
+++ libmudflap/mf-runtime.c 20 Aug 2002 21:04:51 -0000
@@ -55,7 +55,19 @@
struct __mf_options __mf_opts;
-int __mf_active_p = 0;
+mf_state __mf_state = inactive;
+
+#define BEGIN_RECURSION_PROTECT \
+ mf_state old_state; \
+ if (UNLIKELY (__mf_state == reentrant)) \
+ return; \
+ old_state = __mf_state; \
+ __mf_state = reentrant;
+
+#define END_RECURSION_PROTECT \
+ __mf_state = old_state;
+
+
static void
__mf_set_default_options ()
@@ -67,6 +79,7 @@
__mf_opts.verbose_violations = 0;
__mf_opts.optimize_object_tree = 0;
__mf_opts.multi_threaded = 0;
+ __mf_opts.stack_bound = 0;
__mf_opts.free_queue_length = 0;
__mf_opts.persistent_count = 0;
__mf_opts.crumple_zone = 32;
@@ -142,6 +155,10 @@
"support /proc/self/map heuristics",
set_option, 1, &__mf_opts.heur_proc_map},
+ {"stack-bound",
+ "enable a simple upper stack bound heuristic",
+ set_option, 1, &__mf_opts.stack_bound},
+
{"free-queue-length",
"queue N deferred free() calls before performing them",
read_integer_option, 0, &__mf_opts.free_queue_length},
@@ -223,6 +240,7 @@
case '-':
if (*optstr+1)
{
+ int negate = 0;
optstr++;
if (*optstr == '?' || strcmp (optstr, "help") == 0)
@@ -230,19 +248,18 @@
__mf_usage ();
exit (0);
}
+
+
+ if (strncmp (optstr, "no-", 3) == 0)
+ {
+ negate = 1;
+ optstr = & optstr[3];
+ }
for (opts = options; opts->name; opts++)
{
- int negate = 0;
-
- if (strncmp (optstr, "no-", 3) == 0)
- {
- negate = 1;
- optstr = & optstr[3];
- }
-
if (strncmp (optstr, opts->name,
- strlen (opts->name)) == 0)
+ strlen (opts->name)) == 0)
{
optstr += strlen (opts->name);
assert (opts->target);
@@ -294,6 +311,8 @@
{
char *ov = 0;
+ __mf_state = starting;
+
__mf_set_default_options ();
ov = getenv ("MUDFLAP_OPTIONS");
@@ -309,10 +328,10 @@
}
}
- __mf_active_p = 1;
-
__mf_init_heuristics ();
+ __mf_state = active;
+
TRACE_OUT;
}
@@ -414,8 +433,6 @@
unsigned __mf_object_dead_head[__MF_TYPE_GUESS+1]; /* next empty spot */
__mf_object_tree_t *__mf_object_cemetary[__MF_TYPE_GUESS+1][__MF_PERSIST_MAX];
-unsigned __mf_recursion_protect;
-
static __mf_object_tree_t *__mf_find_object (uintptr_t low, uintptr_t high);
static unsigned __mf_find_objects (uintptr_t ptr_low, uintptr_t ptr_high,
__mf_object_tree_t **objs, unsigned max_objs);
@@ -435,14 +452,10 @@
struct __mf_cache *entry = & __mf_lookup_cache [entry_idx];
int violation_p = 0;
uintptr_t ptr_high = CLAMPSZ (ptr, sz);
- static unsigned recursion = 0;
struct __mf_cache old_entry = *entry;
- if (UNLIKELY (! __mf_active_p)) return;
-
- if (UNLIKELY (recursion)) return;
- recursion ++;
+ BEGIN_RECURSION_PROTECT;
switch (__mf_opts.mudflap_mode)
{
@@ -467,8 +480,11 @@
}
else
{
- /* XXX: */
- violation_p = 1;
+ if (! __mf_heuristic_check (ptr, ptr_high))
+ {
+ /* XXX: */
+ violation_p = 1;
+ }
}
}
break;
@@ -486,14 +502,13 @@
/* && (old_entry.low != 0) && (old_entry.high != 0)) */
__mf_lookup_cache_reusecount [entry_idx] ++;
}
-
- if (__mf_opts.trace_mf_calls)
- fprintf (stderr, "mf chk p=%08lx s=%lu\n", ptr, sz);
-
+
+ TRACE ("mf: check p=%p s=%lu viol=%d\n", (void *)ptr, sz, violation_p);
+ END_RECURSION_PROTECT;
+
if (UNLIKELY (violation_p))
- __mf_violation (ptr, sz, (uintptr_t) __builtin_return_address (0), __MF_VIOL_CHECK);
-
- recursion --;
+ __mf_violation (ptr, sz, (uintptr_t) __builtin_return_address (0),
+ __MF_VIOL_CHECK);
}
/* }}} */
@@ -556,11 +571,11 @@
void
__mf_register (uintptr_t ptr, uintptr_t sz, int type, const char *name)
{
- if (UNLIKELY (! __mf_active_p)) return;
- if (__mf_opts.trace_mf_calls)
- fprintf (stderr, "mf reg p=%08lx s=%lu t=%d n=`%s'\n",
- ptr, sz, type, name ? name : "");
+ if (UNLIKELY (!(__mf_state == active || __mf_state == starting))) return;
+
+ TRACE("mf: reg p=%p s=%lu t=%d n='%s'\n", (void *)ptr, sz,
+ type, name ? name : "");
switch (__mf_opts.mudflap_mode)
{
@@ -582,13 +597,11 @@
__mf_object_tree_t *ovr_obj[1];
__mf_object_tree_t *new_obj;
unsigned num_overlapping_objs;
- static unsigned recursion = 0;
uintptr_t low = ptr;
uintptr_t high = CLAMPSZ (ptr, sz);
uintptr_t pc = (uintptr_t) __builtin_return_address (0);
- if (UNLIKELY (recursion)) return;
- recursion ++;
+ BEGIN_RECURSION_PROTECT;
/* Treat unknown size indication as 1. */
if (UNLIKELY (sz == 0)) sz = 1;
@@ -606,13 +619,15 @@
ovr_obj[0]->data.high == high)
{
/* do nothing */
- recursion --;
+ TRACE ("mf: duplicate static reg %p\n", (void *)low);
+ END_RECURSION_PROTECT;
return;
}
else if (type == __MF_TYPE_GUESS)
{
/* do nothing, someone has beat us here. */
- recursion --;
+ TRACE ("mf: existing guessed reg %p\n", (void *)low);
+ END_RECURSION_PROTECT;
return;
}
else
@@ -641,18 +656,14 @@
guess2_low = CLAMPADD (high, (1 + __mf_opts.crumple_zone));
guess2_high = ovr_obj[i]->data.high;
+
+ TRACE("mf: splitting guess region %p-%p\n",
+ guess1_low, guess2_high);
+
/* NB: split regions may disappear if low > high. */
-
- if (__mf_opts.trace_mf_calls)
- {
- fprintf (stderr,
- "mf: splitting guess region %08lx-%08lx\n",
- guess1_low, guess2_high);
- }
- __mf_unlink_object (ovr_obj[i]);
+ __mf_remove_old_object (ovr_obj[i]);
__real_free (ovr_obj[i]->data.alloc_backtrace);
- /* __real_free (ovr_obj[i]->data.dealloc_backtrace); */
__real_free (ovr_obj[i]);
ovr_obj[i] = NULL;
@@ -675,6 +686,7 @@
else
{
/* Two or more *real* mappings here. */
+ TRACE("mf: reg violation %p\n", (void *)low);
__mf_violation
(ptr, sz, (uintptr_t) __builtin_return_address (0),
__MF_VIOL_REGISTER);
@@ -688,7 +700,7 @@
/* We could conceivably call __mf_check() here to prime the cache,
but then the check_count field is not reliable. */
- recursion --;
+ END_RECURSION_PROTECT;
break;
}
@@ -712,7 +724,7 @@
extern void __real_free (void *);
- if (UNLIKELY (! __mf_active_p)) return;
+ BEGIN_RECURSION_PROTECT;
switch (__mf_opts.mudflap_mode)
{
@@ -736,10 +748,7 @@
__mf_object_tree_t *del_obj = NULL; /* Object to actually delete. */
__mf_object_tree_t *objs[1] = {NULL};
unsigned num_overlapping_objs;
-
- if (UNLIKELY (recursion)) return;
- recursion ++;
-
+
/* Treat unknown size indication as 1. */
if (sz == 0) sz = 1;
@@ -752,29 +761,26 @@
{
if (objs[i]->data.type == __MF_TYPE_GUESS)
{
- recursion--;
+ TRACE("mf: ignored guess unreg %p\n", objs[i]->data.low);
+ END_RECURSION_PROTECT;
return;
}
- }
-
+ }
}
if (UNLIKELY (num_overlapping_objs != 1))
{
/* XXX: also: should match ptr == old_obj->low ? */
-
+ TRACE("mf: unreg viol %p\n", (void *)ptr);
+ END_RECURSION_PROTECT;
__mf_violation (ptr, sz, (uintptr_t) __builtin_return_address (0),
__MF_VIOL_UNREGISTER);
- recursion --;
return;
}
old_obj = objs[0];
- if (__mf_opts.trace_mf_calls)
- {
- fprintf (stderr, "mf: removing region %08lx-%08lx\n", old_obj->data.low, old_obj->data.high);
- }
+ TRACE("mf: removing %p-%p\n", old_obj->data.low, old_obj->data.high);
__mf_remove_old_object (old_obj);
@@ -839,7 +845,6 @@
__real_free (del_obj);
}
- recursion --;
break;
}
} /* end switch (__mf_opts.mudflap_mode) */
@@ -851,8 +856,8 @@
__mf_total_unregister_size += sz;
}
- if (__mf_opts.trace_mf_calls)
- fprintf (stderr, "mf unr p=%08lx s=%lu\n", ptr, sz);
+ TRACE("mf: unr p=%p s=%lu\n", (void *)ptr, sz);
+ END_RECURSION_PROTECT;
}
/* }}} */
@@ -1008,7 +1013,7 @@
__mf_object_tree_t* objects[1]; /* Find at most one. */
unsigned count;
- if (__mf_opts.internal_checking)
+ if (UNLIKELY(__mf_opts.internal_checking))
__mf_validate_objects ();
count = __mf_find_objects_rec (low, high, & __mf_object_root, objects, 1);
@@ -1023,7 +1028,7 @@
__mf_find_objects (uintptr_t ptr_low, uintptr_t ptr_high,
__mf_object_tree_t **objs, unsigned max_objs)
{
- if (__mf_opts.internal_checking)
+ if (UNLIKELY(__mf_opts.internal_checking))
__mf_validate_objects ();
return __mf_find_objects_rec (ptr_low, ptr_high, & __mf_object_root, objs, max_objs);
@@ -1038,7 +1043,7 @@
__mf_object_tree_t *node = *link;
assert (ptr != NULL);
- if (node == NULL)
+ if (UNLIKELY(node == NULL))
{
*link = ptr;
return;
@@ -1056,7 +1061,7 @@
void
__mf_link_object (__mf_object_tree_t *ptr)
{
- if (__mf_opts.internal_checking)
+ if (UNLIKELY(__mf_opts.internal_checking))
__mf_validate_objects ();
return __mf_link_object2 (ptr, & __mf_object_root);
@@ -1071,7 +1076,7 @@
__mf_object_tree_t *node = *link;
assert (ptr != NULL);
- if (node == ptr)
+ if (UNLIKELY(node == ptr))
{
static unsigned promote_left_p = 0;
promote_left_p = 1 - promote_left_p;
@@ -1178,7 +1183,8 @@
static void
__mf_describe_object (__mf_object_t *obj)
{
- if (UNLIKELY (! __mf_active_p)) return;
+
+ if (UNLIKELY (__mf_state != active)) return;
fprintf (stderr,
"mudflap object %08lx: name=`%s'\n"
@@ -1246,7 +1252,7 @@
__mf_report ()
{
- if (UNLIKELY (! __mf_active_p)) return;
+ if (UNLIKELY (__mf_state == active)) return;
if (__mf_opts.collect_stats)
{
@@ -1320,10 +1326,9 @@
static unsigned violation_number;
extern void __real_free (void *);
- if (UNLIKELY (! __mf_active_p)) return;
+ BEGIN_RECURSION_PROTECT;
- if (__mf_opts.trace_mf_calls)
- fprintf (stderr, "mf violation pc=%08lx type=%d\n", pc, type);
+ TRACE("mf: violation pc=%p type=%d ptr=%p sz=%d\n", pc, type, ptr, sz);
if (__mf_opts.collect_stats)
__mf_count_violation [(type < 0) ? 0 :
@@ -1432,7 +1437,6 @@
switch (__mf_opts.violation_mode)
{
case viol_nop:
- return;
break;
case viol_segv:
kill (getpid(), SIGSEGV);
@@ -1445,6 +1449,8 @@
system (buf);
break;
}
+
+ END_RECURSION_PROTECT;
}
/* }}} */
Index: libmudflap/mf-runtime.h
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-runtime.h,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 mf-runtime.h
--- libmudflap/mf-runtime.h 20 Aug 2002 16:56:01 -0000 1.1.2.4
+++ libmudflap/mf-runtime.h 20 Aug 2002 21:04:51 -0000
@@ -12,7 +12,9 @@
extern struct __mf_cache __mf_lookup_cache [];
extern uintptr_t __mf_lc_mask;
extern unsigned char __mf_lc_shift;
-extern int __mf_active_p;
+
+typedef enum {inactive, starting, active, reentrant} mf_state;
+extern mf_state __mf_state;
#define UNLIKELY(e) (__builtin_expect (!!(e), 0))
#define LIKELY(e) (__builtin_expect (!!(e), 1))
@@ -39,13 +41,12 @@
#define __MF_PERSIST_MAX 256
#define __MF_FREEQ_MAX 256
-#define TRACE_IN \
- if (__mf_opts.trace_mf_calls) \
- fprintf (stderr, "mf: enter %s\n", __FUNCTION__);
-
-#define TRACE_OUT \
- if (__mf_opts.trace_mf_calls) \
- fprintf (stderr, "mf: exit %s\n", __FUNCTION__);
+#define TRACE(...) \
+ if (UNLIKELY (__mf_opts.trace_mf_calls)) \
+ fprintf (stderr, __VA_ARGS__);
+
+#define TRACE_IN TRACE("mf: enter %s\n", __FUNCTION__)
+#define TRACE_OUT TRACE("mf: exit %s\n", __FUNCTION__)
struct __mf_options
{
@@ -69,6 +70,9 @@
/* Support multiple threads. */
int multi_threaded;
+
+ /* use __libc_stack_end heuristic */
+ int stack_bound;
/* Maintain a queue of this many deferred free()s,
to trap use of freed memory. */