OSDN Git Service

Introduce and use config/gcc-version.m4.
[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 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
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 enum __mf_state_enum { active, reentrant }; 
95
96 /* The __mf_options structure records optional or tunable aspects of the
97  mudflap library's behavior. There is a single global instance of this
98  structure which is populated from user input (in an environment variable)
99  when the library initializes. */
100
101 struct __mf_options
102 {
103   /* Emit a trace message for each call. */
104   unsigned trace_mf_calls;
105
106   /* Collect and emit statistics. */
107   unsigned collect_stats;
108
109   /* Set up a SIGUSR1 -> __mf_report handler. */
110   unsigned sigusr1_report;
111
112   /* Execute internal checking code. */
113   unsigned internal_checking;
114
115   /* Age object liveness periodically. */
116   unsigned tree_aging;
117
118   /* Adapt the lookup cache to working set. */
119   unsigned adapt_cache;
120
121   /* Print list of leaked heap objects on shutdown. */
122   unsigned print_leaks;       
123
124   /* Detect reads of uninitialized objects. */
125   unsigned check_initialization;       
126
127   /* Print verbose description of violations. */
128   unsigned verbose_violations;
129
130   /* Abbreviate duplicate object descriptions.  */
131   unsigned abbreviate;
132
133   /* Emit internal tracing message. */
134   unsigned verbose_trace;
135
136   /* Wipe stack/heap objects upon unwind.  */
137   unsigned wipe_stack;
138   unsigned wipe_heap;
139
140   /* Maintain a queue of this many deferred free()s, 
141      to trap use of freed memory. */
142   unsigned free_queue_length;
143
144   /* Maintain a history of this many past unregistered objects. */
145   unsigned persistent_count;
146
147   /* Pad allocated extents by this many bytes on either side. */
148   unsigned crumple_zone;
149
150   /* Maintain this many stack frames for contexts. */
151   unsigned backtrace;
152
153   /* Ignore read operations even if mode_check is in effect.  */
154   unsigned ignore_reads;
155
156   /* Collect register/unregister timestamps.  */
157   unsigned timestamps;
158
159 #ifdef LIBMUDFLAPTH
160   /* Thread stack size.  */
161   unsigned thread_stack;
162 #endif
163
164   /* Major operation mode */
165   enum
166   {
167     mode_nop,        /* mudflaps do nothing */
168     mode_populate,   /* mudflaps populate tree but do not check for violations */
169     mode_check,      /* mudflaps populate and check for violations (normal) */
170     mode_violate     /* mudflaps trigger a violation on every call (diagnostic) */
171   }
172   mudflap_mode;
173
174   /* How to handle a violation. */
175   enum
176   {
177     viol_nop,        /* Return control to application. */ 
178     viol_segv,       /* Signal self with segv. */
179     viol_abort,      /* Call abort (). */
180     viol_gdb         /* Fork a debugger on self */
181   }
182   violation_mode;
183
184   /* Violation heuristics selection. */
185   unsigned heur_stack_bound; /* allow current stack region */
186   unsigned heur_proc_map;  /* allow & cache /proc/self/map regions.  */
187   unsigned heur_start_end; /* allow _start .. _end */
188   unsigned heur_std_data; /* allow & cache stdlib data */
189 };
190
191
192 #ifdef PIC
193
194 /* This is a table of dynamically resolved function pointers. */
195
196 struct __mf_dynamic_entry
197 {
198   void *pointer;
199   char *name;
200   char *version;
201 };
202
203 /* The definition of the array (mf-runtime.c) must match the enums!  */
204 extern struct __mf_dynamic_entry __mf_dynamic[];
205 enum __mf_dynamic_index
206
207   dyn_calloc, dyn_free, dyn_malloc, dyn_mmap,
208   dyn_munmap, dyn_realloc, 
209   dyn_INITRESOLVE,  /* Marker for last init-time resolution. */
210 #ifdef LIBMUDFLAPTH 
211   dyn_pthread_create,
212   dyn_pthread_join,
213   dyn_pthread_exit
214 #endif
215 };
216
217 #endif /* PIC */
218
219 /* ------------------------------------------------------------------------ */
220 /* Private global variables. */
221 /* ------------------------------------------------------------------------ */
222
223 #ifdef LIBMUDFLAPTH
224 extern pthread_mutex_t __mf_biglock;
225 #define LOCKTH() do { extern unsigned long __mf_lock_contention; \
226                       int rc = pthread_mutex_trylock (& __mf_biglock); \
227                       if (rc) { __mf_lock_contention ++; \
228                                 rc = pthread_mutex_lock (& __mf_biglock); } \
229                       assert (rc==0); } while (0)
230 #define UNLOCKTH() do { int rc = pthread_mutex_unlock (& __mf_biglock); \
231                         assert (rc==0); } while (0)
232 #else
233 #define LOCKTH() do {} while (0)
234 #define UNLOCKTH() do {} while (0)
235 #endif
236
237 #ifdef LIBMUDFLAPTH
238 extern enum __mf_state_enum *__mf_state_perthread ();
239 #define __mf_state (* __mf_state_perthread ())
240 #else 
241 extern enum __mf_state_enum __mf_state;
242 #endif
243 extern int __mf_starting_p;
244 extern struct __mf_options __mf_opts;
245
246 /* ------------------------------------------------------------------------ */
247 /* Utility macros. */
248 /* ------------------------------------------------------------------------ */
249
250 #define UNLIKELY(e) (__builtin_expect (!!(e), 0))
251 #define LIKELY(e) (__builtin_expect (!!(e), 1))
252 #define STRINGIFY2(e) #e
253 #define STRINGIFY(e) STRINGIFY2(e)
254
255 #ifdef LIBMUDFLAPTH
256 #define VERBOSE_TRACE(...) \
257   do { if (UNLIKELY (__mf_opts.verbose_trace)) {  \
258       fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
259       fprintf (stderr, __VA_ARGS__); \
260     } } while (0)
261 #define TRACE(...) \
262   do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
263       fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
264       fprintf (stderr, __VA_ARGS__); \
265     } } while (0)
266 #else
267 #define VERBOSE_TRACE(...) \
268   do { if (UNLIKELY (__mf_opts.verbose_trace)) {  \
269       fprintf (stderr, "mf: "); \
270       fprintf (stderr, __VA_ARGS__); \
271     } } while (0)
272 #define TRACE(...) \
273   do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
274       fprintf (stderr, "mf: "); \
275       fprintf (stderr, __VA_ARGS__); \
276     } } while (0)
277 #endif
278
279
280 #define __MF_PERSIST_MAX 256
281 #define __MF_FREEQ_MAX 256
282
283 /* 
284    Wrapping and redirection:
285
286    Mudflap redirects a number of libc functions into itself, for "cheap"
287    verification (eg. strcpy, bzero, memcpy) and also to register /
288    unregister regions of memory as they are manipulated by the program
289    (eg. malloc/free, mmap/munmap).
290
291    There are two methods of wrapping. 
292
293    (1) The static method involves a list of -wrap=foo flags being passed to
294    the linker, which then links references to "foo" to the symbol
295    "__wrap_foo", and links references to "__real_foo" to the symbol "foo".
296    When compiled without -DPIC, libmudflap.a contains such __wrap_foo
297    functions which delegate to __real_foo functions in libc to get their
298    work done.
299
300    (2) The dynamic method involves providing a definition of symbol foo in
301    libmudflap.so and linking it earlier in the compiler command line,
302    before libc.so. The function "foo" in libmudflap must then call
303    dlsym(RTLD_NEXT, "foo") to acquire a pointer to the "real" libc foo, or
304    at least the "next" foo in the dynamic link resolution order.
305
306    We switch between these two techniques by the presence of the -DPIC
307    #define passed in by libtool when building libmudflap.
308 */
309
310
311 #ifdef PIC
312
313 extern void __mf_resolve_single_dynamic (struct __mf_dynamic_entry *);
314
315 #define _GNU_SOURCE
316 #include <dlfcn.h>
317
318 #define WRAPPER(ret, fname, ...)                      \
319 ret __wrap_ ## fname (__VA_ARGS__)                    \
320     __attribute__ (( alias  (#fname)  ));             \
321 ret __real_ ## fname (__VA_ARGS__)                    \
322     __attribute__ (( alias  (#fname)  ));             \
323 ret fname (__VA_ARGS__)
324 #define DECLARE(ty, fname, ...)                       \
325  typedef ty (*__mf_fn_ ## fname) (__VA_ARGS__);       \
326  extern ty __mf_0fn_ ## fname (__VA_ARGS__);
327 #define CALL_REAL(fname, ...)                         \
328   ({__mf_starting_p \
329      ? __mf_0fn_ ## fname (__VA_ARGS__) \
330     : (__mf_resolve_single_dynamic (& __mf_dynamic[dyn_ ## fname]), \
331        (((__mf_fn_ ## fname)(__mf_dynamic[dyn_ ## fname].pointer)) (__VA_ARGS__)));})
332 #define CALL_BACKUP(fname, ...)                       \
333   __mf_0fn_ ## fname(__VA_ARGS__)
334
335 #else /* not PIC --> static library */
336
337 #define WRAPPER(ret, fname, ...)            \
338 ret __wrap_ ## fname (__VA_ARGS__)
339 #define DECLARE(ty, fname, ...)             \
340  extern ty __real_ ## fname (__VA_ARGS__)
341 #define CALL_REAL(fname, ...)               \
342  __real_ ## fname (__VA_ARGS__)
343 #define CALL_BACKUP(fname, ...)             \
344   __real_ ## fname(__VA_ARGS__)
345
346 #endif /* PIC */
347
348 /* WRAPPER2 is for functions intercepted via macros at compile time. */
349 #define WRAPPER2(ret, fname, ...)                     \
350 ret __mfwrap_ ## fname (__VA_ARGS__)
351
352
353 /* Utility macros for mf-hooks*.c */
354
355 #define MF_VALIDATE_EXTENT(value,size,acc,context) \
356  do { \
357   if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \
358     if (acc == __MF_CHECK_WRITE || ! __mf_opts.ignore_reads) \
359     __mf_check ((void *) (value), (size), acc, "(" context ")"); \
360  } while (0)
361 #define BEGIN_PROTECT(fname, ...)       \
362   if (UNLIKELY (__mf_starting_p)) \
363   {                                         \
364     return CALL_BACKUP(fname, __VA_ARGS__); \
365   }                                         \
366   else if (UNLIKELY (__mf_state == reentrant))   \
367   {                                         \
368     extern unsigned long __mf_reentrancy;   \
369     __mf_reentrancy ++; \
370     return CALL_REAL(fname, __VA_ARGS__);   \
371   }                                         \
372   else                                      \
373   {                                         \
374     TRACE ("%s\n", __PRETTY_FUNCTION__); \
375   }
376
377
378 /* Unlocked variants of main entry points from mf-runtime.h.  */
379 extern void __mfu_check (void *ptr, size_t sz, int type, const char *location);
380 extern void __mfu_register (void *ptr, size_t sz, int type, const char *name);
381 extern void __mfu_unregister (void *ptr, size_t sz, int type);
382 extern void __mfu_report ();
383 extern int __mfu_set_options (const char *opts);
384
385
386 #endif /* __MF_IMPL_H */