[tree-ssa libmudflap] heuristics, build tweaks
Frank Ch. Eigler
fche@redhat.com
Tue Aug 27 15:37:00 GMT 2002
Hi -
I'm about to commit the following patch to libmudflap.
It reorganizes slightly how heuristics are used from __mf_check,
and how the libmudflap.{a,so} is constructed. The wrapping/hook
functions (str*, malloc, etc.) are all broken into individual
object files, for more convenient static linkage. There is also
some other minor cleanup.
2002-08-27 Frank Ch. Eigler <fche@redhat.com>
libmudflap hook breakup:
* Makefile.am (TESTS_ENVIRONMENT): Add ../../gcc to LD_LIBRARY_PATH
for libgcc_s.
(TESTS): Make dependent on libmudflap.
(HOOKOBJS): Break up mf-hooks.o into many little hook objects,
compiled from segments of mf-hooks.c.
* mf-hooks.c: Corresponding changes: wrap each function in
#ifdef/#endif.
* Makefile.in: Regenerated.
Heuristics reorganization:
* mf-heuristics.c (__mf_register_ro_sections, __mf_init_heuristics):
Remove these functions. Update callers.
(__mf_heuristic_check): Incorporate all the various heuristics.
Encode cacheability/retry judgement into trinary return value.
Separate start-end logic into a separate fallback heuristic. Only
register relevant /proc/self/map segments.
* mf-impl.h: Corresponding changes.
* mf-runtime.c (__mf_check): Reorganize heuristics fallback logic.
(__mf_init): Don't call __mf_init_heuristics.
Tracing cleanup:
* mf-heuristics.c, mf-runtime.c: Use new MUDFLAP_OPTION
"-verbose-trace" to emit all tracing messages other than those of
basic public api. Eliminate some duplicate/excessive messages.
* mf-runtime.h: Corresponding changes.
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/Makefile.am,v
retrieving revision 1.1.2.6
diff -u -w -s -p -r1.1.2.6 Makefile.am
--- Makefile.am 27 Aug 2002 16:35:00 -0000 1.1.2.6
+++ Makefile.am 27 Aug 2002 22:29:33 -0000
@@ -7,7 +7,7 @@
AUTOMAKE_OPTIONS = 1.3 cygnus
MAINT_CHARSET = latin1
-TESTS_ENVIRONMENT = LD_LIBRARY_PATH='.libs' MUDFLAP_OPTIONS='-mode-check -viol-abort -no-heur-proc-map'
+TESTS_ENVIRONMENT = LD_LIBRARY_PATH='.libs:../../gcc' MUDFLAP_OPTIONS='-mode-check -viol-abort -no-heur-proc-map'
TESTS = test/fail1.x test/fail10.x test/fail11.x test/fail12.x \
test/fail13.x test/fail14.x test/fail15.x test/fail16.x test/fail17.x \
@@ -34,6 +34,7 @@ test/fail%.x: test/fail%.c
test/pass%.x: test/pass%.c
$(CC) -DSHOULD_PASS -rdynamic -fmudflap -g -o $@ $<
+$(TESTS): $(lib_LTLIBRARIES)
# SUBDIRS =
# PWD = $${PWDCMD-pwd}
@@ -56,11 +57,53 @@ mf-heuristics.o: mf-runtime.h mf-impl.h
libmudflap_la_SOURCES = \
mf-runtime.c \
- mf-hooks.c \
mf-heuristics.c
-# libmudflap_la_LIBADD =
-# libmudflap_la_LDFLAGS =
+HOOKOBJS = \
+ malloc-hook.lo \
+ free-hook.lo \
+ calloc-hook.lo \
+ realloc-hook.lo \
+ memcpy-hook.lo \
+ memmove-hook.lo \
+ memset-hook.lo \
+ memcmp-hook.lo \
+ memchr-hook.lo \
+ memrchr-hook.lo \
+ strcpy-hook.lo \
+ strncpy-hook.lo \
+ strcat-hook.lo \
+ strncat-hook.lo \
+ strcmp-hook.lo \
+ strcasecmp-hook.lo \
+ strncmp-hook.lo \
+ strncasecmp-hook.lo \
+ strdup-hook.lo \
+ strndup-hook.lo \
+ strchr-hook.lo \
+ strrchr-hook.lo \
+ strstr-hook.lo \
+ memmem-hook.lo \
+ strlen-hook.lo \
+ strnlen-hook.lo \
+ bzero-hook.lo \
+ bcopy-hook.lo \
+ bcmp-hook.lo \
+ index-hook.lo \
+ rindex-hook.lo \
+ dlopen-hook.lo \
+ mmap-hook.lo \
+ munmap-hook.lo
+
+
+$(HOOKOBJS): mf-hooks.c mf-runtime.h mf-impl.h
+ set -e; \
+ for i in $(HOOKOBJS); do \
+ hook=`basename $$i -hook.lo`; \
+ $(LTCOMPILE) -DWRAP_$$hook -c $(srcdir)/mf-hooks.c -o $$i; \
+ done
+libmudflap_la_LDFLAGS =
+libmudflap_la_LIBADD = $(HOOKOBJS)
libmudflap_la_DEPENDENCIES = $(libmudflap_la_LIBADD)
Index: mf-heuristics.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-heuristics.c,v
retrieving revision 1.1.2.5
diff -u -w -s -p -r1.1.2.5 mf-heuristics.c
--- mf-heuristics.c 26 Aug 2002 23:18:04 -0000 1.1.2.5
+++ mf-heuristics.c 27 Aug 2002 22:29:34 -0000
@@ -17,11 +17,13 @@
#error "Do not compile this file with -fmudflap!"
#endif
+/* XXX */
extern char _end;
-
+extern char _start;
static const uintptr_t stack_segment_base = 0xC0000000;
static const uintptr_t stack_segment_top = 0xBF800000;
+
static int
is_stack_address (uintptr_t addr)
{
@@ -31,112 +33,89 @@ is_stack_address (uintptr_t addr)
}
-static void
-__mf_register_ro_sections ()
-{
- char buf[512];
- char flags[4];
- void *low, *high;
- FILE *fp;
- TRACE_IN;
- if (LIKELY (__mf_opts.heur_proc_map == 1))
+/* Run some quick validation of the given region. If successful, return non-zero.
+ If the result is cacheworthy, return something positive. */
+int
+__mf_heuristic_check (uintptr_t ptr, uintptr_t ptr_high)
{
- fp = fopen ("/proc/self/maps", "r");
- if (!fp)
+ TRACE_IN;
+
+ /* The first heuristic is to check stack bounds. Since this is a
+ transient condition and quick to check, don't cache its
+ result. */
+ if (__mf_opts.heur_stack_bound)
{
- if (__mf_opts.trace_mf_calls)
+ uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0);
+
+ VERBOSE_TRACE ("mf: stack estimated as %p-%p\n",
+ stack_top_guess, stack_segment_base);
+
+ if (ptr_high <= stack_segment_base &&
+ ptr >= stack_top_guess &&
+ ptr_high >= ptr)
{
- 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;
+ return 1; /* uncacheable */
}
+ }
+
+ /* The second heuristic is to scan the range of memory regions
+ listed in /proc/self/maps, a special file provided by the Linux
+ kernel. Its results may be cached, and in fact, a GUESS object
+ may as well be recorded for interesting matching sections. */
+
+ if (__mf_opts.heur_proc_map)
+ {
+ char buf[512];
+ char flags[4];
+ void *low, *high;
+ FILE *fp;
+ fp = fopen ("/proc/self/maps", "r");
+ if (fp)
+ {
while (fgets (buf, sizeof(buf), fp))
{
if (sscanf (buf, "%p-%p %4c", &low, &high, flags) == 3)
{
- if (! (is_stack_address ((uintptr_t)low) ||
- is_stack_address ((uintptr_t)high)))
+ if ((uintptr_t) low <= ptr &&
+ (uintptr_t) high >= ptr_high)
{
- if (__mf_opts.trace_mf_calls)
- {
- fprintf (stderr, "mf: (heuristics) registering static region %p-%p\n",
- low, high);
- }
+ VERBOSE_TRACE ("mf: registering region %p-%p given %s\n",
+ low, high, buf);
+
+ /* XXX: bad hack; permit __mf_register to do its job. */
+ __mf_state = active;
__mf_register ((uintptr_t) low, (uintptr_t) (high-low),
__MF_TYPE_GUESS,
- "(heuristic) static segment");
- }
- else
- {
- if (__mf_opts.trace_mf_calls)
- {
- fprintf (stderr, "mf: (heuristics) skipping region %s",buf);
- }
+ "/proc/self/maps segment");
+ __mf_state = reentrant;
+
+ TRACE_OUT;
+ return 0; /* undecided tending to cachable yes */
}
}
}
fclose (fp);
}
- TRACE_OUT;
}
+ /* The third heuristic is to approve all accesses between _start and _end,
+ which should include all text and initialized data. */
-int
-__mf_heuristic_check (uintptr_t ptr, uintptr_t ptr_high)
-{
-
- /* First heuristic is to check stack bounds */
-
- if (__mf_opts.stack_bound)
- {
- uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0);
-
- TRACE ("mf: stack bound check on %p - %p\n",
- ptr, ptr_high);
-
- TRACE ("mf: stack estimated as %p - %p\n",
- stack_top_guess, stack_segment_base);
-
- if (LIKELY(is_stack_address (ptr)))
+ if (__mf_opts.heur_start_end)
{
- if (UNLIKELY(ptr_high > stack_segment_base))
+ if (ptr >= (uintptr_t) & _start && ptr_high <= (uintptr_t) & _end)
{
- 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_OUT;
+ return 1; /* uncacheable */
}
}
- TRACE ("mf: no heuristics validate extent %p - %p\n",
- ptr, ptr_high);
- return 0;
-}
-void
-__mf_init_heuristics ()
-{
- enum __mf_state old_state;
- old_state = __mf_state;
- __mf_state = starting;
- TRACE_IN;
- __mf_register_ro_sections ();
TRACE_OUT;
- __mf_state = old_state;
+ return -1; /* hard failure */
}
Index: mf-hooks.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-hooks.c,v
retrieving revision 1.1.2.11
diff -u -w -s -p -r1.1.2.11 mf-hooks.c
--- mf-hooks.c 27 Aug 2002 16:35:00 -0000 1.1.2.11
+++ mf-hooks.c 27 Aug 2002 22:29:34 -0000
@@ -62,6 +62,7 @@ XXX: libgcc license?
/* {{{ malloc/free etc. */
+#ifdef WRAP_malloc
WRAPPER(void *, malloc, size_t c)
{
size_t size_with_crumple_zones;
@@ -85,8 +86,10 @@ WRAPPER(void *, malloc, size_t c)
TRACE_OUT;
return result;
}
+#endif
+#ifdef WRAP_calloc
WRAPPER(void *, calloc, size_t c, size_t n)
{
size_t size_with_crumple_zones;
@@ -116,7 +119,9 @@ WRAPPER(void *, calloc, size_t c, size_t
TRACE_OUT;
return result;
}
+#endif
+#ifdef WRAP_realloc
WRAPPER(void *, realloc, void *buf, size_t c)
{
DECLARE(void * , realloc, void *, size_t);
@@ -148,8 +153,10 @@ WRAPPER(void *, realloc, void *buf, size
TRACE_OUT;
return result;
}
+#endif
+#ifdef WRAP_free
WRAPPER(void, free, void *buf)
{
/* Use a circular queue to delay some number (__mf_opts.free_queue_length) of free()s. */
@@ -217,18 +224,23 @@ WRAPPER(void, free, void *buf)
__mf_state = old_state;
TRACE_OUT;
}
+#endif
+
+#ifdef WRAP_dlopen
WRAPPER(void *, dlopen, const char *filename, int flag)
{
DECLARE(void * , dlopen, const char *filename, int flag);
BEGIN_PROTECT(void *, dlopen, filename, flag);
result = CALL_REAL(dlopen, filename, flag);
__mf_state = old_state;
- __mf_init_heuristics ();
TRACE_OUT;
return result;
}
+#endif
+
+#ifdef WRAP_mmap
WRAPPER(void *, mmap,
void *start, size_t length, int prot,
int flags, int fd, off_t offset)
@@ -258,7 +270,10 @@ WRAPPER(void *, mmap,
TRACE_OUT;
return result;
}
+#endif
+
+#ifdef WRAP_munmap
WRAPPER(int , munmap, void *start, size_t length)
{
DECLARE(int, munmap, void *, size_t);
@@ -269,10 +284,12 @@ WRAPPER(int , munmap, void *start, size_
__mf_state = old_state;
__mf_unregister ((uintptr_t)start, length);
}
+#endif
/* }}} */
/* {{{ str*,mem*,b* */
+#ifdef WRAP_memcpy
WRAPPER(void *, memcpy, void *dest, const void *src, size_t n)
{
DECLARE(void *, memcpy, void *dest, const void *src, size_t n);
@@ -281,9 +298,10 @@ WRAPPER(void *, memcpy, void *dest, cons
MF_VALIDATE_EXTENT(dest, n, "memcpy dest");
END_PROTECT (void *, memcpy, dest, src, n);
}
+#endif
-
+#ifdef WRAP_memmove
WRAPPER(void *, memmove, void *dest, const void *src, size_t n)
{
DECLARE(void *, memmove, void *dest, const void *src, size_t n);
@@ -292,7 +310,9 @@ WRAPPER(void *, memmove, void *dest, con
MF_VALIDATE_EXTENT(dest, n, "memmove dest");
END_PROTECT(void *, memmove, dest, src, n);
}
+#endif
+#ifdef WRAP_memset
WRAPPER(void *, memset, void *s, int c, size_t n)
{
DECLARE(void *, memset, void *s, int c, size_t n);
@@ -300,7 +320,9 @@ WRAPPER(void *, memset, void *s, int c,
MF_VALIDATE_EXTENT(s, n, "memset dest");
END_PROTECT(void *, memset, s, c, n);
}
+#endif
+#ifdef WRAP_memcmp
WRAPPER(int, memcmp, const void *s1, const void *s2, size_t n)
{
DECLARE(int , memcmp, const void *s1, const void *s2, size_t n);
@@ -309,7 +331,9 @@ WRAPPER(int, memcmp, const void *s1, con
MF_VALIDATE_EXTENT(s2, n, "memcmp 2nd arg");
END_PROTECT(int, memcmp, s1, s2, n);
}
+#endif
+#ifdef WRAP_memchr
WRAPPER(void *, memchr, const void *s, int c, size_t n)
{
DECLARE(void *, memchr, const void *s, int c, size_t n);
@@ -317,7 +341,9 @@ WRAPPER(void *, memchr, const void *s, i
MF_VALIDATE_EXTENT(s, n, "memchr region");
END_PROTECT(void *, memchr, s, c, n);
}
+#endif
+#ifdef WRAP_memrchr
WRAPPER(void *, memrchr, const void *s, int c, size_t n)
{
DECLARE(void *, memrchr, const void *s, int c, size_t n);
@@ -325,8 +351,9 @@ WRAPPER(void *, memrchr, const void *s,
MF_VALIDATE_EXTENT(s, n, "memrchr region");
END_PROTECT(void *, memrchr, s, c, n);
}
+#endif
-
+#ifdef WRAP_strcpy
WRAPPER(char *, strcpy, char *dest, const char *src)
{
DECLARE(int, strlen, const char *s);
@@ -344,7 +371,9 @@ WRAPPER(char *, strcpy, char *dest, cons
MF_VALIDATE_EXTENT(dest, CLAMPADD(n, 1), "strcpy dest");
END_PROTECT(char *, strcpy, dest, src);
}
+#endif
+#ifdef WRAP_strncpy
WRAPPER(char *, strncpy, char *dest, const char *src, size_t n)
{
DECLARE(int, strnlen, const char *s, size_t n);
@@ -358,7 +387,9 @@ WRAPPER(char *, strncpy, char *dest, con
MF_VALIDATE_EXTENT(dest, len, "strncpy dest"); /* nb: strNcpy */
END_PROTECT(char *, strncpy, dest, src, n);
}
+#endif
+#ifdef WRAP_strcat
WRAPPER(char *, strcat, char *dest, const char *src)
{
DECLARE(int, strlen, const char *s);
@@ -373,7 +404,9 @@ WRAPPER(char *, strcat, char *dest, cons
MF_VALIDATE_EXTENT(dest, CLAMPADD(dest_sz, CLAMPADD(src_sz, 1)), "strcat dest");
END_PROTECT(char *, strcat, dest, src);
}
+#endif
+#ifdef WRAP_strncat
WRAPPER(char *, strncat, char *dest, const char *src, size_t n)
{
@@ -410,7 +443,9 @@ WRAPPER(char *, strncat, char *dest, con
"strncat dest");
END_PROTECT(char *, strncat, dest, src, n);
}
+#endif
+#ifdef WRAP_strcmp
WRAPPER(int, strcmp, const char *s1, const char *s2)
{
DECLARE(int, strlen, const char *s);
@@ -425,7 +460,9 @@ WRAPPER(int, strcmp, const char *s1, con
MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), "strcmp 2nd arg");
END_PROTECT(int, strcmp, s1, s2);
}
+#endif
+#ifdef WRAP_strcasecmp
WRAPPER(int, strcasecmp, const char *s1, const char *s2)
{
DECLARE(int, strlen, const char *s);
@@ -440,7 +477,9 @@ WRAPPER(int, strcasecmp, const char *s1,
MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), "strcasecmp 2nd arg");
END_PROTECT(int, strcasecmp, s1, s2);
}
+#endif
+#ifdef WRAP_strncmp
WRAPPER(int, strncmp, const char *s1, const char *s2, size_t n)
{
DECLARE(int, strnlen, const char *s, size_t n);
@@ -455,7 +494,9 @@ WRAPPER(int, strncmp, const char *s1, co
MF_VALIDATE_EXTENT(s2, s2_sz, "strncmp 2nd arg");
END_PROTECT(int, strncmp, s1, s2, n);
}
+#endif
+#ifdef WRAP_strncasecmp
WRAPPER(int, strncasecmp, const char *s1, const char *s2, size_t n)
{
DECLARE(int, strnlen, const char *s, size_t n);
@@ -470,7 +511,9 @@ WRAPPER(int, strncasecmp, const char *s1
MF_VALIDATE_EXTENT(s2, s2_sz, "strncasecmp 2nd arg");
END_PROTECT(int, strncasecmp, s1, s2, n);
}
+#endif
+#ifdef WRAP_strdup
WRAPPER(char *, strdup, const char *s)
{
DECLARE(int, strlen, const char *s);
@@ -505,7 +548,9 @@ WRAPPER(char *, strdup, const char *s)
TRACE_OUT;
return result;
}
+#endif
+#ifdef WRAP_strndup
WRAPPER(char *, strndup, const char *s, size_t n)
{
DECLARE(int, strnlen, const char *s, size_t n);
@@ -541,8 +586,9 @@ WRAPPER(char *, strndup, const char *s,
TRACE_OUT;
return result;
}
+#endif
-
+#ifdef WRAP_strchr
WRAPPER(char *, strchr, const char *s, int c)
{
DECLARE(int, strlen, const char *s);
@@ -554,7 +600,9 @@ WRAPPER(char *, strchr, const char *s, i
MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), "strchr region");
END_PROTECT(char *, strchr, s, c);
}
+#endif
+#ifdef WRAP_strrchr
WRAPPER(char *, strrchr, const char *s, int c)
{
DECLARE(int, strlen, const char *s);
@@ -566,8 +614,9 @@ WRAPPER(char *, strrchr, const char *s,
MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), "strrchr region");
END_PROTECT(char *, strrchr, s, c);
}
+#endif
-
+#ifdef WRAP_strstr
WRAPPER(char *, strstr, const char *haystack, const char *needle)
{
DECLARE(int, strlen, const char *s);
@@ -582,7 +631,9 @@ WRAPPER(char *, strstr, const char *hays
MF_VALIDATE_EXTENT(needle, CLAMPADD(needle_sz, 1), "strstr needle");
END_PROTECT(char *, strstr, haystack, needle);
}
+#endif
+#ifdef WRAP_memmem
WRAPPER(void *, memmem,
const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen)
@@ -595,7 +646,9 @@ WRAPPER(void *, memmem,
MF_VALIDATE_EXTENT(needle, needlelen, "memmem needle");
END_PROTECT(char *, memmem, haystack, haystacklen, needle, needlelen);
}
+#endif
+#ifdef WRAP_strlen
WRAPPER(int, strlen, const char *s)
{
DECLARE(int, strlen, const char *s);
@@ -607,7 +660,9 @@ WRAPPER(int, strlen, const char *s)
TRACE_OUT;
return result;
}
+#endif
+#ifdef WRAP_strnlen
WRAPPER(int, strnlen, const char *s, size_t n)
{
DECLARE(int, strnlen, const char *s, size_t n);
@@ -619,7 +674,9 @@ WRAPPER(int, strnlen, const char *s, siz
TRACE_OUT;
return result;
}
+#endif
+#ifdef WRAP_bzero
WRAPPER(void, bzero, void *s, size_t n)
{
DECLARE(void , bzero, void *s, size_t n);
@@ -638,7 +695,9 @@ WRAPPER(void, bzero, void *s, size_t n)
__mf_state = old_state;
TRACE_OUT;
}
+#endif
+#ifdef WRAP_bcopy
WRAPPER(void, bcopy, const void *src, void *dest, size_t n)
{
DECLARE(void , bcopy, const void *src, void *dest, size_t n);
@@ -658,7 +717,9 @@ WRAPPER(void, bcopy, const void *src, vo
__mf_state = old_state;
TRACE_OUT;
}
+#endif
+#ifdef WRAP_bcmp
WRAPPER(int, bcmp, const void *s1, const void *s2, size_t n)
{
DECLARE(int , bcmp, const void *s1, const void *s2, size_t n);
@@ -668,7 +729,9 @@ WRAPPER(int, bcmp, const void *s1, const
MF_VALIDATE_EXTENT(s2, n, "bcmp 2nd arg");
END_PROTECT(int, bcmp, s1, s2, n);
}
+#endif
+#ifdef WRAP_index
WRAPPER(char *, index, const char *s, int c)
{
DECLARE(int, strlen, const char *s);
@@ -680,9 +743,9 @@ WRAPPER(char *, index, const char *s, in
MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), "index region");
END_PROTECT(char *, index, s, c);
}
+#endif
-
-
+#ifdef WRAP_rindex
WRAPPER(char *, rindex, const char *s, int c)
{
DECLARE(int, strlen, const char *s);
@@ -694,7 +757,7 @@ WRAPPER(char *, rindex, const char *s, i
MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), "rindex region");
END_PROTECT(char *, rindex, s, c);
}
-
+#endif
/* }}} */
/* {{{ *printf,*scanf */
Index: mf-impl.h
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-impl.h,v
retrieving revision 1.1.2.2
diff -u -w -s -p -r1.1.2.2 mf-impl.h
--- mf-impl.h 27 Aug 2002 16:35:00 -0000 1.1.2.2
+++ mf-impl.h 27 Aug 2002 22:29:34 -0000
@@ -19,13 +19,14 @@
/* Private functions. */
-extern void __mf_init_heuristics ();
extern void __mf_violation (uintptr_t ptr, uintptr_t sz,
uintptr_t pc, const char *location,
int type);
extern size_t __mf_backtrace (char ***, void *, unsigned);
extern void __mf_resolve_dynamics ();
+extern int __mf_heuristic_check (uintptr_t, uintptr_t);
+
/* ------------------------------------------------------------------------ */
/* Type definitions. */
@@ -63,15 +64,15 @@ struct __mf_options
/* Print verbose description of violations. */
int verbose_violations;
+ /* Emit internal tracing message. */
+ int verbose_trace;
+
/* Perform occasional tree-rotations to optimize lookups. */
int optimize_object_tree;
/* 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. */
int free_queue_length;
@@ -109,7 +110,9 @@ struct __mf_options
violation_mode;
/* Violation heuristics selection. */
- int heur_proc_map; /* Register /proc/self/map regions. */
+ int heur_stack_bound; /* allow current stack region */
+ int heur_proc_map; /* allow & cache /proc/self/map regions. */
+ int heur_start_end; /* allow & cache _start .. _end */
};
@@ -175,12 +178,15 @@ extern struct __mf_dynamic __mf_dynamic;
#define LIKELY(e) (__builtin_expect (!!(e), 1))
#define STRINGIFY2(e) #e
#define STRINGIFY(e) STRINGIFY2(e)
+#define VERBOSE_TRACE(...) \
+ if (UNLIKELY (__mf_opts.verbose_trace)) \
+ fprintf (stderr, __VA_ARGS__);
#define TRACE(...) \
if (UNLIKELY (__mf_opts.trace_mf_calls)) \
fprintf (stderr, __VA_ARGS__);
-#define TRACE_IN TRACE("mf: enter %s\n", __PRETTY_FUNCTION__)
-#define TRACE_OUT TRACE("mf: exit %s\n", __PRETTY_FUNCTION__)
+#define TRACE_IN VERBOSE_TRACE ("mf: enter %s\n", __PRETTY_FUNCTION__)
+#define TRACE_OUT VERBOSE_TRACE ("mf: exit %s\n", __PRETTY_FUNCTION__)
#define __MF_PERSIST_MAX 256
Index: mf-runtime.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-runtime.c,v
retrieving revision 1.1.2.9
diff -u -w -s -p -r1.1.2.9 mf-runtime.c
--- mf-runtime.c 26 Aug 2002 23:18:04 -0000 1.1.2.9
+++ mf-runtime.c 27 Aug 2002 22:29:34 -0000
@@ -87,13 +87,13 @@ static void
__mf_set_default_options ()
{
__mf_opts.trace_mf_calls = 0;
+ __mf_opts.verbose_trace = 0;
__mf_opts.collect_stats = 0;
__mf_opts.internal_checking = 0;
__mf_opts.print_leaks = 0;
__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;
@@ -101,6 +101,8 @@ __mf_set_default_options ()
__mf_opts.mudflap_mode = mode_check;
__mf_opts.violation_mode = viol_nop;
__mf_opts.heur_proc_map = 1;
+ __mf_opts.heur_stack_bound = 0;
+ __mf_opts.heur_start_end = 0;
}
static struct option
@@ -146,6 +148,10 @@ options [] =
{"trace-calls",
"trace calls to mudflap runtime library",
set_option, 1, &__mf_opts.trace_mf_calls},
+ {"verbose-trace",
+ "trace internal events within mudflap runtime library",
+ set_option, 1, &__mf_opts.verbose_trace},
+
{"collect-stats",
"collect statistics on mudflap's operation",
set_option, 1, &__mf_opts.collect_stats},
@@ -168,9 +174,12 @@ options [] =
{"heur-proc-map",
"support /proc/self/map heuristics",
set_option, 1, &__mf_opts.heur_proc_map},
- {"stack-bound",
+ {"heur-stack-bound",
"enable a simple upper stack bound heuristic",
- set_option, 1, &__mf_opts.stack_bound},
+ set_option, 1, &__mf_opts.heur_stack_bound},
+ {"heur-start-end",
+ "support _start.._end heuristics",
+ set_option, 1, &__mf_opts.heur_start_end},
{"free-queue-length",
"queue N deferred free() calls before performing them",
@@ -423,8 +432,6 @@ void __mf_init ()
}
}
- __mf_init_heuristics ();
-
__mf_state = active;
TRACE_OUT;
@@ -447,7 +454,7 @@ static unsigned long __mf_count_check;
static unsigned long __mf_lookup_cache_reusecount [LOOKUP_CACHE_SIZE_MAX];
static unsigned long __mf_treerot_left, __mf_treerot_right;
static unsigned long __mf_count_register;
-static unsigned long __mf_total_register_size [__MF_TYPE_GUESS+1];
+static unsigned long __mf_total_register_size [__MF_TYPE_MAX+1];
static unsigned long __mf_count_unregister;
static unsigned long __mf_total_unregister_size;
static unsigned long __mf_count_violation [__MF_VIOL_UNREGISTER+1];
@@ -508,10 +515,11 @@ void __mf_check (uintptr_t ptr, uintptr_
struct __mf_cache *entry = & __mf_lookup_cache [entry_idx];
int violation_p = 0;
uintptr_t ptr_high = CLAMPSZ (ptr, sz);
-
struct __mf_cache old_entry = *entry;
BEGIN_RECURSION_PROTECT;
+ TRACE ("mf: check p=%p s=%lu "
+ "location=`%s'\n", (void *)ptr, sz, location);
switch (__mf_opts.mudflap_mode)
{
@@ -525,10 +533,9 @@ void __mf_check (uintptr_t ptr, uintptr_
case mode_check:
{
-
- int attempts = 2;
-
- while (attempts--)
+ unsigned heuristics = 0;
+ /* Looping only occurs if heuristics were triggered. */
+ while (1)
{
__mf_object_tree_t *node = __mf_find_object (ptr, ptr_high);
__mf_object_t *obj = (node != NULL ? (& node->data) : NULL);
@@ -538,29 +545,33 @@ void __mf_check (uintptr_t ptr, uintptr_
entry->low = obj->low;
entry->high = obj->high;
obj->check_count ++; /* XXX: what about overflow? */
- attempts = 0;
+ break;
}
- else
+ else if (heuristics++ < 2) /* XXX parametrize this number? */
{
- if (__mf_heuristic_check (ptr, ptr_high))
+ int judgement = __mf_heuristic_check (ptr, ptr_high);
+ if (judgement < 0)
{
- attempts = 0;
+ violation_p = 1;
+ break;
}
- else
- {
- /* Possible violation. */
- if (attempts > 0)
+ else if (judgement > 0)
{
- /* Try re-initializing heuristics. */
- __mf_init_heuristics ();
+ violation_p = 0;
+ break;
}
- else
+ else if (judgement == 0)
{
- /* This is our second time around,
- therefore we are out of luck. */
- violation_p = 1;
+ /* Undecided: try again. Most likely, the heuristics function
+ has deposited an object in the database and is expecting us
+ to find it the next time around. */
+ continue;
}
}
+ else /* no more heuristics iterations allowed */
+ {
+ violation_p = 1;
+ break;
}
}
}
@@ -580,8 +591,6 @@ void __mf_check (uintptr_t ptr, uintptr_
__mf_lookup_cache_reusecount [entry_idx] ++;
}
- TRACE ("mf: check p=%p s=%lu viol=%d location=%s\n", (void *)ptr, sz,
- violation_p, location);
END_RECURSION_PROTECT;
if (UNLIKELY (violation_p))
@@ -646,10 +655,9 @@ __mf_remove_old_object (__mf_object_tree
void
__mf_register (uintptr_t ptr, uintptr_t sz, int type, const char *name)
{
+ /* if (UNLIKELY (!(__mf_state == active || __mf_state == starting))) return; */
- if (UNLIKELY (!(__mf_state == active || __mf_state == starting))) return;
-
- TRACE("mf: reg p=%p s=%lu t=%d n='%s'\n", (void *)ptr, sz,
+ TRACE ("mf: register p=%p s=%lu t=%d n='%s'\n", (void *)ptr, sz,
type, name ? name : "");
switch (__mf_opts.mudflap_mode)
@@ -665,6 +673,7 @@ __mf_register (uintptr_t ptr, uintptr_t
case mode_populate:
/* Clear the cache. */
+ /* XXX: why the entire cache? */
memset (__mf_lookup_cache, 0, sizeof(__mf_lookup_cache));
break;
@@ -695,7 +704,7 @@ __mf_register (uintptr_t ptr, uintptr_t
ovr_obj[0]->data.high == high)
{
/* do nothing */
- TRACE ("mf: duplicate static reg %p\n", (void *)low);
+ VERBOSE_TRACE ("mf: duplicate static reg %p\n", (void *)low);
END_RECURSION_PROTECT;
return;
}
@@ -713,9 +722,15 @@ __mf_register (uintptr_t ptr, uintptr_t
}
}
+ /* XXX: the following logic is too restrictive.
+ We should handle the case of inserting a big GUESS
+ on top of a little (say) HEAP area. The new GUESS
+ thingie should be split up the same way as if the
+ little HEAPie was added second. */
if (all_guesses)
{
- TRACE ("mf: replacing %d existing guess%s at %p with %p - %p\n",
+ VERBOSE_TRACE ("mf: replacing %d existing guess%s at %p "
+ "with %p - %p\n",
num_overlapping_objs,
(num_overlapping_objs > 1 ? "es" : ""),
(void *)low,
@@ -734,7 +749,7 @@ __mf_register (uintptr_t ptr, uintptr_t
}
else
{
- TRACE ("mf: preserving %d regions at %p\n",
+ VERBOSE_TRACE ("mf: preserving %d regions at %p\n",
num_overlapping_objs, (void *)low);
}
END_RECURSION_PROTECT;
@@ -766,7 +781,7 @@ __mf_register (uintptr_t ptr, uintptr_t
guess2_low = CLAMPADD (high, (1 + __mf_opts.crumple_zone));
guess2_high = ovr_obj[i]->data.high;
- TRACE("mf: splitting guess region %p-%p\n",
+ VERBOSE_TRACE ("mf: splitting guess region %p-%p\n",
guess1_low, guess2_high);
/* NB: split regions may disappear if low > high. */
@@ -795,7 +810,6 @@ __mf_register (uintptr_t ptr, uintptr_t
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), NULL,
@@ -820,7 +834,7 @@ __mf_register (uintptr_t ptr, uintptr_t
{
__mf_count_register ++;
__mf_total_register_size [(type < 0) ? 0 :
- (type > __MF_TYPE_GUESS) ? 0 :
+ (type > __MF_TYPE_MAX) ? 0 :
type] += sz;
}
}
@@ -834,6 +848,8 @@ __mf_unregister (uintptr_t ptr, uintptr_
DECLARE (void, free, void *ptr);
BEGIN_RECURSION_PROTECT;
+ TRACE ("mf: unregister p=%p s=%lu\n", (void *)ptr, sz);
+
switch (__mf_opts.mudflap_mode)
{
case mode_nop:
@@ -870,7 +886,7 @@ __mf_unregister (uintptr_t ptr, uintptr_
{
if (objs[i]->data.type == __MF_TYPE_GUESS)
{
- TRACE("mf: ignored guess unreg %p\n", objs[i]->data.low);
+ VERBOSE_TRACE ("mf: ignored guess unreg %p\n", objs[i]->data.low);
END_RECURSION_PROTECT;
return;
}
@@ -879,8 +895,7 @@ __mf_unregister (uintptr_t ptr, uintptr_
if (UNLIKELY (num_overlapping_objs != 1))
{
- /* XXX: also: should match ptr == old_obj->low ? */
- TRACE("mf: unreg viol %p\n", (void *)ptr);
+ /* XXX: also: should check/assert ptr == old_obj->low ? */
END_RECURSION_PROTECT;
__mf_violation (ptr, sz,
(uintptr_t) __builtin_return_address (0), NULL,
@@ -890,7 +905,7 @@ __mf_unregister (uintptr_t ptr, uintptr_
old_obj = objs[0];
- TRACE("mf: removing %p-%p\n", old_obj->data.low, old_obj->data.high);
+ VERBOSE_TRACE ("mf: removing %p-%p\n", old_obj->data.low, old_obj->data.high);
__mf_remove_old_object (old_obj);
@@ -964,7 +979,6 @@ __mf_unregister (uintptr_t ptr, uintptr_
__mf_total_unregister_size += sz;
}
- TRACE("mf: unr p=%p s=%lu\n", (void *)ptr, sz);
END_RECURSION_PROTECT;
}
@@ -1367,13 +1381,14 @@ __mf_report ()
"*******\n"
"mudflap stats:\n"
"calls to __mf_check: %lu rot: %lu/%lu\n"
- " __mf_register: %lu [%luB, %luB, %luB, %luB]\n"
+ " __mf_register: %lu [%luB, %luB, %luB, %luB, %luB]\n"
" __mf_unregister: %lu [%luB]\n"
" __mf_violation: [%lu, %lu, %lu, %lu]\n",
__mf_count_check, __mf_treerot_left, __mf_treerot_right,
__mf_count_register,
__mf_total_register_size[0], __mf_total_register_size[1],
__mf_total_register_size[2], __mf_total_register_size[3],
+ __mf_total_register_size[4], /* XXX */
__mf_count_unregister, __mf_total_unregister_size,
__mf_count_violation[0], __mf_count_violation[1],
__mf_count_violation[2], __mf_count_violation[3]);
@@ -1490,16 +1505,18 @@ __mf_violation (uintptr_t ptr, uintptr_t
violation_number ++;
fprintf (stderr,
"*******\n"
- "mudflap violation %u: time=%lu.%06lu ptr=%08lx size=%lu pc=%08lx%s%s%s type=%s\n",
+ "mudflap violation %u (%s): time=%lu.%06lu "
+ "ptr=%08lx size=%lu pc=%08lx%s%s%s\n",
violation_number,
- now.tv_sec, now.tv_usec, ptr, sz, pc,
- (location != NULL ? " location=`" : ""),
- (location != NULL ? location : ""),
- (location != NULL ? "'" : ""),
((type == __MF_VIOL_CHECK) ? "check" :
(type == __MF_VIOL_REGISTER) ? "register" :
(type == __MF_VIOL_UNREGISTER) ? "unregister" :
- "unknown"));
+ "unknown"),
+ now.tv_sec, now.tv_usec,
+ ptr, sz, pc,
+ (location != NULL ? " location=`" : ""),
+ (location != NULL ? location : ""),
+ (location != NULL ? "'" : ""));
if (__mf_opts.backtrace > 0)
{
@@ -1561,7 +1578,7 @@ __mf_violation (uintptr_t ptr, uintptr_t
unsigned after = (low > obj->high) ? low - obj->high : 0;
unsigned into = (high >= obj->low && low <= obj->high) ? low - obj->low : 0;
- fprintf (stderr, "Nearby object %u: ptr is %uB %s\n",
+ fprintf (stderr, "Nearby object %u: region is %uB %s\n",
i + 1,
(before ? before :
after ? after :
Index: mf-runtime.h
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-runtime.h,v
retrieving revision 1.1.2.7
diff -u -w -s -p -r1.1.2.7 mf-runtime.h
--- mf-runtime.h 26 Aug 2002 23:18:04 -0000 1.1.2.7
+++ mf-runtime.h 27 Aug 2002 22:29:34 -0000
@@ -44,6 +44,7 @@ extern void __mf_check (uintptr_t ptr, u
#define __MF_TYPE_STACK 2
#define __MF_TYPE_STATIC 3
#define __MF_TYPE_GUESS 4
+#define __MF_TYPE_MAX __MF_TYPE_GUESS
/* The "public" mudflap API */
extern void __mf_register (uintptr_t ptr, uintptr_t sz, int type, const char *name);
More information about the Gcc-patches
mailing list