diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libmudflap/mf-heuristics.c | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libmudflap/mf-heuristics.c')
-rw-r--r-- | libmudflap/mf-heuristics.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/libmudflap/mf-heuristics.c b/libmudflap/mf-heuristics.c new file mode 100644 index 000000000..020a7c29d --- /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 <fche@redhat.com> + and Graydon Hoare <graydon@redhat.com> + +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 +<http://www.gnu.org/licenses/>. */ + +#include "config.h" + +#include <stdio.h> + +#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<max_entries; i++) + { + if (entry_used[i] && + (entry[i].low <= ptr) && + (entry[i].high >= 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<max_entries; i++) + { + if (! entry_used[i]) + { + entry[i].low = (uintptr_t) low; + entry[i].high = (uintptr_t) high; + entry_used[i] = 1; + break; + } + } + + VERBOSE_TRACE ("mf: registering region #%d " + "%p-%p given %s", + i, (void *) low, (void *) high, buf); + + __mfu_register ((void *) low, (size_t) (high-low), + __MF_TYPE_GUESS, + "/proc/self/maps segment"); + + return 0; /* undecided (tending to cachable) */ + } + } + } + fclose (fp); + } + } + } + + + /* The third heuristic is to approve all accesses between _start (or its + equivalent for the given target) and _end, which should include all + text and initialized data. */ + if (__mf_opts.heur_start_end) + if (ptr >= (uintptr_t) & ENTRY_POINT && ptr_high <= (uintptr_t) & _end) + return 1; /* uncacheable */ + + return 0; /* unknown */ +} |