1 //=-- lsan_interceptors.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of LeakSanitizer. 10 // Interceptors for standalone LSan. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "interception/interception.h" 15 #include "sanitizer_common/sanitizer_allocator.h" 16 #include "sanitizer_common/sanitizer_allocator_dlsym.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 #if SANITIZER_POSIX 27 #include "sanitizer_common/sanitizer_posix.h" 28 #endif 29 #include "sanitizer_common/sanitizer_tls_get_addr.h" 30 #include "lsan.h" 31 #include "lsan_allocator.h" 32 #include "lsan_common.h" 33 #include "lsan_thread.h" 34 35 #include <stddef.h> 36 37 using namespace __lsan; 38 39 extern "C" { 40 int pthread_attr_init(void *attr); 41 int pthread_attr_destroy(void *attr); 42 int pthread_attr_getdetachstate(void *attr, int *v); 43 int pthread_key_create(unsigned *key, void (*destructor)(void* v)); 44 int pthread_setspecific(unsigned key, const void *v); 45 } 46 47 struct DlsymAlloc : DlSymAllocator<DlsymAlloc> { 48 static bool UseImpl() { return lsan_init_is_running; } 49 static void OnAllocate(const void *ptr, uptr size) { 50 #if CAN_SANITIZE_LEAKS 51 // Suppress leaks from dlerror(). Previously dlsym hack on global array was 52 // used by leak sanitizer as a root region. 53 __lsan_register_root_region(ptr, size); 54 #endif 55 } 56 static void OnFree(const void *ptr, uptr size) { 57 #if CAN_SANITIZE_LEAKS 58 __lsan_unregister_root_region(ptr, size); 59 #endif 60 } 61 }; 62 63 ///// Malloc/free interceptors. ///// 64 65 namespace std { 66 struct nothrow_t; 67 enum class align_val_t: size_t; 68 } 69 70 #if !SANITIZER_APPLE 71 INTERCEPTOR(void*, malloc, uptr size) { 72 if (DlsymAlloc::Use()) 73 return DlsymAlloc::Allocate(size); 74 ENSURE_LSAN_INITED; 75 GET_STACK_TRACE_MALLOC; 76 return lsan_malloc(size, stack); 77 } 78 79 INTERCEPTOR(void, free, void *p) { 80 if (UNLIKELY(!p)) 81 return; 82 if (DlsymAlloc::PointerIsMine(p)) 83 return DlsymAlloc::Free(p); 84 ENSURE_LSAN_INITED; 85 lsan_free(p); 86 } 87 88 INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 89 if (DlsymAlloc::Use()) 90 return DlsymAlloc::Callocate(nmemb, size); 91 ENSURE_LSAN_INITED; 92 GET_STACK_TRACE_MALLOC; 93 return lsan_calloc(nmemb, size, stack); 94 } 95 96 INTERCEPTOR(void *, realloc, void *ptr, uptr size) { 97 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 98 return DlsymAlloc::Realloc(ptr, size); 99 ENSURE_LSAN_INITED; 100 GET_STACK_TRACE_MALLOC; 101 return lsan_realloc(ptr, size, stack); 102 } 103 104 INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) { 105 ENSURE_LSAN_INITED; 106 GET_STACK_TRACE_MALLOC; 107 return lsan_reallocarray(q, nmemb, size, stack); 108 } 109 110 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 111 ENSURE_LSAN_INITED; 112 GET_STACK_TRACE_MALLOC; 113 return lsan_posix_memalign(memptr, alignment, size, stack); 114 } 115 116 INTERCEPTOR(void*, valloc, uptr size) { 117 ENSURE_LSAN_INITED; 118 GET_STACK_TRACE_MALLOC; 119 return lsan_valloc(size, stack); 120 } 121 #endif // !SANITIZER_APPLE 122 123 #if SANITIZER_INTERCEPT_MEMALIGN 124 INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { 125 ENSURE_LSAN_INITED; 126 GET_STACK_TRACE_MALLOC; 127 return lsan_memalign(alignment, size, stack); 128 } 129 #define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign) 130 #else 131 #define LSAN_MAYBE_INTERCEPT_MEMALIGN 132 #endif // SANITIZER_INTERCEPT_MEMALIGN 133 134 #if SANITIZER_INTERCEPT___LIBC_MEMALIGN 135 INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) { 136 ENSURE_LSAN_INITED; 137 GET_STACK_TRACE_MALLOC; 138 void *res = lsan_memalign(alignment, size, stack); 139 DTLS_on_libc_memalign(res, size); 140 return res; 141 } 142 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign) 143 #else 144 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN 145 #endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN 146 147 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 148 INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) { 149 ENSURE_LSAN_INITED; 150 GET_STACK_TRACE_MALLOC; 151 return lsan_aligned_alloc(alignment, size, stack); 152 } 153 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc) 154 #else 155 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC 156 #endif 157 158 #if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE 159 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 160 ENSURE_LSAN_INITED; 161 return GetMallocUsableSize(ptr); 162 } 163 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \ 164 INTERCEPT_FUNCTION(malloc_usable_size) 165 #else 166 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE 167 #endif 168 169 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 170 struct fake_mallinfo { 171 int x[10]; 172 }; 173 174 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 175 struct fake_mallinfo res; 176 internal_memset(&res, 0, sizeof(res)); 177 return res; 178 } 179 #define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo) 180 181 INTERCEPTOR(int, mallopt, int cmd, int value) { 182 return 0; 183 } 184 #define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) 185 #else 186 #define LSAN_MAYBE_INTERCEPT_MALLINFO 187 #define LSAN_MAYBE_INTERCEPT_MALLOPT 188 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 189 190 #if SANITIZER_INTERCEPT_PVALLOC 191 INTERCEPTOR(void*, pvalloc, uptr size) { 192 ENSURE_LSAN_INITED; 193 GET_STACK_TRACE_MALLOC; 194 return lsan_pvalloc(size, stack); 195 } 196 #define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) 197 #else 198 #define LSAN_MAYBE_INTERCEPT_PVALLOC 199 #endif // SANITIZER_INTERCEPT_PVALLOC 200 201 #if SANITIZER_INTERCEPT_CFREE 202 INTERCEPTOR(void, cfree, void *p) ALIAS(WRAP(free)); 203 #define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree) 204 #else 205 #define LSAN_MAYBE_INTERCEPT_CFREE 206 #endif // SANITIZER_INTERCEPT_CFREE 207 208 #if SANITIZER_INTERCEPT_MCHECK_MPROBE 209 INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) { 210 return 0; 211 } 212 213 INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) { 214 return 0; 215 } 216 217 INTERCEPTOR(int, mprobe, void *ptr) { 218 return 0; 219 } 220 #endif // SANITIZER_INTERCEPT_MCHECK_MPROBE 221 222 223 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. 224 #define OPERATOR_NEW_BODY(nothrow)\ 225 ENSURE_LSAN_INITED;\ 226 GET_STACK_TRACE_MALLOC;\ 227 void *res = lsan_malloc(size, stack);\ 228 if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 229 return res; 230 #define OPERATOR_NEW_BODY_ALIGN(nothrow)\ 231 ENSURE_LSAN_INITED;\ 232 GET_STACK_TRACE_MALLOC;\ 233 void *res = lsan_memalign((uptr)align, size, stack);\ 234 if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 235 return res; 236 237 #define OPERATOR_DELETE_BODY\ 238 ENSURE_LSAN_INITED;\ 239 lsan_free(ptr); 240 241 // On OS X it's not enough to just provide our own 'operator new' and 242 // 'operator delete' implementations, because they're going to be in the runtime 243 // dylib, and the main executable will depend on both the runtime dylib and 244 // libstdc++, each of has its implementation of new and delete. 245 // To make sure that C++ allocation/deallocation operators are overridden on 246 // OS X we need to intercept them using their mangled names. 247 #if !SANITIZER_APPLE 248 249 INTERCEPTOR_ATTRIBUTE 250 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 251 INTERCEPTOR_ATTRIBUTE 252 void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 253 INTERCEPTOR_ATTRIBUTE 254 void *operator new(size_t size, std::nothrow_t const&) 255 { OPERATOR_NEW_BODY(true /*nothrow*/); } 256 INTERCEPTOR_ATTRIBUTE 257 void *operator new[](size_t size, std::nothrow_t const&) 258 { OPERATOR_NEW_BODY(true /*nothrow*/); } 259 INTERCEPTOR_ATTRIBUTE 260 void *operator new(size_t size, std::align_val_t align) 261 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 262 INTERCEPTOR_ATTRIBUTE 263 void *operator new[](size_t size, std::align_val_t align) 264 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 265 INTERCEPTOR_ATTRIBUTE 266 void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 267 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 268 INTERCEPTOR_ATTRIBUTE 269 void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 270 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 271 272 INTERCEPTOR_ATTRIBUTE 273 void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 274 INTERCEPTOR_ATTRIBUTE 275 void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 276 INTERCEPTOR_ATTRIBUTE 277 void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 278 INTERCEPTOR_ATTRIBUTE 279 void operator delete[](void *ptr, std::nothrow_t const &) 280 { OPERATOR_DELETE_BODY; } 281 INTERCEPTOR_ATTRIBUTE 282 void operator delete(void *ptr, size_t size) NOEXCEPT 283 { OPERATOR_DELETE_BODY; } 284 INTERCEPTOR_ATTRIBUTE 285 void operator delete[](void *ptr, size_t size) NOEXCEPT 286 { OPERATOR_DELETE_BODY; } 287 INTERCEPTOR_ATTRIBUTE 288 void operator delete(void *ptr, std::align_val_t) NOEXCEPT 289 { OPERATOR_DELETE_BODY; } 290 INTERCEPTOR_ATTRIBUTE 291 void operator delete[](void *ptr, std::align_val_t) NOEXCEPT 292 { OPERATOR_DELETE_BODY; } 293 INTERCEPTOR_ATTRIBUTE 294 void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&) 295 { OPERATOR_DELETE_BODY; } 296 INTERCEPTOR_ATTRIBUTE 297 void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&) 298 { OPERATOR_DELETE_BODY; } 299 INTERCEPTOR_ATTRIBUTE 300 void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT 301 { OPERATOR_DELETE_BODY; } 302 INTERCEPTOR_ATTRIBUTE 303 void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT 304 { OPERATOR_DELETE_BODY; } 305 306 #else // SANITIZER_APPLE 307 308 INTERCEPTOR(void *, _Znwm, size_t size) 309 { OPERATOR_NEW_BODY(false /*nothrow*/); } 310 INTERCEPTOR(void *, _Znam, size_t size) 311 { OPERATOR_NEW_BODY(false /*nothrow*/); } 312 INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) 313 { OPERATOR_NEW_BODY(true /*nothrow*/); } 314 INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) 315 { OPERATOR_NEW_BODY(true /*nothrow*/); } 316 317 INTERCEPTOR(void, _ZdlPv, void *ptr) 318 { OPERATOR_DELETE_BODY; } 319 INTERCEPTOR(void, _ZdaPv, void *ptr) 320 { OPERATOR_DELETE_BODY; } 321 INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 322 { OPERATOR_DELETE_BODY; } 323 INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 324 { OPERATOR_DELETE_BODY; } 325 326 #endif // !SANITIZER_APPLE 327 328 329 ///// Thread initialization and finalization. ///// 330 331 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA 332 static unsigned g_thread_finalize_key; 333 334 static void thread_finalize(void *v) { 335 uptr iter = (uptr)v; 336 if (iter > 1) { 337 if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) { 338 Report("LeakSanitizer: failed to set thread key.\n"); 339 Die(); 340 } 341 return; 342 } 343 ThreadFinish(); 344 } 345 #endif 346 347 #if SANITIZER_NETBSD 348 INTERCEPTOR(void, _lwp_exit) { 349 ENSURE_LSAN_INITED; 350 ThreadFinish(); 351 REAL(_lwp_exit)(); 352 } 353 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit) 354 #else 355 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT 356 #endif 357 358 #if SANITIZER_INTERCEPT_THR_EXIT 359 INTERCEPTOR(void, thr_exit, tid_t *state) { 360 ENSURE_LSAN_INITED; 361 ThreadFinish(); 362 REAL(thr_exit)(state); 363 } 364 #define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit) 365 #else 366 #define LSAN_MAYBE_INTERCEPT_THR_EXIT 367 #endif 368 369 #if SANITIZER_INTERCEPT___CXA_ATEXIT 370 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 371 void *dso_handle) { 372 __lsan::ScopedInterceptorDisabler disabler; 373 return REAL(__cxa_atexit)(func, arg, dso_handle); 374 } 375 #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit) 376 #else 377 #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT 378 #endif 379 380 #if SANITIZER_INTERCEPT_ATEXIT 381 INTERCEPTOR(int, atexit, void (*f)()) { 382 __lsan::ScopedInterceptorDisabler disabler; 383 return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0); 384 } 385 #define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit) 386 #else 387 #define LSAN_MAYBE_INTERCEPT_ATEXIT 388 #endif 389 390 #if SANITIZER_INTERCEPT_PTHREAD_ATFORK 391 extern "C" { 392 extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 393 void (*child)()); 394 } 395 396 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 397 void (*child)()) { 398 __lsan::ScopedInterceptorDisabler disabler; 399 // REAL(pthread_atfork) cannot be called due to symbol indirections at least 400 // on NetBSD 401 return _pthread_atfork(prepare, parent, child); 402 } 403 #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork) 404 #else 405 #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK 406 #endif 407 408 #if SANITIZER_INTERCEPT_STRERROR 409 INTERCEPTOR(char *, strerror, int errnum) { 410 __lsan::ScopedInterceptorDisabler disabler; 411 return REAL(strerror)(errnum); 412 } 413 #define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror) 414 #else 415 #define LSAN_MAYBE_INTERCEPT_STRERROR 416 #endif 417 418 #if SANITIZER_POSIX 419 420 template <bool Detached> 421 static void *ThreadStartFunc(void *arg) { 422 u32 parent_tid = (uptr)arg; 423 uptr tid = ThreadCreate(parent_tid, Detached); 424 // Wait until the last iteration to maximize the chance that we are the last 425 // destructor to run. 426 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 427 if (pthread_setspecific(g_thread_finalize_key, 428 (void*)GetPthreadDestructorIterations())) { 429 Report("LeakSanitizer: failed to set thread key.\n"); 430 Die(); 431 } 432 # endif 433 ThreadStart(tid, GetTid()); 434 auto self = GetThreadSelf(); 435 auto args = GetThreadArgRetval().GetArgs(self); 436 void *retval = (*args.routine)(args.arg_retval); 437 GetThreadArgRetval().Finish(self, retval); 438 return retval; 439 } 440 441 INTERCEPTOR(int, pthread_create, void *th, void *attr, 442 void *(*callback)(void *), void *param) { 443 ENSURE_LSAN_INITED; 444 EnsureMainThreadIDIsCorrect(); 445 446 bool detached = [attr]() { 447 int d = 0; 448 return attr && !pthread_attr_getdetachstate(attr, &d) && IsStateDetached(d); 449 }(); 450 451 __sanitizer_pthread_attr_t myattr; 452 if (!attr) { 453 pthread_attr_init(&myattr); 454 attr = &myattr; 455 } 456 AdjustStackSize(attr); 457 uptr this_tid = GetCurrentThreadId(); 458 int result; 459 { 460 // Ignore all allocations made by pthread_create: thread stack/TLS may be 461 // stored by pthread for future reuse even after thread destruction, and 462 // the linked list it's stored in doesn't even hold valid pointers to the 463 // objects, the latter are calculated by obscure pointer arithmetic. 464 ScopedInterceptorDisabler disabler; 465 GetThreadArgRetval().Create(detached, {callback, param}, [&]() -> uptr { 466 result = REAL(pthread_create)( 467 th, attr, detached ? ThreadStartFunc<true> : ThreadStartFunc<false>, 468 (void *)this_tid); 469 return result ? 0 : *(uptr *)(th); 470 }); 471 } 472 if (attr == &myattr) 473 pthread_attr_destroy(&myattr); 474 return result; 475 } 476 477 INTERCEPTOR(int, pthread_join, void *thread, void **retval) { 478 int result; 479 GetThreadArgRetval().Join((uptr)thread, [&]() { 480 result = REAL(pthread_join)(thread, retval); 481 return !result; 482 }); 483 return result; 484 } 485 486 INTERCEPTOR(int, pthread_detach, void *thread) { 487 int result; 488 GetThreadArgRetval().Detach((uptr)thread, [&]() { 489 result = REAL(pthread_detach)(thread); 490 return !result; 491 }); 492 return result; 493 } 494 495 INTERCEPTOR(void, pthread_exit, void *retval) { 496 GetThreadArgRetval().Finish(GetThreadSelf(), retval); 497 REAL(pthread_exit)(retval); 498 } 499 500 # if SANITIZER_INTERCEPT_TRYJOIN 501 INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) { 502 int result; 503 GetThreadArgRetval().Join((uptr)thread, [&]() { 504 result = REAL(pthread_tryjoin_np)(thread, ret); 505 return !result; 506 }); 507 return result; 508 } 509 # define LSAN_MAYBE_INTERCEPT_TRYJOIN INTERCEPT_FUNCTION(pthread_tryjoin_np) 510 # else 511 # define LSAN_MAYBE_INTERCEPT_TRYJOIN 512 # endif // SANITIZER_INTERCEPT_TRYJOIN 513 514 # if SANITIZER_INTERCEPT_TIMEDJOIN 515 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret, 516 const struct timespec *abstime) { 517 int result; 518 GetThreadArgRetval().Join((uptr)thread, [&]() { 519 result = REAL(pthread_timedjoin_np)(thread, ret, abstime); 520 return !result; 521 }); 522 return result; 523 } 524 # define LSAN_MAYBE_INTERCEPT_TIMEDJOIN \ 525 INTERCEPT_FUNCTION(pthread_timedjoin_np) 526 # else 527 # define LSAN_MAYBE_INTERCEPT_TIMEDJOIN 528 # endif // SANITIZER_INTERCEPT_TIMEDJOIN 529 530 DEFINE_INTERNAL_PTHREAD_FUNCTIONS 531 532 INTERCEPTOR(void, _exit, int status) { 533 if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode; 534 REAL(_exit)(status); 535 } 536 537 #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) 538 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_LSAN_INITED 539 #include "sanitizer_common/sanitizer_signal_interceptors.inc" 540 541 #endif // SANITIZER_POSIX 542 543 namespace __lsan { 544 545 void InitializeInterceptors() { 546 // Fuchsia doesn't use interceptors that require any setup. 547 #if !SANITIZER_FUCHSIA 548 __interception::DoesNotSupportStaticLinking(); 549 InitializeSignalInterceptors(); 550 551 INTERCEPT_FUNCTION(malloc); 552 INTERCEPT_FUNCTION(free); 553 LSAN_MAYBE_INTERCEPT_CFREE; 554 INTERCEPT_FUNCTION(calloc); 555 INTERCEPT_FUNCTION(realloc); 556 LSAN_MAYBE_INTERCEPT_MEMALIGN; 557 LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN; 558 LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; 559 INTERCEPT_FUNCTION(posix_memalign); 560 INTERCEPT_FUNCTION(valloc); 561 LSAN_MAYBE_INTERCEPT_PVALLOC; 562 LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE; 563 LSAN_MAYBE_INTERCEPT_MALLINFO; 564 LSAN_MAYBE_INTERCEPT_MALLOPT; 565 INTERCEPT_FUNCTION(pthread_create); 566 INTERCEPT_FUNCTION(pthread_join); 567 INTERCEPT_FUNCTION(pthread_detach); 568 INTERCEPT_FUNCTION(pthread_exit); 569 LSAN_MAYBE_INTERCEPT_TIMEDJOIN; 570 LSAN_MAYBE_INTERCEPT_TRYJOIN; 571 INTERCEPT_FUNCTION(_exit); 572 573 LSAN_MAYBE_INTERCEPT__LWP_EXIT; 574 LSAN_MAYBE_INTERCEPT_THR_EXIT; 575 576 LSAN_MAYBE_INTERCEPT___CXA_ATEXIT; 577 LSAN_MAYBE_INTERCEPT_ATEXIT; 578 LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK; 579 580 LSAN_MAYBE_INTERCEPT_STRERROR; 581 582 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 583 if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { 584 Report("LeakSanitizer: failed to create thread key.\n"); 585 Die(); 586 } 587 #endif 588 589 #endif // !SANITIZER_FUCHSIA 590 } 591 592 } // namespace __lsan 593