Mercurial > hg > CbC > CbC_gcc
comparison libmudflap/mf-heuristics.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Mudflap: narrow-pointer bounds-checking by tree rewriting. | |
2 Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. | |
3 Contributed by Frank Ch. Eigler <fche@redhat.com> | |
4 and Graydon Hoare <graydon@redhat.com> | |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 Under Section 7 of GPL version 3, you are granted additional | |
19 permissions described in the GCC Runtime Library Exception, version | |
20 3.1, as published by the Free Software Foundation. | |
21 | |
22 You should have received a copy of the GNU General Public License and | |
23 a copy of the GCC Runtime Library Exception along with this program; | |
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
25 <http://www.gnu.org/licenses/>. */ | |
26 | |
27 #include "config.h" | |
28 | |
29 #include <stdio.h> | |
30 | |
31 #include "mf-runtime.h" | |
32 #include "mf-impl.h" | |
33 | |
34 #ifdef _MUDFLAP | |
35 #error "Do not compile this file with -fmudflap!" | |
36 #endif | |
37 | |
38 | |
39 extern char _end[]; | |
40 extern char ENTRY_POINT[]; | |
41 | |
42 | |
43 /* Run some quick validation of the given region. | |
44 Return -1 / 0 / 1 if the access known-invalid, possibly-valid, or known-valid. | |
45 */ | |
46 int | |
47 __mf_heuristic_check (uintptr_t ptr, uintptr_t ptr_high) | |
48 { | |
49 VERBOSE_TRACE ("mf: heuristic check\n"); | |
50 | |
51 /* XXX: Disable the stack bounding check for libmudflapth. We do | |
52 actually have enough information to track stack bounds (see | |
53 __mf_pthread_info in mf-hooks.c), so with a bit of future work, | |
54 this heuristic can be turned on. */ | |
55 #ifndef LIBMUDFLAPTH | |
56 | |
57 /* The first heuristic is to check stack bounds. This is a | |
58 transient condition and quick to check. */ | |
59 if (__mf_opts.heur_stack_bound) | |
60 { | |
61 uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0); | |
62 #if defined(__i386__) && defined (__linux__) | |
63 uintptr_t stack_segment_base = 0xC0000000; /* XXX: Bad assumption. */ | |
64 #else | |
65 /* Cause tests to fail. */ | |
66 uintptr_t stack_segment_base = 0; | |
67 #endif | |
68 | |
69 VERBOSE_TRACE ("mf: stack estimated as %p-%p\n", | |
70 (void *) stack_top_guess, (void *) stack_segment_base); | |
71 | |
72 if (ptr_high <= stack_segment_base && | |
73 ptr >= stack_top_guess && | |
74 ptr_high >= ptr) | |
75 { | |
76 return 1; | |
77 } | |
78 } | |
79 #endif | |
80 | |
81 | |
82 /* The second heuristic is to scan the range of memory regions | |
83 listed in /proc/self/maps, a special file provided by the Linux | |
84 kernel. Its results may be cached, and in fact, a GUESS object | |
85 may as well be recorded for interesting matching sections. */ | |
86 if (__mf_opts.heur_proc_map) | |
87 { | |
88 /* Keep a record of seen records from /proc/self/map. */ | |
89 enum { max_entries = 500 }; | |
90 struct proc_self_map_entry | |
91 { | |
92 uintptr_t low; | |
93 uintptr_t high; | |
94 }; | |
95 static struct proc_self_map_entry entry [max_entries]; | |
96 static unsigned entry_used [max_entries]; | |
97 | |
98 /* Look for a known proc_self_map entry that may cover this | |
99 region. If one exists, then this heuristic has already run, | |
100 and should not be run again. The check should be allowed to | |
101 fail. */ | |
102 unsigned i; | |
103 unsigned deja_vu = 0; | |
104 for (i=0; i<max_entries; i++) | |
105 { | |
106 if (entry_used[i] && | |
107 (entry[i].low <= ptr) && | |
108 (entry[i].high >= ptr_high)) | |
109 deja_vu = 1; | |
110 } | |
111 | |
112 if (! deja_vu) | |
113 { | |
114 /* Time to run the heuristic. Rescan /proc/self/maps; update the | |
115 entry[] array; XXX: remove expired entries, add new ones. | |
116 XXX: Consider entries that have grown (e.g., stack). */ | |
117 char buf[512]; | |
118 char flags[4]; | |
119 void *low, *high; | |
120 FILE *fp; | |
121 | |
122 fp = fopen ("/proc/self/maps", "r"); | |
123 if (fp) | |
124 { | |
125 while (fgets (buf, sizeof(buf), fp)) | |
126 { | |
127 if (sscanf (buf, "%p-%p %4c", &low, &high, flags) == 3) | |
128 { | |
129 if ((uintptr_t) low <= ptr && | |
130 (uintptr_t) high >= ptr_high) | |
131 { | |
132 for (i=0; i<max_entries; i++) | |
133 { | |
134 if (! entry_used[i]) | |
135 { | |
136 entry[i].low = (uintptr_t) low; | |
137 entry[i].high = (uintptr_t) high; | |
138 entry_used[i] = 1; | |
139 break; | |
140 } | |
141 } | |
142 | |
143 VERBOSE_TRACE ("mf: registering region #%d " | |
144 "%p-%p given %s", | |
145 i, (void *) low, (void *) high, buf); | |
146 | |
147 __mfu_register ((void *) low, (size_t) (high-low), | |
148 __MF_TYPE_GUESS, | |
149 "/proc/self/maps segment"); | |
150 | |
151 return 0; /* undecided (tending to cachable) */ | |
152 } | |
153 } | |
154 } | |
155 fclose (fp); | |
156 } | |
157 } | |
158 } | |
159 | |
160 | |
161 /* The third heuristic is to approve all accesses between _start (or its | |
162 equivalent for the given target) and _end, which should include all | |
163 text and initialized data. */ | |
164 if (__mf_opts.heur_start_end) | |
165 if (ptr >= (uintptr_t) & ENTRY_POINT && ptr_high <= (uintptr_t) & _end) | |
166 return 1; /* uncacheable */ | |
167 | |
168 return 0; /* unknown */ | |
169 } |