1169695Skan/* Implementation header for mudflap runtime library.
2169695Skan   Mudflap: narrow-pointer bounds-checking by tree rewriting.
3169695Skan   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4169695Skan   Contributed by Frank Ch. Eigler <fche@redhat.com>
5169695Skan   and Graydon Hoare <graydon@redhat.com>
6169695Skan
7169695SkanThis file is part of GCC.
8169695Skan
9169695SkanGCC is free software; you can redistribute it and/or modify it under
10169695Skanthe terms of the GNU General Public License as published by the Free
11169695SkanSoftware Foundation; either version 2, or (at your option) any later
12169695Skanversion.
13169695Skan
14169695SkanIn addition to the permissions in the GNU General Public License, the
15169695SkanFree Software Foundation gives you unlimited permission to link the
16169695Skancompiled version of this file into combinations with other programs,
17169695Skanand to distribute those combinations without any restriction coming
18169695Skanfrom the use of this file.  (The General Public License restrictions
19169695Skando apply in other respects; for example, they cover modification of
20169695Skanthe file, and distribution when not linked into a combine
21169695Skanexecutable.)
22169695Skan
23169695SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
24169695SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
25169695SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26169695Skanfor more details.
27169695Skan
28169695SkanYou should have received a copy of the GNU General Public License
29169695Skanalong with GCC; see the file COPYING.  If not, write to the Free
30169695SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
31169695Skan02110-1301, USA.  */
32169695Skan
33169695Skan#ifndef __MF_IMPL_H
34169695Skan#define __MF_IMPL_H
35169695Skan
36169695Skan#ifdef _MUDFLAP
37169695Skan#error "Do not compile this file with -fmudflap!"
38169695Skan#endif
39169695Skan
40169695Skan#if HAVE_PTHREAD_H
41169695Skan#include <pthread.h>
42169695Skan#elif LIBMUDFLAPTH
43169695Skan#error "Cannot build libmudflapth without pthread.h."
44169695Skan#endif
45169695Skan
46169695Skan#if HAVE_STDINT_H
47169695Skan#include <stdint.h>
48169695Skan#else
49169695Skantypedef __mf_uintptr_t uintptr_t;
50169695Skan#endif
51169695Skan
52169695Skan/* Private definitions related to mf-runtime.h  */
53169695Skan
54169695Skan#define __MF_TYPE_MAX_CEM  __MF_TYPE_STACK  /* largest type# for the cemetary */
55169695Skan#define __MF_TYPE_MAX __MF_TYPE_GUESS
56169695Skan
57169695Skan
58169695Skan#ifndef max
59169695Skan#define max(a,b) ((a) > (b) ? (a) : (b))
60169695Skan#endif
61169695Skan
62169695Skan#ifndef min
63169695Skan#define min(a,b) ((a) < (b) ? (a) : (b))
64169695Skan#endif
65169695Skan
66169695Skan/* Address calculation macros.  */
67169695Skan
68169695Skan#define MINPTR ((uintptr_t) 0)
69169695Skan#define MAXPTR (~ (uintptr_t) 0)
70169695Skan
71169695Skan/* Clamp the addition/subtraction of uintptr_t's to [MINPTR,MAXPTR] */
72169695Skan#define CLAMPSUB(ptr,offset) (((uintptr_t) ptr) >= (offset) ? ((uintptr_t) ptr)-((uintptr_t) offset) : MINPTR)
73169695Skan#define CLAMPADD(ptr,offset) (((uintptr_t) ptr) <= MAXPTR-(offset) ? ((uintptr_t) ptr)+((uintptr_t) offset) : MAXPTR)
74169695Skan#define CLAMPSZ(ptr,size) ((size) ? (((uintptr_t) ptr) <= MAXPTR-(size)+1 ? ((uintptr_t) ptr)+((uintptr_t) size) - 1 : MAXPTR) : ((uintptr_t) ptr))
75169695Skan
76169695Skan#define __MF_CACHE_INDEX(ptr) ((((uintptr_t) (ptr)) >> __mf_lc_shift) & __mf_lc_mask)
77169695Skan#define __MF_CACHE_MISS_P(ptr,sz) ({ \
78169695Skan             struct __mf_cache *elem = & __mf_lookup_cache[__MF_CACHE_INDEX((ptr))]; \
79169695Skan             ((elem->low > (uintptr_t) (ptr)) ||                  \
80169695Skan	      (elem->high < (CLAMPADD((uintptr_t) (ptr), (uintptr_t) CLAMPSUB(sz,1) )))); })
81169695Skan/* XXX: the above should use CLAMPSZ () */
82169695Skan
83169695Skan
84169695Skan
85169695Skan/* Private functions. */
86169695Skan
87169695Skanextern void __mf_violation (void *ptr, size_t sz,
88169695Skan			    uintptr_t pc, const char *location,
89169695Skan			    int type);
90169695Skanextern size_t __mf_backtrace (char ***, void *, unsigned);
91169695Skanextern int __mf_heuristic_check (uintptr_t, uintptr_t);
92169695Skan
93169695Skan/* ------------------------------------------------------------------------ */
94169695Skan/* Type definitions. */
95169695Skan/* ------------------------------------------------------------------------ */
96169695Skan
97169695Skan/* The mf_state type codes describe recursion and initialization order.
98169695Skan
99169695Skan   reentrant means we are inside a mf-runtime support routine, such as
100169695Skan   __mf_register, and thus there should be no calls to any wrapped functions,
101169695Skan   such as the wrapped malloc.  This indicates a bug if it occurs.
102169695Skan   in_malloc means we are inside a real malloc call inside a wrapped malloc
103169695Skan   call, and thus there should be no calls to any wrapped functions like the
104169695Skan   wrapped mmap.  This happens on some systems due to how the system libraries
105169695Skan   are constructed.  */
106169695Skan
107169695Skanenum __mf_state_enum { active, reentrant, in_malloc };
108169695Skan
109169695Skan/* The __mf_options structure records optional or tunable aspects of the
110169695Skan mudflap library's behavior. There is a single global instance of this
111169695Skan structure which is populated from user input (in an environment variable)
112169695Skan when the library initializes. */
113169695Skan
114169695Skanstruct __mf_options
115169695Skan{
116169695Skan  /* Emit a trace message for each call. */
117169695Skan  unsigned trace_mf_calls;
118169695Skan
119169695Skan  /* Collect and emit statistics. */
120169695Skan  unsigned collect_stats;
121169695Skan
122169695Skan  /* Set up a SIGUSR1 -> __mf_report handler. */
123169695Skan  unsigned sigusr1_report;
124169695Skan
125169695Skan  /* Execute internal checking code. */
126169695Skan  unsigned internal_checking;
127169695Skan
128169695Skan  /* Age object liveness periodically. */
129169695Skan  unsigned tree_aging;
130169695Skan
131169695Skan  /* Adapt the lookup cache to working set. */
132169695Skan  unsigned adapt_cache;
133169695Skan
134169695Skan  /* Print list of leaked heap objects on shutdown. */
135169695Skan  unsigned print_leaks;
136169695Skan
137169695Skan  /* Detect reads of uninitialized objects. */
138169695Skan  unsigned check_initialization;
139169695Skan
140169695Skan  /* Print verbose description of violations. */
141169695Skan  unsigned verbose_violations;
142169695Skan
143169695Skan  /* Abbreviate duplicate object descriptions.  */
144169695Skan  unsigned abbreviate;
145169695Skan
146169695Skan  /* Emit internal tracing message. */
147169695Skan  unsigned verbose_trace;
148169695Skan
149169695Skan  /* Wipe stack/heap objects upon unwind.  */
150169695Skan  unsigned wipe_stack;
151169695Skan  unsigned wipe_heap;
152169695Skan
153169695Skan  /* Maintain a queue of this many deferred free()s,
154169695Skan     to trap use of freed memory. */
155169695Skan  unsigned free_queue_length;
156169695Skan
157169695Skan  /* Maintain a history of this many past unregistered objects. */
158169695Skan  unsigned persistent_count;
159169695Skan
160169695Skan  /* Pad allocated extents by this many bytes on either side. */
161169695Skan  unsigned crumple_zone;
162169695Skan
163169695Skan  /* Maintain this many stack frames for contexts. */
164169695Skan  unsigned backtrace;
165169695Skan
166169695Skan  /* Ignore read operations even if mode_check is in effect.  */
167169695Skan  unsigned ignore_reads;
168169695Skan
169169695Skan  /* Collect register/unregister timestamps.  */
170169695Skan  unsigned timestamps;
171169695Skan
172169695Skan#ifdef LIBMUDFLAPTH
173169695Skan  /* Thread stack size.  */
174169695Skan  unsigned thread_stack;
175169695Skan#endif
176169695Skan
177169695Skan  /* Major operation mode */
178169695Skan#define mode_nop 0      /* Do nothing.  */
179169695Skan#define mode_populate 1 /* Populate tree but do not check for violations.  */
180169695Skan#define mode_check 2    /* Populate and check for violations (normal).  */
181169695Skan#define mode_violate 3  /* Trigger a violation on every call (diagnostic).  */
182169695Skan  unsigned mudflap_mode;
183169695Skan
184169695Skan  /* How to handle a violation. */
185169695Skan#define viol_nop 0   /* Return control to application. */
186169695Skan#define viol_segv 1  /* Signal self with segv. */
187169695Skan#define viol_abort 2 /* Call abort (). */
188169695Skan#define viol_gdb 3   /* Fork a debugger on self */
189169695Skan  unsigned violation_mode;
190169695Skan
191169695Skan  /* Violation heuristics selection. */
192169695Skan  unsigned heur_stack_bound; /* allow current stack region */
193169695Skan  unsigned heur_proc_map;  /* allow & cache /proc/self/map regions.  */
194169695Skan  unsigned heur_start_end; /* allow _start .. _end */
195169695Skan  unsigned heur_std_data; /* allow & cache stdlib data */
196169695Skan};
197169695Skan
198169695Skan
199169695Skan#ifdef PIC
200169695Skan
201169695Skan/* This is a table of dynamically resolved function pointers. */
202169695Skan
203169695Skanstruct __mf_dynamic_entry
204169695Skan{
205169695Skan  void *pointer;
206169695Skan  char *name;
207169695Skan  char *version;
208169695Skan};
209169695Skan
210169695Skan/* The definition of the array (mf-runtime.c) must match the enums!  */
211169695Skanextern struct __mf_dynamic_entry __mf_dynamic[];
212169695Skanenum __mf_dynamic_index
213169695Skan{
214169695Skan  dyn_calloc, dyn_free, dyn_malloc, dyn_mmap,
215169695Skan  dyn_munmap, dyn_realloc,
216169695Skan  dyn_INITRESOLVE,  /* Marker for last init-time resolution. */
217169695Skan#ifdef LIBMUDFLAPTH
218169695Skan  dyn_pthread_create
219169695Skan#endif
220169695Skan};
221169695Skan
222169695Skan#endif /* PIC */
223169695Skan
224169695Skan/* ------------------------------------------------------------------------ */
225169695Skan/* Private global variables. */
226169695Skan/* ------------------------------------------------------------------------ */
227169695Skan
228169695Skan#ifdef LIBMUDFLAPTH
229169695Skanextern pthread_mutex_t __mf_biglock;
230169695Skan#define LOCKTH() do { extern unsigned long __mf_lock_contention; \
231169695Skan                      int rc = pthread_mutex_trylock (& __mf_biglock); \
232169695Skan                      if (rc) { __mf_lock_contention ++; \
233169695Skan                                rc = pthread_mutex_lock (& __mf_biglock); } \
234169695Skan                      assert (rc==0); } while (0)
235169695Skan#define UNLOCKTH() do { int rc = pthread_mutex_unlock (& __mf_biglock); \
236169695Skan                        assert (rc==0); } while (0)
237169695Skan#else
238169695Skan#define LOCKTH() do {} while (0)
239169695Skan#define UNLOCKTH() do {} while (0)
240169695Skan#endif
241169695Skan
242169695Skan#if defined(LIBMUDFLAPTH) && !defined(HAVE_TLS)
243169695Skanextern enum __mf_state_enum __mf_get_state (void);
244169695Skanextern void __mf_set_state (enum __mf_state_enum);
245169695Skan#else
246169695Skan# ifdef LIBMUDFLAPTH
247169695Skanextern __thread enum __mf_state_enum __mf_state_1;
248169695Skan# else
249169695Skanextern enum __mf_state_enum __mf_state_1;
250169695Skan# endif
251169695Skanstatic inline enum __mf_state_enum __mf_get_state (void)
252169695Skan{
253169695Skan  return __mf_state_1;
254169695Skan}
255169695Skanstatic inline void __mf_set_state (enum __mf_state_enum s)
256169695Skan{
257169695Skan  __mf_state_1 = s;
258169695Skan}
259169695Skan#endif
260169695Skan
261169695Skanextern int __mf_starting_p;
262169695Skanextern struct __mf_options __mf_opts;
263169695Skan
264169695Skan/* ------------------------------------------------------------------------ */
265169695Skan/* Utility macros. */
266169695Skan/* ------------------------------------------------------------------------ */
267169695Skan
268169695Skan#define UNLIKELY(e) (__builtin_expect (!!(e), 0))
269169695Skan#define LIKELY(e) (__builtin_expect (!!(e), 1))
270169695Skan#define STRINGIFY2(e) #e
271169695Skan#define STRINGIFY(e) STRINGIFY2(e)
272169695Skan
273169695Skan#ifdef LIBMUDFLAPTH
274169695Skan#define VERBOSE_TRACE(...) \
275169695Skan  do { if (UNLIKELY (__mf_opts.verbose_trace)) {  \
276169695Skan      fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
277169695Skan      fprintf (stderr, __VA_ARGS__); \
278169695Skan    } } while (0)
279169695Skan#define TRACE(...) \
280169695Skan  do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
281169695Skan      fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
282169695Skan      fprintf (stderr, __VA_ARGS__); \
283169695Skan    } } while (0)
284169695Skan#else
285169695Skan#define VERBOSE_TRACE(...) \
286169695Skan  do { if (UNLIKELY (__mf_opts.verbose_trace)) {  \
287169695Skan      fprintf (stderr, "mf: "); \
288169695Skan      fprintf (stderr, __VA_ARGS__); \
289169695Skan    } } while (0)
290169695Skan#define TRACE(...) \
291169695Skan  do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
292169695Skan      fprintf (stderr, "mf: "); \
293169695Skan      fprintf (stderr, __VA_ARGS__); \
294169695Skan    } } while (0)
295169695Skan#endif
296169695Skan
297169695Skan
298169695Skan#define __MF_PERSIST_MAX 256
299169695Skan#define __MF_FREEQ_MAX 256
300169695Skan
301169695Skan/*
302169695Skan   Wrapping and redirection:
303169695Skan
304169695Skan   Mudflap redirects a number of libc functions into itself, for "cheap"
305169695Skan   verification (eg. strcpy, bzero, memcpy) and also to register /
306169695Skan   unregister regions of memory as they are manipulated by the program
307169695Skan   (eg. malloc/free, mmap/munmap).
308169695Skan
309169695Skan   There are two methods of wrapping.
310169695Skan
311169695Skan   (1) The static method involves a list of -wrap=foo flags being passed to
312169695Skan   the linker, which then links references to "foo" to the symbol
313169695Skan   "__wrap_foo", and links references to "__real_foo" to the symbol "foo".
314169695Skan   When compiled without -DPIC, libmudflap.a contains such __wrap_foo
315169695Skan   functions which delegate to __real_foo functions in libc to get their
316169695Skan   work done.
317169695Skan
318169695Skan   (2) The dynamic method involves providing a definition of symbol foo in
319169695Skan   libmudflap.so and linking it earlier in the compiler command line,
320169695Skan   before libc.so. The function "foo" in libmudflap must then call
321169695Skan   dlsym(RTLD_NEXT, "foo") to acquire a pointer to the "real" libc foo, or
322169695Skan   at least the "next" foo in the dynamic link resolution order.
323169695Skan
324169695Skan   We switch between these two techniques by the presence of the -DPIC
325169695Skan   #define passed in by libtool when building libmudflap.
326169695Skan*/
327169695Skan
328169695Skan
329169695Skan#ifdef PIC
330169695Skan
331169695Skanextern void __mf_resolve_single_dynamic (struct __mf_dynamic_entry *);
332169695Skan
333169695Skan#define _GNU_SOURCE
334169695Skan#include <dlfcn.h>
335169695Skan
336169695Skan#define WRAPPER(ret, fname, ...)                      \
337169695Skanret __wrap_ ## fname (__VA_ARGS__)                    \
338169695Skan    __attribute__ (( alias  (#fname)  ));             \
339169695Skanret __real_ ## fname (__VA_ARGS__)                    \
340169695Skan    __attribute__ (( alias  (#fname)  ));             \
341169695Skanret fname (__VA_ARGS__)
342169695Skan#define DECLARE(ty, fname, ...)                       \
343169695Skan typedef ty (*__mf_fn_ ## fname) (__VA_ARGS__);       \
344169695Skan extern ty __mf_0fn_ ## fname (__VA_ARGS__);
345169695Skan#define CALL_REAL(fname, ...)                         \
346169695Skan  ({__mf_starting_p \
347169695Skan     ? __mf_0fn_ ## fname (__VA_ARGS__) \
348169695Skan    : (__mf_resolve_single_dynamic (& __mf_dynamic[dyn_ ## fname]), \
349169695Skan       (((__mf_fn_ ## fname)(__mf_dynamic[dyn_ ## fname].pointer)) (__VA_ARGS__)));})
350169695Skan#define CALL_BACKUP(fname, ...)                       \
351169695Skan  __mf_0fn_ ## fname(__VA_ARGS__)
352169695Skan
353169695Skan#else /* not PIC --> static library */
354169695Skan
355169695Skan#define WRAPPER(ret, fname, ...)            \
356169695Skanret __wrap_ ## fname (__VA_ARGS__)
357169695Skan#define DECLARE(ty, fname, ...)             \
358169695Skan extern ty __real_ ## fname (__VA_ARGS__)
359169695Skan#define CALL_REAL(fname, ...)               \
360169695Skan __real_ ## fname (__VA_ARGS__)
361169695Skan#define CALL_BACKUP(fname, ...)             \
362169695Skan  __real_ ## fname(__VA_ARGS__)
363169695Skan
364169695Skan#endif /* PIC */
365169695Skan
366169695Skan/* WRAPPER2 is for functions intercepted via macros at compile time. */
367169695Skan#define WRAPPER2(ret, fname, ...)                     \
368169695Skanret __mfwrap_ ## fname (__VA_ARGS__)
369169695Skan
370169695Skan
371169695Skan/* Utility macros for mf-hooks*.c */
372169695Skan
373169695Skan#define MF_VALIDATE_EXTENT(value,size,acc,context) \
374169695Skan do { \
375169695Skan  if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \
376169695Skan    if (acc == __MF_CHECK_WRITE || ! __mf_opts.ignore_reads) \
377169695Skan    __mf_check ((void *) (value), (size), acc, "(" context ")"); \
378169695Skan } while (0)
379169695Skan#define BEGIN_PROTECT(fname, ...)       \
380169695Skan  if (UNLIKELY (__mf_starting_p)) \
381169695Skan  {                                         \
382169695Skan    return CALL_BACKUP(fname, __VA_ARGS__); \
383169695Skan  }                                         \
384169695Skan  else if (UNLIKELY (__mf_get_state () == reentrant))   \
385169695Skan  {                                         \
386169695Skan    extern unsigned long __mf_reentrancy;   \
387169695Skan    __mf_reentrancy ++; \
388169695Skan    return CALL_REAL(fname, __VA_ARGS__);   \
389169695Skan  }                                         \
390169695Skan  else if (UNLIKELY (__mf_get_state () == in_malloc))   \
391169695Skan  {                                         \
392169695Skan    return CALL_REAL(fname, __VA_ARGS__);   \
393169695Skan  }                                         \
394169695Skan  else                                      \
395169695Skan  {                                         \
396169695Skan    TRACE ("%s\n", __PRETTY_FUNCTION__); \
397169695Skan  }
398169695Skan
399169695Skan/* There is an assumption here that these will only be called in routines
400169695Skan   that call BEGIN_PROTECT at the start, and hence the state must always
401169695Skan   be active when BEGIN_MALLOC_PROTECT is called.  */
402169695Skan#define BEGIN_MALLOC_PROTECT() \
403169695Skan  __mf_set_state (in_malloc)
404169695Skan
405169695Skan#define END_MALLOC_PROTECT() \
406169695Skan  __mf_set_state (active)
407169695Skan
408169695Skan/* Unlocked variants of main entry points from mf-runtime.h.  */
409169695Skanextern void __mfu_check (void *ptr, size_t sz, int type, const char *location);
410169695Skanextern void __mfu_register (void *ptr, size_t sz, int type, const char *name);
411169695Skanextern void __mfu_unregister (void *ptr, size_t sz, int type);
412169695Skanextern void __mfu_report ();
413169695Skanextern int __mfu_set_options (const char *opts);
414169695Skan
415169695Skan
416169695Skan#endif /* __MF_IMPL_H */
417