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