#ifndef __MF_IMPL_H
#define __MF_IMPL_H
#ifdef _MUDFLAP
#error "Do not compile this file with -fmudflap!"
#endif
#if HAVE_PTHREAD_H
#include <pthread.h>
#elif LIBMUDFLAPTH
#error "Cannot build libmudflapth without pthread.h."
#endif
#if HAVE_STDINT_H
#include <stdint.h>
#else
typedef __mf_uintptr_t uintptr_t;
#endif
#define __MF_TYPE_MAX_CEM __MF_TYPE_STACK
#define __MF_TYPE_MAX __MF_TYPE_GUESS
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#define MINPTR ((uintptr_t) 0)
#define MAXPTR (~ (uintptr_t) 0)
#define CLAMPSUB(ptr,offset) (((uintptr_t) ptr) >= (offset) ? ((uintptr_t) ptr)-((uintptr_t) offset) : MINPTR)
#define CLAMPADD(ptr,offset) (((uintptr_t) ptr) <= MAXPTR-(offset) ? ((uintptr_t) ptr)+((uintptr_t) offset) : MAXPTR)
#define CLAMPSZ(ptr,size) ((size) ? (((uintptr_t) ptr) <= MAXPTR-(size)+1 ? ((uintptr_t) ptr)+((uintptr_t) size) - 1 : MAXPTR) : ((uintptr_t) ptr))
#define __MF_CACHE_INDEX(ptr) ((((uintptr_t) (ptr)) >> __mf_lc_shift) & __mf_lc_mask)
#define __MF_CACHE_MISS_P(ptr,sz) ({ \
struct __mf_cache *elem = & __mf_lookup_cache[__MF_CACHE_INDEX((ptr))]; \
((elem->low > (uintptr_t) (ptr)) || \
(elem->high < (CLAMPADD((uintptr_t) (ptr), (uintptr_t) CLAMPSUB(sz,1) )))); })
extern void __mf_violation (void *ptr, size_t sz,
uintptr_t pc, const char *location,
int type);
extern size_t __mf_backtrace (char ***, void *, unsigned);
extern int __mf_heuristic_check (uintptr_t, uintptr_t);
enum __mf_state_enum { active, reentrant };
struct __mf_options
{
unsigned trace_mf_calls;
unsigned collect_stats;
unsigned sigusr1_report;
unsigned internal_checking;
unsigned tree_aging;
unsigned adapt_cache;
unsigned print_leaks;
unsigned check_initialization;
unsigned verbose_violations;
unsigned abbreviate;
unsigned verbose_trace;
unsigned wipe_stack;
unsigned wipe_heap;
unsigned free_queue_length;
unsigned persistent_count;
unsigned crumple_zone;
unsigned backtrace;
unsigned ignore_reads;
unsigned timestamps;
#ifdef LIBMUDFLAPTH
unsigned thread_stack;
#endif
enum
{
mode_nop,
mode_populate,
mode_check,
mode_violate
}
mudflap_mode;
enum
{
viol_nop,
viol_segv,
viol_abort,
viol_gdb
}
violation_mode;
unsigned heur_stack_bound;
unsigned heur_proc_map;
unsigned heur_start_end;
unsigned heur_std_data;
};
#ifdef PIC
struct __mf_dynamic_entry
{
void *pointer;
char *name;
char *version;
};
extern struct __mf_dynamic_entry __mf_dynamic[];
enum __mf_dynamic_index
{
dyn_calloc, dyn_free, dyn_malloc, dyn_mmap,
dyn_munmap, dyn_realloc,
dyn_INITRESOLVE,
#ifdef LIBMUDFLAPTH
dyn_pthread_create,
dyn_pthread_join,
dyn_pthread_exit
#endif
};
#endif
#ifdef LIBMUDFLAPTH
extern pthread_mutex_t __mf_biglock;
#define LOCKTH() do { extern unsigned long __mf_lock_contention; \
int rc = pthread_mutex_trylock (& __mf_biglock); \
if (rc) { __mf_lock_contention ++; \
rc = pthread_mutex_lock (& __mf_biglock); } \
assert (rc==0); } while (0)
#define UNLOCKTH() do { int rc = pthread_mutex_unlock (& __mf_biglock); \
assert (rc==0); } while (0)
#else
#define LOCKTH() do {} while (0)
#define UNLOCKTH() do {} while (0)
#endif
#ifdef LIBMUDFLAPTH
extern enum __mf_state_enum *__mf_state_perthread ();
#define __mf_state (* __mf_state_perthread ())
#else
extern enum __mf_state_enum __mf_state;
#endif
extern int __mf_starting_p;
extern struct __mf_options __mf_opts;
#define UNLIKELY(e) (__builtin_expect (!!(e), 0))
#define LIKELY(e) (__builtin_expect (!!(e), 1))
#define STRINGIFY2(e) #e
#define STRINGIFY(e) STRINGIFY2(e)
#ifdef LIBMUDFLAPTH
#define VERBOSE_TRACE(...) \
do { if (UNLIKELY (__mf_opts.verbose_trace)) { \
fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
fprintf (stderr, __VA_ARGS__); \
} } while (0)
#define TRACE(...) \
do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
fprintf (stderr, __VA_ARGS__); \
} } while (0)
#else
#define VERBOSE_TRACE(...) \
do { if (UNLIKELY (__mf_opts.verbose_trace)) { \
fprintf (stderr, "mf: "); \
fprintf (stderr, __VA_ARGS__); \
} } while (0)
#define TRACE(...) \
do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
fprintf (stderr, "mf: "); \
fprintf (stderr, __VA_ARGS__); \
} } while (0)
#endif
#define __MF_PERSIST_MAX 256
#define __MF_FREEQ_MAX 256
#ifdef PIC
extern void __mf_resolve_single_dynamic (struct __mf_dynamic_entry *);
#define _GNU_SOURCE
#include <dlfcn.h>
#define WRAPPER(ret, fname, ...) \
ret __wrap_ ## fname (__VA_ARGS__) \
__attribute__ (( alias (#fname) )); \
ret __real_ ## fname (__VA_ARGS__) \
__attribute__ (( alias (#fname) )); \
ret fname (__VA_ARGS__)
#define DECLARE(ty, fname, ...) \
typedef ty (*__mf_fn_ ## fname) (__VA_ARGS__); \
extern ty __mf_0fn_ ## fname (__VA_ARGS__);
#define CALL_REAL(fname, ...) \
({__mf_starting_p \
? __mf_0fn_ ## fname (__VA_ARGS__) \
: (__mf_resolve_single_dynamic (& __mf_dynamic[dyn_ ## fname]), \
(((__mf_fn_ ## fname)(__mf_dynamic[dyn_ ## fname].pointer)) (__VA_ARGS__)));})
#define CALL_BACKUP(fname, ...) \
__mf_0fn_ ## fname(__VA_ARGS__)
#else
#define WRAPPER(ret, fname, ...) \
ret __wrap_ ## fname (__VA_ARGS__)
#define DECLARE(ty, fname, ...) \
extern ty __real_ ## fname (__VA_ARGS__)
#define CALL_REAL(fname, ...) \
__real_ ## fname (__VA_ARGS__)
#define CALL_BACKUP(fname, ...) \
__real_ ## fname(__VA_ARGS__)
#endif
#define WRAPPER2(ret, fname, ...) \
ret __mfwrap_ ## fname (__VA_ARGS__)
#define MF_VALIDATE_EXTENT(value,size,acc,context) \
do { \
if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \
if (acc == __MF_CHECK_WRITE || ! __mf_opts.ignore_reads) \
__mf_check ((void *) (value), (size), acc, "(" context ")"); \
} while (0)
#define BEGIN_PROTECT(fname, ...) \
if (UNLIKELY (__mf_starting_p)) \
{ \
return CALL_BACKUP(fname, __VA_ARGS__); \
} \
else if (UNLIKELY (__mf_state == reentrant)) \
{ \
extern unsigned long __mf_reentrancy; \
__mf_reentrancy ++; \
return CALL_REAL(fname, __VA_ARGS__); \
} \
else \
{ \
TRACE ("%s\n", __PRETTY_FUNCTION__); \
}
extern void __mfu_check (void *ptr, size_t sz, int type, const char *location);
extern void __mfu_register (void *ptr, size_t sz, int type, const char *name);
extern void __mfu_unregister (void *ptr, size_t sz, int type);
extern void __mfu_report ();
extern int __mfu_set_options (const char *opts);
#endif