OSDN Git Service

2005-08-17 Kelley Cook <kcook@gcc.gnu.org>
[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, 51 Franklin Street, Fifth Floor, Boston, MA
31 02110-1301, 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 #define mode_nop 0      /* Do nothing.  */
171 #define mode_populate 1 /* Populate tree but do not check for violations.  */
172 #define mode_check 2    /* Populate and check for violations (normal).  */
173 #define mode_violate 3  /* Trigger a violation on every call (diagnostic).  */
174   unsigned mudflap_mode;
175
176   /* How to handle a violation. */
177 #define viol_nop 0   /* Return control to application. */
178 #define viol_segv 1  /* Signal self with segv. */
179 #define viol_abort 2 /* Call abort (). */
180 #define viol_gdb 3   /* Fork a debugger on self */
181   unsigned violation_mode;
182
183   /* Violation heuristics selection. */
184   unsigned heur_stack_bound; /* allow current stack region */
185   unsigned heur_proc_map;  /* allow & cache /proc/self/map regions.  */
186   unsigned heur_start_end; /* allow _start .. _end */
187   unsigned heur_std_data; /* allow & cache stdlib data */
188 };
189
190
191 #ifdef PIC
192
193 /* This is a table of dynamically resolved function pointers. */
194
195 struct __mf_dynamic_entry
196 {
197   void *pointer;
198   char *name;
199   char *version;
200 };
201
202 /* The definition of the array (mf-runtime.c) must match the enums!  */
203 extern struct __mf_dynamic_entry __mf_dynamic[];
204 enum __mf_dynamic_index
205 {
206   dyn_calloc, dyn_free, dyn_malloc, dyn_mmap,
207   dyn_munmap, dyn_realloc,
208   dyn_INITRESOLVE,  /* Marker for last init-time resolution. */
209 #ifdef LIBMUDFLAPTH
210   dyn_pthread_create
211 #endif
212 };
213
214 #endif /* PIC */
215
216 /* ------------------------------------------------------------------------ */
217 /* Private global variables. */
218 /* ------------------------------------------------------------------------ */
219
220 #ifdef LIBMUDFLAPTH
221 extern pthread_mutex_t __mf_biglock;
222 #define LOCKTH() do { extern unsigned long __mf_lock_contention; \
223                       int rc = pthread_mutex_trylock (& __mf_biglock); \
224                       if (rc) { __mf_lock_contention ++; \
225                                 rc = pthread_mutex_lock (& __mf_biglock); } \
226                       assert (rc==0); } while (0)
227 #define UNLOCKTH() do { int rc = pthread_mutex_unlock (& __mf_biglock); \
228                         assert (rc==0); } while (0)
229 #else
230 #define LOCKTH() do {} while (0)
231 #define UNLOCKTH() do {} while (0)
232 #endif
233
234 #if defined(LIBMUDFLAPTH) && !defined(HAVE_TLS)
235 extern enum __mf_state_enum __mf_get_state (void);
236 extern void __mf_set_state (enum __mf_state_enum);
237 #else
238 # ifdef LIBMUDFLAPTH
239 extern __thread enum __mf_state_enum __mf_state_1;
240 # else
241 extern enum __mf_state_enum __mf_state_1;
242 # endif
243 static inline enum __mf_state_enum __mf_get_state (void)
244 {
245   return __mf_state_1;
246 }
247 static inline void __mf_set_state (enum __mf_state_enum s)
248 {
249   __mf_state_1 = s;
250 }
251 #endif
252
253 extern int __mf_starting_p;
254 extern struct __mf_options __mf_opts;
255
256 /* ------------------------------------------------------------------------ */
257 /* Utility macros. */
258 /* ------------------------------------------------------------------------ */
259
260 #define UNLIKELY(e) (__builtin_expect (!!(e), 0))
261 #define LIKELY(e) (__builtin_expect (!!(e), 1))
262 #define STRINGIFY2(e) #e
263 #define STRINGIFY(e) STRINGIFY2(e)
264
265 #ifdef LIBMUDFLAPTH
266 #define VERBOSE_TRACE(...) \
267   do { if (UNLIKELY (__mf_opts.verbose_trace)) {  \
268       fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
269       fprintf (stderr, __VA_ARGS__); \
270     } } while (0)
271 #define TRACE(...) \
272   do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
273       fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
274       fprintf (stderr, __VA_ARGS__); \
275     } } while (0)
276 #else
277 #define VERBOSE_TRACE(...) \
278   do { if (UNLIKELY (__mf_opts.verbose_trace)) {  \
279       fprintf (stderr, "mf: "); \
280       fprintf (stderr, __VA_ARGS__); \
281     } } while (0)
282 #define TRACE(...) \
283   do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
284       fprintf (stderr, "mf: "); \
285       fprintf (stderr, __VA_ARGS__); \
286     } } while (0)
287 #endif
288
289
290 #define __MF_PERSIST_MAX 256
291 #define __MF_FREEQ_MAX 256
292
293 /*
294    Wrapping and redirection:
295
296    Mudflap redirects a number of libc functions into itself, for "cheap"
297    verification (eg. strcpy, bzero, memcpy) and also to register /
298    unregister regions of memory as they are manipulated by the program
299    (eg. malloc/free, mmap/munmap).
300
301    There are two methods of wrapping.
302
303    (1) The static method involves a list of -wrap=foo flags being passed to
304    the linker, which then links references to "foo" to the symbol
305    "__wrap_foo", and links references to "__real_foo" to the symbol "foo".
306    When compiled without -DPIC, libmudflap.a contains such __wrap_foo
307    functions which delegate to __real_foo functions in libc to get their
308    work done.
309
310    (2) The dynamic method involves providing a definition of symbol foo in
311    libmudflap.so and linking it earlier in the compiler command line,
312    before libc.so. The function "foo" in libmudflap must then call
313    dlsym(RTLD_NEXT, "foo") to acquire a pointer to the "real" libc foo, or
314    at least the "next" foo in the dynamic link resolution order.
315
316    We switch between these two techniques by the presence of the -DPIC
317    #define passed in by libtool when building libmudflap.
318 */
319
320
321 #ifdef PIC
322
323 extern void __mf_resolve_single_dynamic (struct __mf_dynamic_entry *);
324
325 #define _GNU_SOURCE
326 #include <dlfcn.h>
327
328 #define WRAPPER(ret, fname, ...)                      \
329 ret __wrap_ ## fname (__VA_ARGS__)                    \
330     __attribute__ (( alias  (#fname)  ));             \
331 ret __real_ ## fname (__VA_ARGS__)                    \
332     __attribute__ (( alias  (#fname)  ));             \
333 ret fname (__VA_ARGS__)
334 #define DECLARE(ty, fname, ...)                       \
335  typedef ty (*__mf_fn_ ## fname) (__VA_ARGS__);       \
336  extern ty __mf_0fn_ ## fname (__VA_ARGS__);
337 #define CALL_REAL(fname, ...)                         \
338   ({__mf_starting_p \
339      ? __mf_0fn_ ## fname (__VA_ARGS__) \
340     : (__mf_resolve_single_dynamic (& __mf_dynamic[dyn_ ## fname]), \
341        (((__mf_fn_ ## fname)(__mf_dynamic[dyn_ ## fname].pointer)) (__VA_ARGS__)));})
342 #define CALL_BACKUP(fname, ...)                       \
343   __mf_0fn_ ## fname(__VA_ARGS__)
344
345 #else /* not PIC --> static library */
346
347 #define WRAPPER(ret, fname, ...)            \
348 ret __wrap_ ## fname (__VA_ARGS__)
349 #define DECLARE(ty, fname, ...)             \
350  extern ty __real_ ## fname (__VA_ARGS__)
351 #define CALL_REAL(fname, ...)               \
352  __real_ ## fname (__VA_ARGS__)
353 #define CALL_BACKUP(fname, ...)             \
354   __real_ ## fname(__VA_ARGS__)
355
356 #endif /* PIC */
357
358 /* WRAPPER2 is for functions intercepted via macros at compile time. */
359 #define WRAPPER2(ret, fname, ...)                     \
360 ret __mfwrap_ ## fname (__VA_ARGS__)
361
362
363 /* Utility macros for mf-hooks*.c */
364
365 #define MF_VALIDATE_EXTENT(value,size,acc,context) \
366  do { \
367   if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \
368     if (acc == __MF_CHECK_WRITE || ! __mf_opts.ignore_reads) \
369     __mf_check ((void *) (value), (size), acc, "(" context ")"); \
370  } while (0)
371 #define BEGIN_PROTECT(fname, ...)       \
372   if (UNLIKELY (__mf_starting_p)) \
373   {                                         \
374     return CALL_BACKUP(fname, __VA_ARGS__); \
375   }                                         \
376   else if (UNLIKELY (__mf_get_state () == reentrant))   \
377   {                                         \
378     extern unsigned long __mf_reentrancy;   \
379     __mf_reentrancy ++; \
380     return CALL_REAL(fname, __VA_ARGS__);   \
381   }                                         \
382   else                                      \
383   {                                         \
384     TRACE ("%s\n", __PRETTY_FUNCTION__); \
385   }
386
387
388 /* Unlocked variants of main entry points from mf-runtime.h.  */
389 extern void __mfu_check (void *ptr, size_t sz, int type, const char *location);
390 extern void __mfu_register (void *ptr, size_t sz, int type, const char *name);
391 extern void __mfu_unregister (void *ptr, size_t sz, int type);
392 extern void __mfu_report ();
393 extern int __mfu_set_options (const char *opts);
394
395
396 #endif /* __MF_IMPL_H */