OSDN Git Service

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