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 35using namespace __lsan; 36 37extern "C" { 38int pthread_attr_init(void *attr); 39int pthread_attr_destroy(void *attr); 40int pthread_attr_getdetachstate(void *attr, int *v); 41int pthread_key_create(unsigned *key, void (*destructor)(void* v)); 42int pthread_setspecific(unsigned key, const void *v); 43} 44 45///// Malloc/free interceptors. ///// 46 47namespace std { 48 struct nothrow_t; 49 enum class align_val_t: size_t; 50} 51 52#if !SANITIZER_MAC 53INTERCEPTOR(void*, malloc, uptr size) { 54 ENSURE_LSAN_INITED; 55 GET_STACK_TRACE_MALLOC; 56 return lsan_malloc(size, stack); 57} 58 59INTERCEPTOR(void, free, void *p) { 60 ENSURE_LSAN_INITED; 61 lsan_free(p); 62} 63 64INTERCEPTOR(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 81INTERCEPTOR(void*, realloc, void *q, uptr size) { 82 ENSURE_LSAN_INITED; 83 GET_STACK_TRACE_MALLOC; 84 return lsan_realloc(q, size, stack); 85} 86 87INTERCEPTOR(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 93INTERCEPTOR(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 101INTERCEPTOR(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 108INTERCEPTOR(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 122INTERCEPTOR(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 133INTERCEPTOR(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 144struct fake_mallinfo { 145 int x[10]; 146}; 147 148INTERCEPTOR(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 155INTERCEPTOR(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 165INTERCEPTOR(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 176INTERCEPTOR(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 183INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) { 184 return 0; 185} 186 187INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) { 188 return 0; 189} 190 191INTERCEPTOR(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 223INTERCEPTOR_ATTRIBUTE 224void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 225INTERCEPTOR_ATTRIBUTE 226void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 227INTERCEPTOR_ATTRIBUTE 228void *operator new(size_t size, std::nothrow_t const&) 229{ OPERATOR_NEW_BODY(true /*nothrow*/); } 230INTERCEPTOR_ATTRIBUTE 231void *operator new[](size_t size, std::nothrow_t const&) 232{ OPERATOR_NEW_BODY(true /*nothrow*/); } 233INTERCEPTOR_ATTRIBUTE 234void *operator new(size_t size, std::align_val_t align) 235{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 236INTERCEPTOR_ATTRIBUTE 237void *operator new[](size_t size, std::align_val_t align) 238{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 239INTERCEPTOR_ATTRIBUTE 240void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 241{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 242INTERCEPTOR_ATTRIBUTE 243void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 244{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 245 246INTERCEPTOR_ATTRIBUTE 247void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 248INTERCEPTOR_ATTRIBUTE 249void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 250INTERCEPTOR_ATTRIBUTE 251void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 252INTERCEPTOR_ATTRIBUTE 253void operator delete[](void *ptr, std::nothrow_t const &) 254{ OPERATOR_DELETE_BODY; } 255INTERCEPTOR_ATTRIBUTE 256void operator delete(void *ptr, size_t size) NOEXCEPT 257{ OPERATOR_DELETE_BODY; } 258INTERCEPTOR_ATTRIBUTE 259void operator delete[](void *ptr, size_t size) NOEXCEPT 260{ OPERATOR_DELETE_BODY; } 261INTERCEPTOR_ATTRIBUTE 262void operator delete(void *ptr, std::align_val_t) NOEXCEPT 263{ OPERATOR_DELETE_BODY; } 264INTERCEPTOR_ATTRIBUTE 265void operator delete[](void *ptr, std::align_val_t) NOEXCEPT 266{ OPERATOR_DELETE_BODY; } 267INTERCEPTOR_ATTRIBUTE 268void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&) 269{ OPERATOR_DELETE_BODY; } 270INTERCEPTOR_ATTRIBUTE 271void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&) 272{ OPERATOR_DELETE_BODY; } 273INTERCEPTOR_ATTRIBUTE 274void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT 275{ OPERATOR_DELETE_BODY; } 276INTERCEPTOR_ATTRIBUTE 277void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT 278{ OPERATOR_DELETE_BODY; } 279 280#else // SANITIZER_MAC 281 282INTERCEPTOR(void *, _Znwm, size_t size) 283{ OPERATOR_NEW_BODY(false /*nothrow*/); } 284INTERCEPTOR(void *, _Znam, size_t size) 285{ OPERATOR_NEW_BODY(false /*nothrow*/); } 286INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) 287{ OPERATOR_NEW_BODY(true /*nothrow*/); } 288INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) 289{ OPERATOR_NEW_BODY(true /*nothrow*/); } 290 291INTERCEPTOR(void, _ZdlPv, void *ptr) 292{ OPERATOR_DELETE_BODY; } 293INTERCEPTOR(void, _ZdaPv, void *ptr) 294{ OPERATOR_DELETE_BODY; } 295INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 296{ OPERATOR_DELETE_BODY; } 297INTERCEPTOR(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 306static unsigned g_thread_finalize_key; 307 308static 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 322INTERCEPTOR(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 333INTERCEPTOR(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 343struct ThreadParam { 344 void *(*callback)(void *arg); 345 void *param; 346 atomic_uintptr_t tid; 347}; 348 349extern "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 371INTERCEPTOR(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 409INTERCEPTOR(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 418INTERCEPTOR(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 426namespace __lsan { 427 428void 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