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