/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008
+ Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
and Graydon Hoare <graydon@redhat.com>
Splay Tree code originally by Mark Mitchell <mark@markmitchell.com>,
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"
#ifdef LIBMUDFLAPTH
#ifdef HAVE_TLS
-__thread enum __mf_state_enum __mf_state_1 = active;
+__thread enum __mf_state_enum __mf_state_1 = reentrant;
#endif
#else
-enum __mf_state_enum __mf_state_1 = active;
+enum __mf_state_enum __mf_state_1 = reentrant;
#endif
#ifdef LIBMUDFLAPTH
__mf_opts.timestamps = 1;
__mf_opts.mudflap_mode = mode_check;
__mf_opts.violation_mode = viol_nop;
+#ifdef HAVE___LIBC_FREERES
+ __mf_opts.call_libc_freeres = 1;
+#endif
__mf_opts.heur_std_data = 1;
#ifdef LIBMUDFLAPTH
__mf_opts.thread_stack = 0;
#endif
}
-static struct option
+static struct mudoption
{
char *name;
char *description;
{"print-leaks",
"print any memory leaks at program shutdown",
set_option, 1, &__mf_opts.print_leaks},
+#ifdef HAVE___LIBC_FREERES
+ {"libc-freeres",
+ "call glibc __libc_freeres at shutdown for better leak data",
+ set_option, 1, &__mf_opts.call_libc_freeres},
+#endif
{"check-initialization",
"detect uninitialized object reads",
set_option, 1, &__mf_opts.check_initialization},
static void
__mf_usage ()
{
- struct option *opt;
+ struct mudoption *opt;
fprintf (stderr,
"This is a %s%sGCC \"mudflap\" memory-checked binary.\n"
- "Mudflap is Copyright (C) 2002-2004 Free Software Foundation, Inc.\n"
+ "Mudflap is Copyright (C) 2002-2008 Free Software Foundation, Inc.\n"
"\n"
"The mudflap code can be controlled by an environment variable:\n"
"\n"
int
__mfu_set_options (const char *optstr)
{
- struct option *opts = 0;
+ struct mudoption *opts = 0;
char *nxt = 0;
long tmp = 0;
int rc = 0;
#endif
__mf_starting_p = 0;
+ __mf_set_state (active);
+
__mf_set_default_options ();
ov = getenv ("MUDFLAP_OPTIONS");
/* Can it possibly exist in the cache? */
if (LIKELY (old_obj->read_count + old_obj->write_count))
{
- /* As reported by Herman ten Brugge, we need to scan the entire
- cache for entries that may hit this object. */
uintptr_t low = old_obj->low;
uintptr_t high = old_obj->high;
- struct __mf_cache *entry = & __mf_lookup_cache [0];
+ struct __mf_cache *entry;
unsigned i;
- for (i = 0; i <= __mf_lc_mask; i++, entry++)
- {
- /* NB: the "||" in the following test permits this code to
- tolerate the situation introduced by __mf_check over
- contiguous objects, where a cache entry spans several
- objects. */
- if (entry->low == low || entry->high == high)
+ if ((high - low) >= (__mf_lc_mask << __mf_lc_shift))
+ {
+ /* For large objects (>= cache size - 1) check the whole cache. */
+ entry = & __mf_lookup_cache [0];
+ for (i = 0; i <= __mf_lc_mask; i++, entry++)
{
- entry->low = MAXPTR;
- entry->high = MINPTR;
+ /* NB: the "||" in the following test permits this code to
+ tolerate the situation introduced by __mf_check over
+ contiguous objects, where a cache entry spans several
+ objects. */
+ if (entry->low == low || entry->high == high)
+ {
+ entry->low = MAXPTR;
+ entry->high = MINPTR;
+ }
}
}
+ else
+ {
+ /* Object is now smaller then cache size. */
+ unsigned entry_low_idx = __MF_CACHE_INDEX (low);
+ unsigned entry_high_idx = __MF_CACHE_INDEX (high);
+ if (entry_low_idx <= entry_high_idx)
+ {
+ entry = & __mf_lookup_cache [entry_low_idx];
+ for (i = entry_low_idx; i <= entry_high_idx; i++, entry++)
+ {
+ /* NB: the "||" in the following test permits this code to
+ tolerate the situation introduced by __mf_check over
+ contiguous objects, where a cache entry spans several
+ objects. */
+ if (entry->low == low || entry->high == high)
+ {
+ entry->low = MAXPTR;
+ entry->high = MINPTR;
+ }
+ }
+ }
+ else
+ {
+ /* Object wrapped around the end of the cache. First search
+ from low to end of cache and then from 0 to high. */
+ entry = & __mf_lookup_cache [entry_low_idx];
+ for (i = entry_low_idx; i <= __mf_lc_mask; i++, entry++)
+ {
+ /* NB: the "||" in the following test permits this code to
+ tolerate the situation introduced by __mf_check over
+ contiguous objects, where a cache entry spans several
+ objects. */
+ if (entry->low == low || entry->high == high)
+ {
+ entry->low = MAXPTR;
+ entry->high = MINPTR;
+ }
+ }
+ entry = & __mf_lookup_cache [0];
+ for (i = 0; i <= entry_high_idx; i++, entry++)
+ {
+ /* NB: the "||" in the following test permits this code to
+ tolerate the situation introduced by __mf_check over
+ contiguous objects, where a cache entry spans several
+ objects. */
+ if (entry->low == low || entry->high == high)
+ {
+ entry->low = MAXPTR;
+ entry->high = MINPTR;
+ }
+ }
+ }
+ }
}
}
(old_obj->type == __MF_TYPE_HEAP
|| old_obj->type == __MF_TYPE_HEAP_I))
{
+ /* The problem with a warning message here is that we may not
+ be privy to accesses to such objects that occur within
+ uninstrumented libraries. */
+#if 0
fprintf (stderr,
"*******\n"
"mudflap warning: unaccessed registered object:\n");
__mf_describe_object (old_obj);
+#endif
}
}
/* Free up any remaining alloca()'d blocks. */
__mf_wrap_alloca_indirect (0);
+#ifdef HAVE___LIBC_FREERES
+ if (__mf_opts.call_libc_freeres)
+ {
+ extern void __libc_freeres (void);
+ __libc_freeres ();
+ }
+#endif
+
__mf_describe_object (NULL); /* Reset description epoch. */
l = __mf_report_leaks ();
fprintf (stderr, "number of leaked objects: %u\n", l);