X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=libmudflap%2Fmf-heuristics.c;fp=libmudflap%2Fmf-heuristics.c;h=020a7c29d527aae026147bda403bd0b675f54918;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=0000000000000000000000000000000000000000;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/libmudflap/mf-heuristics.c b/libmudflap/mf-heuristics.c new file mode 100644 index 00000000..020a7c29 --- /dev/null +++ b/libmudflap/mf-heuristics.c @@ -0,0 +1,169 @@ +/* Mudflap: narrow-pointer bounds-checking by tree rewriting. + Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. + Contributed by Frank Ch. Eigler + and Graydon Hoare + +This file is part of GCC. + +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 3, or (at your option) any later +version. + +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. + +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 +. */ + +#include "config.h" + +#include + +#include "mf-runtime.h" +#include "mf-impl.h" + +#ifdef _MUDFLAP +#error "Do not compile this file with -fmudflap!" +#endif + + +extern char _end[]; +extern char ENTRY_POINT[]; + + +/* Run some quick validation of the given region. + Return -1 / 0 / 1 if the access known-invalid, possibly-valid, or known-valid. +*/ +int +__mf_heuristic_check (uintptr_t ptr, uintptr_t ptr_high) +{ + VERBOSE_TRACE ("mf: heuristic check\n"); + + /* XXX: Disable the stack bounding check for libmudflapth. We do + actually have enough information to track stack bounds (see + __mf_pthread_info in mf-hooks.c), so with a bit of future work, + this heuristic can be turned on. */ +#ifndef LIBMUDFLAPTH + + /* The first heuristic is to check stack bounds. This is a + transient condition and quick to check. */ + if (__mf_opts.heur_stack_bound) + { + uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0); +#if defined(__i386__) && defined (__linux__) + uintptr_t stack_segment_base = 0xC0000000; /* XXX: Bad assumption. */ +#else + /* Cause tests to fail. */ + uintptr_t stack_segment_base = 0; +#endif + + VERBOSE_TRACE ("mf: stack estimated as %p-%p\n", + (void *) stack_top_guess, (void *) stack_segment_base); + + if (ptr_high <= stack_segment_base && + ptr >= stack_top_guess && + ptr_high >= ptr) + { + return 1; + } + } +#endif + + + /* 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) + { + /* Keep a record of seen records from /proc/self/map. */ + enum { max_entries = 500 }; + struct proc_self_map_entry + { + uintptr_t low; + uintptr_t high; + }; + static struct proc_self_map_entry entry [max_entries]; + static unsigned entry_used [max_entries]; + + /* Look for a known proc_self_map entry that may cover this + region. If one exists, then this heuristic has already run, + and should not be run again. The check should be allowed to + fail. */ + unsigned i; + unsigned deja_vu = 0; + for (i=0; i= ptr_high)) + deja_vu = 1; + } + + if (! deja_vu) + { + /* Time to run the heuristic. Rescan /proc/self/maps; update the + entry[] array; XXX: remove expired entries, add new ones. + XXX: Consider entries that have grown (e.g., stack). */ + 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 ((uintptr_t) low <= ptr && + (uintptr_t) high >= ptr_high) + { + for (i=0; i= (uintptr_t) & ENTRY_POINT && ptr_high <= (uintptr_t) & _end) + return 1; /* uncacheable */ + + return 0; /* unknown */ +}