Mercurial > hg > CbC > CbC_gcc
comparison libmudflap/mf-impl.h @ 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 /* Implementation header for mudflap runtime library. | |
2 Mudflap: narrow-pointer bounds-checking by tree rewriting. | |
3 Copyright (C) 2002, 2003, 2004, 2009 Free Software Foundation, Inc. | |
4 Contributed by Frank Ch. Eigler <fche@redhat.com> | |
5 and Graydon Hoare <graydon@redhat.com> | |
6 | |
7 This file is part of GCC. | |
8 | |
9 GCC is free software; you can redistribute it and/or modify it under | |
10 the terms of the GNU General Public License as published by the Free | |
11 Software Foundation; either version 3, or (at your option) any later | |
12 version. | |
13 | |
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 Under Section 7 of GPL version 3, you are granted additional | |
20 permissions described in the GCC Runtime Library Exception, version | |
21 3.1, as published by the Free Software Foundation. | |
22 | |
23 You should have received a copy of the GNU General Public License and | |
24 a copy of the GCC Runtime Library Exception along with this program; | |
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
26 <http://www.gnu.org/licenses/>. */ | |
27 | |
28 #ifndef __MF_IMPL_H | |
29 #define __MF_IMPL_H | |
30 | |
31 #ifdef _MUDFLAP | |
32 #error "Do not compile this file with -fmudflap!" | |
33 #endif | |
34 | |
35 #if HAVE_PTHREAD_H | |
36 #include <pthread.h> | |
37 #elif LIBMUDFLAPTH | |
38 #error "Cannot build libmudflapth without pthread.h." | |
39 #endif | |
40 | |
41 #if HAVE_STDINT_H | |
42 #include <stdint.h> | |
43 #else | |
44 typedef __mf_uintptr_t uintptr_t; | |
45 #endif | |
46 | |
47 /* Private definitions related to mf-runtime.h */ | |
48 | |
49 #define __MF_TYPE_MAX_CEM __MF_TYPE_STACK /* largest type# for the cemetary */ | |
50 #define __MF_TYPE_MAX __MF_TYPE_GUESS | |
51 | |
52 | |
53 #ifndef max | |
54 #define max(a,b) ((a) > (b) ? (a) : (b)) | |
55 #endif | |
56 | |
57 #ifndef min | |
58 #define min(a,b) ((a) < (b) ? (a) : (b)) | |
59 #endif | |
60 | |
61 /* Address calculation macros. */ | |
62 | |
63 #define MINPTR ((uintptr_t) 0) | |
64 #define MAXPTR (~ (uintptr_t) 0) | |
65 | |
66 /* Clamp the addition/subtraction of uintptr_t's to [MINPTR,MAXPTR] */ | |
67 #define CLAMPSUB(ptr,offset) (((uintptr_t) ptr) >= (offset) ? ((uintptr_t) ptr)-((uintptr_t) offset) : MINPTR) | |
68 #define CLAMPADD(ptr,offset) (((uintptr_t) ptr) <= MAXPTR-(offset) ? ((uintptr_t) ptr)+((uintptr_t) offset) : MAXPTR) | |
69 #define CLAMPSZ(ptr,size) ((size) ? (((uintptr_t) ptr) <= MAXPTR-(size)+1 ? ((uintptr_t) ptr)+((uintptr_t) size) - 1 : MAXPTR) : ((uintptr_t) ptr)) | |
70 | |
71 #define __MF_CACHE_INDEX(ptr) ((((uintptr_t) (ptr)) >> __mf_lc_shift) & __mf_lc_mask) | |
72 #define __MF_CACHE_MISS_P(ptr,sz) ({ \ | |
73 struct __mf_cache *elem = & __mf_lookup_cache[__MF_CACHE_INDEX((ptr))]; \ | |
74 ((elem->low > (uintptr_t) (ptr)) || \ | |
75 (elem->high < (CLAMPADD((uintptr_t) (ptr), (uintptr_t) CLAMPSUB(sz,1) )))); }) | |
76 /* XXX: the above should use CLAMPSZ () */ | |
77 | |
78 | |
79 | |
80 /* Private functions. */ | |
81 | |
82 extern void __mf_violation (void *ptr, size_t sz, | |
83 uintptr_t pc, const char *location, | |
84 int type); | |
85 extern size_t __mf_backtrace (char ***, void *, unsigned); | |
86 extern int __mf_heuristic_check (uintptr_t, uintptr_t); | |
87 | |
88 /* ------------------------------------------------------------------------ */ | |
89 /* Type definitions. */ | |
90 /* ------------------------------------------------------------------------ */ | |
91 | |
92 /* The mf_state type codes describe recursion and initialization order. | |
93 | |
94 reentrant means we are inside a mf-runtime support routine, such as | |
95 __mf_register, and thus there should be no calls to any wrapped functions, | |
96 such as the wrapped malloc. This indicates a bug if it occurs. | |
97 in_malloc means we are inside a real malloc call inside a wrapped malloc | |
98 call, and thus there should be no calls to any wrapped functions like the | |
99 wrapped mmap. This happens on some systems due to how the system libraries | |
100 are constructed. */ | |
101 | |
102 enum __mf_state_enum { active, reentrant, in_malloc }; | |
103 | |
104 /* The __mf_options structure records optional or tunable aspects of the | |
105 mudflap library's behavior. There is a single global instance of this | |
106 structure which is populated from user input (in an environment variable) | |
107 when the library initializes. */ | |
108 | |
109 struct __mf_options | |
110 { | |
111 /* Emit a trace message for each call. */ | |
112 unsigned trace_mf_calls; | |
113 | |
114 /* Collect and emit statistics. */ | |
115 unsigned collect_stats; | |
116 | |
117 /* Set up a SIGUSR1 -> __mf_report handler. */ | |
118 unsigned sigusr1_report; | |
119 | |
120 /* Execute internal checking code. */ | |
121 unsigned internal_checking; | |
122 | |
123 /* Age object liveness periodically. */ | |
124 unsigned tree_aging; | |
125 | |
126 /* Adapt the lookup cache to working set. */ | |
127 unsigned adapt_cache; | |
128 | |
129 /* Print list of leaked heap objects on shutdown. */ | |
130 unsigned print_leaks; | |
131 | |
132 #ifdef HAVE___LIBC_FREERES | |
133 /* Call __libc_freeres before leak analysis. */ | |
134 unsigned call_libc_freeres; | |
135 #endif | |
136 | |
137 /* Detect reads of uninitialized objects. */ | |
138 unsigned check_initialization; | |
139 | |
140 /* Print verbose description of violations. */ | |
141 unsigned verbose_violations; | |
142 | |
143 /* Abbreviate duplicate object descriptions. */ | |
144 unsigned abbreviate; | |
145 | |
146 /* Emit internal tracing message. */ | |
147 unsigned verbose_trace; | |
148 | |
149 /* Wipe stack/heap objects upon unwind. */ | |
150 unsigned wipe_stack; | |
151 unsigned wipe_heap; | |
152 | |
153 /* Maintain a queue of this many deferred free()s, | |
154 to trap use of freed memory. */ | |
155 unsigned free_queue_length; | |
156 | |
157 /* Maintain a history of this many past unregistered objects. */ | |
158 unsigned persistent_count; | |
159 | |
160 /* Pad allocated extents by this many bytes on either side. */ | |
161 unsigned crumple_zone; | |
162 | |
163 /* Maintain this many stack frames for contexts. */ | |
164 unsigned backtrace; | |
165 | |
166 /* Ignore read operations even if mode_check is in effect. */ | |
167 unsigned ignore_reads; | |
168 | |
169 /* Collect register/unregister timestamps. */ | |
170 unsigned timestamps; | |
171 | |
172 #ifdef LIBMUDFLAPTH | |
173 /* Thread stack size. */ | |
174 unsigned thread_stack; | |
175 #endif | |
176 | |
177 /* Major operation mode */ | |
178 #define mode_nop 0 /* Do nothing. */ | |
179 #define mode_populate 1 /* Populate tree but do not check for violations. */ | |
180 #define mode_check 2 /* Populate and check for violations (normal). */ | |
181 #define mode_violate 3 /* Trigger a violation on every call (diagnostic). */ | |
182 unsigned mudflap_mode; | |
183 | |
184 /* How to handle a violation. */ | |
185 #define viol_nop 0 /* Return control to application. */ | |
186 #define viol_segv 1 /* Signal self with segv. */ | |
187 #define viol_abort 2 /* Call abort (). */ | |
188 #define viol_gdb 3 /* Fork a debugger on self */ | |
189 unsigned violation_mode; | |
190 | |
191 /* Violation heuristics selection. */ | |
192 unsigned heur_stack_bound; /* allow current stack region */ | |
193 unsigned heur_proc_map; /* allow & cache /proc/self/map regions. */ | |
194 unsigned heur_start_end; /* allow _start .. _end */ | |
195 unsigned heur_std_data; /* allow & cache stdlib data */ | |
196 }; | |
197 | |
198 | |
199 #ifdef PIC | |
200 | |
201 /* This is a table of dynamically resolved function pointers. */ | |
202 | |
203 struct __mf_dynamic_entry | |
204 { | |
205 void *pointer; | |
206 char *name; | |
207 char *version; | |
208 }; | |
209 | |
210 /* The definition of the array (mf-runtime.c) must match the enums! */ | |
211 extern struct __mf_dynamic_entry __mf_dynamic[]; | |
212 enum __mf_dynamic_index | |
213 { | |
214 dyn_calloc, dyn_free, dyn_malloc, dyn_mmap, | |
215 dyn_munmap, dyn_realloc, | |
216 dyn_INITRESOLVE, /* Marker for last init-time resolution. */ | |
217 #ifdef LIBMUDFLAPTH | |
218 dyn_pthread_create | |
219 #endif | |
220 }; | |
221 | |
222 #endif /* PIC */ | |
223 | |
224 /* ------------------------------------------------------------------------ */ | |
225 /* Private global variables. */ | |
226 /* ------------------------------------------------------------------------ */ | |
227 | |
228 #ifdef LIBMUDFLAPTH | |
229 extern pthread_mutex_t __mf_biglock; | |
230 #define LOCKTH() do { extern unsigned long __mf_lock_contention; \ | |
231 int rc = pthread_mutex_trylock (& __mf_biglock); \ | |
232 if (rc) { __mf_lock_contention ++; \ | |
233 rc = pthread_mutex_lock (& __mf_biglock); } \ | |
234 assert (rc==0); } while (0) | |
235 #define UNLOCKTH() do { int rc = pthread_mutex_unlock (& __mf_biglock); \ | |
236 assert (rc==0); } while (0) | |
237 #else | |
238 #define LOCKTH() do {} while (0) | |
239 #define UNLOCKTH() do {} while (0) | |
240 #endif | |
241 | |
242 #if defined(LIBMUDFLAPTH) && (!defined(HAVE_TLS) || defined(USE_EMUTLS)) | |
243 extern enum __mf_state_enum __mf_get_state (void); | |
244 extern void __mf_set_state (enum __mf_state_enum); | |
245 #else | |
246 # ifdef LIBMUDFLAPTH | |
247 extern __thread enum __mf_state_enum __mf_state_1; | |
248 # else | |
249 extern enum __mf_state_enum __mf_state_1; | |
250 # endif | |
251 static inline enum __mf_state_enum __mf_get_state (void) | |
252 { | |
253 return __mf_state_1; | |
254 } | |
255 static inline void __mf_set_state (enum __mf_state_enum s) | |
256 { | |
257 __mf_state_1 = s; | |
258 } | |
259 #endif | |
260 | |
261 extern int __mf_starting_p; | |
262 extern struct __mf_options __mf_opts; | |
263 | |
264 /* ------------------------------------------------------------------------ */ | |
265 /* Utility macros. */ | |
266 /* ------------------------------------------------------------------------ */ | |
267 | |
268 #define UNLIKELY(e) (__builtin_expect (!!(e), 0)) | |
269 #define LIKELY(e) (__builtin_expect (!!(e), 1)) | |
270 #define STRINGIFY2(e) #e | |
271 #define STRINGIFY(e) STRINGIFY2(e) | |
272 | |
273 #ifdef LIBMUDFLAPTH | |
274 #define VERBOSE_TRACE(...) \ | |
275 do { if (UNLIKELY (__mf_opts.verbose_trace)) { \ | |
276 fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \ | |
277 fprintf (stderr, __VA_ARGS__); \ | |
278 } } while (0) | |
279 #define TRACE(...) \ | |
280 do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \ | |
281 fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \ | |
282 fprintf (stderr, __VA_ARGS__); \ | |
283 } } while (0) | |
284 #else | |
285 #define VERBOSE_TRACE(...) \ | |
286 do { if (UNLIKELY (__mf_opts.verbose_trace)) { \ | |
287 fprintf (stderr, "mf: "); \ | |
288 fprintf (stderr, __VA_ARGS__); \ | |
289 } } while (0) | |
290 #define TRACE(...) \ | |
291 do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \ | |
292 fprintf (stderr, "mf: "); \ | |
293 fprintf (stderr, __VA_ARGS__); \ | |
294 } } while (0) | |
295 #endif | |
296 | |
297 | |
298 #define __MF_PERSIST_MAX 256 | |
299 #define __MF_FREEQ_MAX 256 | |
300 | |
301 /* | |
302 Wrapping and redirection: | |
303 | |
304 Mudflap redirects a number of libc functions into itself, for "cheap" | |
305 verification (eg. strcpy, bzero, memcpy) and also to register / | |
306 unregister regions of memory as they are manipulated by the program | |
307 (eg. malloc/free, mmap/munmap). | |
308 | |
309 There are two methods of wrapping. | |
310 | |
311 (1) The static method involves a list of -wrap=foo flags being passed to | |
312 the linker, which then links references to "foo" to the symbol | |
313 "__wrap_foo", and links references to "__real_foo" to the symbol "foo". | |
314 When compiled without -DPIC, libmudflap.a contains such __wrap_foo | |
315 functions which delegate to __real_foo functions in libc to get their | |
316 work done. | |
317 | |
318 (2) The dynamic method involves providing a definition of symbol foo in | |
319 libmudflap.so and linking it earlier in the compiler command line, | |
320 before libc.so. The function "foo" in libmudflap must then call | |
321 dlsym(RTLD_NEXT, "foo") to acquire a pointer to the "real" libc foo, or | |
322 at least the "next" foo in the dynamic link resolution order. | |
323 | |
324 We switch between these two techniques by the presence of the -DPIC | |
325 #define passed in by libtool when building libmudflap. | |
326 */ | |
327 | |
328 | |
329 #ifdef PIC | |
330 | |
331 extern void __mf_resolve_single_dynamic (struct __mf_dynamic_entry *); | |
332 | |
333 #define _GNU_SOURCE | |
334 #include <dlfcn.h> | |
335 | |
336 #define WRAPPER(ret, fname, ...) \ | |
337 ret __wrap_ ## fname (__VA_ARGS__) \ | |
338 __attribute__ (( alias (#fname) )); \ | |
339 ret __real_ ## fname (__VA_ARGS__) \ | |
340 __attribute__ (( alias (#fname) )); \ | |
341 ret fname (__VA_ARGS__) | |
342 #define DECLARE(ty, fname, ...) \ | |
343 typedef ty (*__mf_fn_ ## fname) (__VA_ARGS__); \ | |
344 extern ty __mf_0fn_ ## fname (__VA_ARGS__); | |
345 #define CALL_REAL(fname, ...) \ | |
346 ({__mf_starting_p \ | |
347 ? __mf_0fn_ ## fname (__VA_ARGS__) \ | |
348 : (__mf_resolve_single_dynamic (& __mf_dynamic[dyn_ ## fname]), \ | |
349 (((__mf_fn_ ## fname)(__mf_dynamic[dyn_ ## fname].pointer)) (__VA_ARGS__)));}) | |
350 #define CALL_BACKUP(fname, ...) \ | |
351 __mf_0fn_ ## fname(__VA_ARGS__) | |
352 | |
353 #else /* not PIC --> static library */ | |
354 | |
355 #define WRAPPER(ret, fname, ...) \ | |
356 ret __wrap_ ## fname (__VA_ARGS__) | |
357 #define DECLARE(ty, fname, ...) \ | |
358 extern ty __real_ ## fname (__VA_ARGS__) | |
359 #define CALL_REAL(fname, ...) \ | |
360 __real_ ## fname (__VA_ARGS__) | |
361 #define CALL_BACKUP(fname, ...) \ | |
362 __real_ ## fname(__VA_ARGS__) | |
363 | |
364 #endif /* PIC */ | |
365 | |
366 /* WRAPPER2 is for functions intercepted via macros at compile time. */ | |
367 #define WRAPPER2(ret, fname, ...) \ | |
368 ret __mfwrap_ ## fname (__VA_ARGS__) | |
369 | |
370 | |
371 /* Utility macros for mf-hooks*.c */ | |
372 | |
373 #define MF_VALIDATE_EXTENT(value,size,acc,context) \ | |
374 do { \ | |
375 if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \ | |
376 if (acc == __MF_CHECK_WRITE || ! __mf_opts.ignore_reads) \ | |
377 __mf_check ((void *) (value), (size), acc, "(" context ")"); \ | |
378 } while (0) | |
379 #define BEGIN_PROTECT(fname, ...) \ | |
380 if (UNLIKELY (__mf_starting_p)) \ | |
381 { \ | |
382 return CALL_BACKUP(fname, __VA_ARGS__); \ | |
383 } \ | |
384 else if (UNLIKELY (__mf_get_state () == reentrant)) \ | |
385 { \ | |
386 extern unsigned long __mf_reentrancy; \ | |
387 __mf_reentrancy ++; \ | |
388 return CALL_REAL(fname, __VA_ARGS__); \ | |
389 } \ | |
390 else if (UNLIKELY (__mf_get_state () == in_malloc)) \ | |
391 { \ | |
392 return CALL_REAL(fname, __VA_ARGS__); \ | |
393 } \ | |
394 else \ | |
395 { \ | |
396 TRACE ("%s\n", __PRETTY_FUNCTION__); \ | |
397 } | |
398 | |
399 /* There is an assumption here that these will only be called in routines | |
400 that call BEGIN_PROTECT at the start, and hence the state must always | |
401 be active when BEGIN_MALLOC_PROTECT is called. */ | |
402 #define BEGIN_MALLOC_PROTECT() \ | |
403 __mf_set_state (in_malloc) | |
404 | |
405 #define END_MALLOC_PROTECT() \ | |
406 __mf_set_state (active) | |
407 | |
408 /* Unlocked variants of main entry points from mf-runtime.h. */ | |
409 extern void __mfu_check (void *ptr, size_t sz, int type, const char *location); | |
410 extern void __mfu_register (void *ptr, size_t sz, int type, const char *name); | |
411 extern void __mfu_unregister (void *ptr, size_t sz, int type); | |
412 extern void __mfu_report (); | |
413 extern int __mfu_set_options (const char *opts); | |
414 | |
415 | |
416 #endif /* __MF_IMPL_H */ |