Home | History | Annotate | Line # | Download | only in lsan
      1 //=-- lsan_interceptors.cc ------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of LeakSanitizer.
     11 // Interceptors for standalone LSan.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "interception/interception.h"
     16 #include "sanitizer_common/sanitizer_allocator.h"
     17 #include "sanitizer_common/sanitizer_allocator_report.h"
     18 #include "sanitizer_common/sanitizer_atomic.h"
     19 #include "sanitizer_common/sanitizer_common.h"
     20 #include "sanitizer_common/sanitizer_flags.h"
     21 #include "sanitizer_common/sanitizer_internal_defs.h"
     22 #include "sanitizer_common/sanitizer_linux.h"
     23 #include "sanitizer_common/sanitizer_platform_interceptors.h"
     24 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
     25 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
     26 #include "sanitizer_common/sanitizer_posix.h"
     27 #include "sanitizer_common/sanitizer_tls_get_addr.h"
     28 #include "lsan.h"
     29 #include "lsan_allocator.h"
     30 #include "lsan_common.h"
     31 #include "lsan_thread.h"
     32 
     33 #include <stddef.h>
     34 
     35 using namespace __lsan;
     36 
     37 extern "C" {
     38 int pthread_attr_init(void *attr);
     39 int pthread_attr_destroy(void *attr);
     40 int pthread_attr_getdetachstate(void *attr, int *v);
     41 int pthread_key_create(unsigned *key, void (*destructor)(void* v));
     42 int pthread_setspecific(unsigned key, const void *v);
     43 }
     44 
     45 ///// Malloc/free interceptors. /////
     46 
     47 namespace std {
     48   struct nothrow_t;
     49   enum class align_val_t: size_t;
     50 }
     51 
     52 #if !SANITIZER_MAC
     53 INTERCEPTOR(void*, malloc, uptr size) {
     54   ENSURE_LSAN_INITED;
     55   GET_STACK_TRACE_MALLOC;
     56   return lsan_malloc(size, stack);
     57 }
     58 
     59 INTERCEPTOR(void, free, void *p) {
     60   ENSURE_LSAN_INITED;
     61   lsan_free(p);
     62 }
     63 
     64 INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
     65   if (lsan_init_is_running) {
     66     // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
     67     const uptr kCallocPoolSize = 1024;
     68     static uptr calloc_memory_for_dlsym[kCallocPoolSize];
     69     static uptr allocated;
     70     uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
     71     void *mem = (void*)&calloc_memory_for_dlsym[allocated];
     72     allocated += size_in_words;
     73     CHECK(allocated < kCallocPoolSize);
     74     return mem;
     75   }
     76   ENSURE_LSAN_INITED;
     77   GET_STACK_TRACE_MALLOC;
     78   return lsan_calloc(nmemb, size, stack);
     79 }
     80 
     81 INTERCEPTOR(void*, realloc, void *q, uptr size) {
     82   ENSURE_LSAN_INITED;
     83   GET_STACK_TRACE_MALLOC;
     84   return lsan_realloc(q, size, stack);
     85 }
     86 
     87 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
     88   ENSURE_LSAN_INITED;
     89   GET_STACK_TRACE_MALLOC;
     90   return lsan_posix_memalign(memptr, alignment, size, stack);
     91 }
     92 
     93 INTERCEPTOR(void*, valloc, uptr size) {
     94   ENSURE_LSAN_INITED;
     95   GET_STACK_TRACE_MALLOC;
     96   return lsan_valloc(size, stack);
     97 }
     98 #endif
     99 
    100 #if SANITIZER_INTERCEPT_MEMALIGN
    101 INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
    102   ENSURE_LSAN_INITED;
    103   GET_STACK_TRACE_MALLOC;
    104   return lsan_memalign(alignment, size, stack);
    105 }
    106 #define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
    107 
    108 INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {
    109   ENSURE_LSAN_INITED;
    110   GET_STACK_TRACE_MALLOC;
    111   void *res = lsan_memalign(alignment, size, stack);
    112   DTLS_on_libc_memalign(res, size);
    113   return res;
    114 }
    115 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
    116 #else
    117 #define LSAN_MAYBE_INTERCEPT_MEMALIGN
    118 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
    119 #endif // SANITIZER_INTERCEPT_MEMALIGN
    120 
    121 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
    122 INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
    123   ENSURE_LSAN_INITED;
    124   GET_STACK_TRACE_MALLOC;
    125   return lsan_aligned_alloc(alignment, size, stack);
    126 }
    127 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)
    128 #else
    129 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC
    130 #endif
    131 
    132 #if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE
    133 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
    134   ENSURE_LSAN_INITED;
    135   return GetMallocUsableSize(ptr);
    136 }
    137 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
    138         INTERCEPT_FUNCTION(malloc_usable_size)
    139 #else
    140 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
    141 #endif
    142 
    143 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
    144 struct fake_mallinfo {
    145   int x[10];
    146 };
    147 
    148 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
    149   struct fake_mallinfo res;
    150   internal_memset(&res, 0, sizeof(res));
    151   return res;
    152 }
    153 #define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
    154 
    155 INTERCEPTOR(int, mallopt, int cmd, int value) {
    156   return 0;
    157 }
    158 #define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
    159 #else
    160 #define LSAN_MAYBE_INTERCEPT_MALLINFO
    161 #define LSAN_MAYBE_INTERCEPT_MALLOPT
    162 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
    163 
    164 #if SANITIZER_INTERCEPT_PVALLOC
    165 INTERCEPTOR(void*, pvalloc, uptr size) {
    166   ENSURE_LSAN_INITED;
    167   GET_STACK_TRACE_MALLOC;
    168   return lsan_pvalloc(size, stack);
    169 }
    170 #define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
    171 #else
    172 #define LSAN_MAYBE_INTERCEPT_PVALLOC
    173 #endif // SANITIZER_INTERCEPT_PVALLOC
    174 
    175 #if SANITIZER_INTERCEPT_CFREE
    176 INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free));
    177 #define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
    178 #else
    179 #define LSAN_MAYBE_INTERCEPT_CFREE
    180 #endif // SANITIZER_INTERCEPT_CFREE
    181 
    182 #if SANITIZER_INTERCEPT_MCHECK_MPROBE
    183 INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
    184   return 0;
    185 }
    186 
    187 INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
    188   return 0;
    189 }
    190 
    191 INTERCEPTOR(int, mprobe, void *ptr) {
    192   return 0;
    193 }
    194 #endif // SANITIZER_INTERCEPT_MCHECK_MPROBE
    195 
    196 
    197 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
    198 #define OPERATOR_NEW_BODY(nothrow)\
    199   ENSURE_LSAN_INITED;\
    200   GET_STACK_TRACE_MALLOC;\
    201   void *res = lsan_malloc(size, stack);\
    202   if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
    203   return res;
    204 #define OPERATOR_NEW_BODY_ALIGN(nothrow)\
    205   ENSURE_LSAN_INITED;\
    206   GET_STACK_TRACE_MALLOC;\
    207   void *res = lsan_memalign((uptr)align, size, stack);\
    208   if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
    209   return res;
    210 
    211 #define OPERATOR_DELETE_BODY\
    212   ENSURE_LSAN_INITED;\
    213   lsan_free(ptr);
    214 
    215 // On OS X it's not enough to just provide our own 'operator new' and
    216 // 'operator delete' implementations, because they're going to be in the runtime
    217 // dylib, and the main executable will depend on both the runtime dylib and
    218 // libstdc++, each of has its implementation of new and delete.
    219 // To make sure that C++ allocation/deallocation operators are overridden on
    220 // OS X we need to intercept them using their mangled names.
    221 #if !SANITIZER_MAC
    222 
    223 INTERCEPTOR_ATTRIBUTE
    224 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
    225 INTERCEPTOR_ATTRIBUTE
    226 void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
    227 INTERCEPTOR_ATTRIBUTE
    228 void *operator new(size_t size, std::nothrow_t const&)
    229 { OPERATOR_NEW_BODY(true /*nothrow*/); }
    230 INTERCEPTOR_ATTRIBUTE
    231 void *operator new[](size_t size, std::nothrow_t const&)
    232 { OPERATOR_NEW_BODY(true /*nothrow*/); }
    233 INTERCEPTOR_ATTRIBUTE
    234 void *operator new(size_t size, std::align_val_t align)
    235 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
    236 INTERCEPTOR_ATTRIBUTE
    237 void *operator new[](size_t size, std::align_val_t align)
    238 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
    239 INTERCEPTOR_ATTRIBUTE
    240 void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
    241 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
    242 INTERCEPTOR_ATTRIBUTE
    243 void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
    244 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
    245 
    246 INTERCEPTOR_ATTRIBUTE
    247 void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
    248 INTERCEPTOR_ATTRIBUTE
    249 void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
    250 INTERCEPTOR_ATTRIBUTE
    251 void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
    252 INTERCEPTOR_ATTRIBUTE
    253 void operator delete[](void *ptr, std::nothrow_t const &)
    254 { OPERATOR_DELETE_BODY; }
    255 INTERCEPTOR_ATTRIBUTE
    256 void operator delete(void *ptr, size_t size) NOEXCEPT
    257 { OPERATOR_DELETE_BODY; }
    258 INTERCEPTOR_ATTRIBUTE
    259 void operator delete[](void *ptr, size_t size) NOEXCEPT
    260 { OPERATOR_DELETE_BODY; }
    261 INTERCEPTOR_ATTRIBUTE
    262 void operator delete(void *ptr, std::align_val_t) NOEXCEPT
    263 { OPERATOR_DELETE_BODY; }
    264 INTERCEPTOR_ATTRIBUTE
    265 void operator delete[](void *ptr, std::align_val_t) NOEXCEPT
    266 { OPERATOR_DELETE_BODY; }
    267 INTERCEPTOR_ATTRIBUTE
    268 void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&)
    269 { OPERATOR_DELETE_BODY; }
    270 INTERCEPTOR_ATTRIBUTE
    271 void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&)
    272 { OPERATOR_DELETE_BODY; }
    273 INTERCEPTOR_ATTRIBUTE
    274 void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT
    275 { OPERATOR_DELETE_BODY; }
    276 INTERCEPTOR_ATTRIBUTE
    277 void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT
    278 { OPERATOR_DELETE_BODY; }
    279 
    280 #else  // SANITIZER_MAC
    281 
    282 INTERCEPTOR(void *, _Znwm, size_t size)
    283 { OPERATOR_NEW_BODY(false /*nothrow*/); }
    284 INTERCEPTOR(void *, _Znam, size_t size)
    285 { OPERATOR_NEW_BODY(false /*nothrow*/); }
    286 INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&)
    287 { OPERATOR_NEW_BODY(true /*nothrow*/); }
    288 INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&)
    289 { OPERATOR_NEW_BODY(true /*nothrow*/); }
    290 
    291 INTERCEPTOR(void, _ZdlPv, void *ptr)
    292 { OPERATOR_DELETE_BODY; }
    293 INTERCEPTOR(void, _ZdaPv, void *ptr)
    294 { OPERATOR_DELETE_BODY; }
    295 INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
    296 { OPERATOR_DELETE_BODY; }
    297 INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
    298 { OPERATOR_DELETE_BODY; }
    299 
    300 #endif  // !SANITIZER_MAC
    301 
    302 
    303 ///// Thread initialization and finalization. /////
    304 
    305 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
    306 static unsigned g_thread_finalize_key;
    307 
    308 static void thread_finalize(void *v) {
    309   uptr iter = (uptr)v;
    310   if (iter > 1) {
    311     if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
    312       Report("LeakSanitizer: failed to set thread key.\n");
    313       Die();
    314     }
    315     return;
    316   }
    317   ThreadFinish();
    318 }
    319 #endif
    320 
    321 #if SANITIZER_NETBSD
    322 INTERCEPTOR(void, _lwp_exit) {
    323   ENSURE_LSAN_INITED;
    324   ThreadFinish();
    325   REAL(_lwp_exit)();
    326 }
    327 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit)
    328 #else
    329 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT
    330 #endif
    331 
    332 #if SANITIZER_INTERCEPT_THR_EXIT
    333 INTERCEPTOR(void, thr_exit, tid_t *state) {
    334   ENSURE_LSAN_INITED;
    335   ThreadFinish();
    336   REAL(thr_exit)(state);
    337 }
    338 #define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit)
    339 #else
    340 #define LSAN_MAYBE_INTERCEPT_THR_EXIT
    341 #endif
    342 
    343 struct ThreadParam {
    344   void *(*callback)(void *arg);
    345   void *param;
    346   atomic_uintptr_t tid;
    347 };
    348 
    349 extern "C" void *__lsan_thread_start_func(void *arg) {
    350   ThreadParam *p = (ThreadParam*)arg;
    351   void* (*callback)(void *arg) = p->callback;
    352   void *param = p->param;
    353   // Wait until the last iteration to maximize the chance that we are the last
    354   // destructor to run.
    355 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
    356   if (pthread_setspecific(g_thread_finalize_key,
    357                           (void*)GetPthreadDestructorIterations())) {
    358     Report("LeakSanitizer: failed to set thread key.\n");
    359     Die();
    360   }
    361 #endif
    362   int tid = 0;
    363   while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
    364     internal_sched_yield();
    365   SetCurrentThread(tid);
    366   ThreadStart(tid, GetTid());
    367   atomic_store(&p->tid, 0, memory_order_release);
    368   return callback(param);
    369 }
    370 
    371 INTERCEPTOR(int, pthread_create, void *th, void *attr,
    372             void *(*callback)(void *), void *param) {
    373   ENSURE_LSAN_INITED;
    374   EnsureMainThreadIDIsCorrect();
    375   __sanitizer_pthread_attr_t myattr;
    376   if (!attr) {
    377     pthread_attr_init(&myattr);
    378     attr = &myattr;
    379   }
    380   AdjustStackSize(attr);
    381   int detached = 0;
    382   pthread_attr_getdetachstate(attr, &detached);
    383   ThreadParam p;
    384   p.callback = callback;
    385   p.param = param;
    386   atomic_store(&p.tid, 0, memory_order_relaxed);
    387   int res;
    388   {
    389     // Ignore all allocations made by pthread_create: thread stack/TLS may be
    390     // stored by pthread for future reuse even after thread destruction, and
    391     // the linked list it's stored in doesn't even hold valid pointers to the
    392     // objects, the latter are calculated by obscure pointer arithmetic.
    393     ScopedInterceptorDisabler disabler;
    394     res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p);
    395   }
    396   if (res == 0) {
    397     int tid = ThreadCreate(GetCurrentThread(), *(uptr *)th,
    398                            IsStateDetached(detached));
    399     CHECK_NE(tid, 0);
    400     atomic_store(&p.tid, tid, memory_order_release);
    401     while (atomic_load(&p.tid, memory_order_acquire) != 0)
    402       internal_sched_yield();
    403   }
    404   if (attr == &myattr)
    405     pthread_attr_destroy(&myattr);
    406   return res;
    407 }
    408 
    409 INTERCEPTOR(int, pthread_join, void *th, void **ret) {
    410   ENSURE_LSAN_INITED;
    411   int tid = ThreadTid((uptr)th);
    412   int res = REAL(pthread_join)(th, ret);
    413   if (res == 0)
    414     ThreadJoin(tid);
    415   return res;
    416 }
    417 
    418 INTERCEPTOR(void, _exit, int status) {
    419   if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode;
    420   REAL(_exit)(status);
    421 }
    422 
    423 #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
    424 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
    425 
    426 namespace __lsan {
    427 
    428 void InitializeInterceptors() {
    429   InitializeSignalInterceptors();
    430 
    431   INTERCEPT_FUNCTION(malloc);
    432   INTERCEPT_FUNCTION(free);
    433   LSAN_MAYBE_INTERCEPT_CFREE;
    434   INTERCEPT_FUNCTION(calloc);
    435   INTERCEPT_FUNCTION(realloc);
    436   LSAN_MAYBE_INTERCEPT_MEMALIGN;
    437   LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
    438   LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;
    439   INTERCEPT_FUNCTION(posix_memalign);
    440   INTERCEPT_FUNCTION(valloc);
    441   LSAN_MAYBE_INTERCEPT_PVALLOC;
    442   LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
    443   LSAN_MAYBE_INTERCEPT_MALLINFO;
    444   LSAN_MAYBE_INTERCEPT_MALLOPT;
    445   INTERCEPT_FUNCTION(pthread_create);
    446   INTERCEPT_FUNCTION(pthread_join);
    447   INTERCEPT_FUNCTION(_exit);
    448 
    449   LSAN_MAYBE_INTERCEPT__LWP_EXIT;
    450   LSAN_MAYBE_INTERCEPT_THR_EXIT;
    451 
    452 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
    453   if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
    454     Report("LeakSanitizer: failed to create thread key.\n");
    455     Die();
    456   }
    457 #endif
    458 }
    459 
    460 } // namespace __lsan
    461