11844Swollman//=-- lsan_interceptors.cpp -----------------------------------------------===//
250476Speter//
31844Swollman// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41638Srgrimes// See https://llvm.org/LICENSE.txt for license information.
594940Sru// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61638Srgrimes//
742915Sjdp//===----------------------------------------------------------------------===//
842915Sjdp//
942915Sjdp// This file is a part of LeakSanitizer.
1042915Sjdp// Interceptors for standalone LSan.
1142915Sjdp//
1242915Sjdp//===----------------------------------------------------------------------===//
1342915Sjdp
1442915Sjdp#include "interception/interception.h"
1542915Sjdp#include "sanitizer_common/sanitizer_allocator.h"
1699362Sru#include "sanitizer_common/sanitizer_allocator_dlsym.h"
1742915Sjdp#include "sanitizer_common/sanitizer_allocator_report.h"
1842915Sjdp#include "sanitizer_common/sanitizer_atomic.h"
1929141Speter#include "sanitizer_common/sanitizer_common.h"
2042915Sjdp#include "sanitizer_common/sanitizer_flags.h"
2142915Sjdp#include "sanitizer_common/sanitizer_internal_defs.h"
2242915Sjdp#include "sanitizer_common/sanitizer_linux.h"
2342915Sjdp#include "sanitizer_common/sanitizer_platform_interceptors.h"
2442915Sjdp#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
2542915Sjdp#include "sanitizer_common/sanitizer_platform_limits_posix.h"
2642915Sjdp#if SANITIZER_POSIX
2729141Speter#include "sanitizer_common/sanitizer_posix.h"
282827Sjkh#endif
292827Sjkh#include "sanitizer_common/sanitizer_tls_get_addr.h"
302827Sjkh#include "lsan.h"
312827Sjkh#include "lsan_allocator.h"
322827Sjkh#include "lsan_common.h"
331638Srgrimes#include "lsan_thread.h"
342827Sjkh
351638Srgrimes#include <stddef.h>
3643055Sjdp
3718529Sbdeusing namespace __lsan;
3831809Sbde
3918529Sbdeextern "C" {
401638Srgrimesint pthread_attr_init(void *attr);
4142450Sjdpint pthread_attr_destroy(void *attr);
421638Srgrimesint pthread_attr_getdetachstate(void *attr, int *v);
4395064Sobrienint pthread_key_create(unsigned *key, void (*destructor)(void* v));
441638Srgrimesint pthread_setspecific(unsigned key, const void *v);
4596512Sru}
4696512Sru
4796512Srustruct DlsymAlloc : DlSymAllocator<DlsymAlloc> {
4896512Sru  static bool UseImpl() { return lsan_init_is_running; }
4996512Sru  static void OnAllocate(const void *ptr, uptr size) {
5096512Sru#if CAN_SANITIZE_LEAKS
5196512Sru    // Suppress leaks from dlerror(). Previously dlsym hack on global array was
5296512Sru    // used by leak sanitizer as a root region.
5392491Smarkm    __lsan_register_root_region(ptr, size);
5492491Smarkm#endif
5592553Sru  }
5692491Smarkm  static void OnFree(const void *ptr, uptr size) {
5792491Smarkm#if CAN_SANITIZE_LEAKS
5892553Sru    __lsan_unregister_root_region(ptr, size);
5992553Sru#endif
6092491Smarkm  }
611638Srgrimes};
621844Swollman
6338186Speter///// Malloc/free interceptors. /////
6438186Speter
651638Srgrimesnamespace std {
661638Srgrimes  struct nothrow_t;
6724761Sjdp  enum class align_val_t: size_t;
6838186Speter}
6938186Speter
701638Srgrimes#if !SANITIZER_MAC
7142450SjdpINTERCEPTOR(void*, malloc, uptr size) {
721844Swollman  if (DlsymAlloc::Use())
7396258Sobrien    return DlsymAlloc::Allocate(size);
7438186Speter  ENSURE_LSAN_INITED;
751844Swollman  GET_STACK_TRACE_MALLOC;
7636673Sdt  return lsan_malloc(size, stack);
771844Swollman}
7838186Speter
7938186SpeterINTERCEPTOR(void, free, void *p) {
801844Swollman  if (DlsymAlloc::PointerIsMine(p))
8136673Sdt    return DlsymAlloc::Free(p);
8224761Sjdp  ENSURE_LSAN_INITED;
8338186Speter  lsan_free(p);
8438186Speter}
851844Swollman
8642450SjdpINTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
871844Swollman  if (DlsymAlloc::Use())
8896258Sobrien    return DlsymAlloc::Callocate(nmemb, size);
8938186Speter  ENSURE_LSAN_INITED;
901844Swollman  GET_STACK_TRACE_MALLOC;
911844Swollman  return lsan_calloc(nmemb, size, stack);
921844Swollman}
9338186Speter
9438186SpeterINTERCEPTOR(void *, realloc, void *ptr, uptr size) {
951844Swollman  if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
961844Swollman    return DlsymAlloc::Realloc(ptr, size);
9724761Sjdp  ENSURE_LSAN_INITED;
9838186Speter  GET_STACK_TRACE_MALLOC;
9938186Speter  return lsan_realloc(ptr, size, stack);
1001844Swollman}
10142450Sjdp
1021844SwollmanINTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) {
10396258Sobrien  ENSURE_LSAN_INITED;
10438186Speter  GET_STACK_TRACE_MALLOC;
1051844Swollman  return lsan_reallocarray(q, nmemb, size, stack);
10636054Sbde}
10736054Sbde
10838186SpeterINTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
10938186Speter  ENSURE_LSAN_INITED;
11036054Sbde  GET_STACK_TRACE_MALLOC;
11136054Sbde  return lsan_posix_memalign(memptr, alignment, size, stack);
11236054Sbde}
11338186Speter
11438186SpeterINTERCEPTOR(void*, valloc, uptr size) {
11536054Sbde  ENSURE_LSAN_INITED;
11642450Sjdp  GET_STACK_TRACE_MALLOC;
11736054Sbde  return lsan_valloc(size, stack);
11896258Sobrien}
11938186Speter#endif  // !SANITIZER_MAC
12036054Sbde
12195251Sru#if SANITIZER_INTERCEPT_MEMALIGN
12297101SruINTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
12317510Speter  ENSURE_LSAN_INITED;
12496258Sobrien  GET_STACK_TRACE_MALLOC;
12538186Speter  return lsan_memalign(alignment, size, stack);
1261638Srgrimes}
12795251Sru#define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
12897101Sru#else
12917510Speter#define LSAN_MAYBE_INTERCEPT_MEMALIGN
13096258Sobrien#endif  // SANITIZER_INTERCEPT_MEMALIGN
13138186Speter
1321638Srgrimes#if SANITIZER_INTERCEPT___LIBC_MEMALIGN
13395251SruINTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {
13497101Sru  ENSURE_LSAN_INITED;
13595216Smarkm  GET_STACK_TRACE_MALLOC;
13638186Speter  void *res = lsan_memalign(alignment, size, stack);
13738186Speter  DTLS_on_libc_memalign(res, size);
1381638Srgrimes  return res;
1391844Swollman}
14097101Sru#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
14196258Sobrien#else
14238186Speter#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
1431844Swollman#endif  // SANITIZER_INTERCEPT___LIBC_MEMALIGN
1441844Swollman
14597101Sru#if SANITIZER_INTERCEPT_ALIGNED_ALLOC
14696258SobrienINTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
14738186Speter  ENSURE_LSAN_INITED;
1481844Swollman  GET_STACK_TRACE_MALLOC;
14942450Sjdp  return lsan_aligned_alloc(alignment, size, stack);
15097101Sru}
15195216Smarkm#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)
15238186Speter#else
15338186Speter#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC
1541844Swollman#endif
15596512Sru
1561638Srgrimes#if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE
15799362SruINTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
15899362Sru  ENSURE_LSAN_INITED;
15999362Sru  return GetMallocUsableSize(ptr);
16099362Sru}
16196512Sru#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
16296512Sru        INTERCEPT_FUNCTION(malloc_usable_size)
1631638Srgrimes#else
16496512Sru#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
16596512Sru#endif
16696512Sru
16796512Sru#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
16896512Srustruct fake_mallinfo {
16999362Sru  int x[10];
1701638Srgrimes};
17196512Sru
17295114SobrienINTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
17399362Sru  struct fake_mallinfo res;
17496512Sru  internal_memset(&res, 0, sizeof(res));
17596512Sru  return res;
17695306Sru}
17796512Sru#define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
17896512Sru
17996512SruINTERCEPTOR(int, mallopt, int cmd, int value) {
18096512Sru  return 0;
18196512Sru}
18274805Sru#define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
1831844Swollman#else
18499362Sru#define LSAN_MAYBE_INTERCEPT_MALLINFO
18599362Sru#define LSAN_MAYBE_INTERCEPT_MALLOPT
18696512Sru#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
18799362Sru
1881844Swollman#if SANITIZER_INTERCEPT_PVALLOC
18996512SruINTERCEPTOR(void*, pvalloc, uptr size) {
19096512Sru  ENSURE_LSAN_INITED;
1911638Srgrimes  GET_STACK_TRACE_MALLOC;
19242915Sjdp  return lsan_pvalloc(size, stack);
19342915Sjdp}
19496512Sru#define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
19542915Sjdp#else
19696512Sru#define LSAN_MAYBE_INTERCEPT_PVALLOC
19742915Sjdp#endif // SANITIZER_INTERCEPT_PVALLOC
19838655Sjb
19991011Sru#if SANITIZER_INTERCEPT_CFREE
20096512SruINTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free));
20191011Sru#define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
20228945Speter#else
20396343Sobrien#define LSAN_MAYBE_INTERCEPT_CFREE
20496512Sru#endif // SANITIZER_INTERCEPT_CFREE
20591011Sru
20628945Speter#if SANITIZER_INTERCEPT_MCHECK_MPROBE
20742915SjdpINTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
2081844Swollman  return 0;
20999362Sru}
21096512Sru
21196512SruINTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
21296512Sru  return 0;
2132353Sbde}
21496512Sru
21596512SruINTERCEPTOR(int, mprobe, void *ptr) {
21696512Sru  return 0;
2173859Sbde}
2181844Swollman#endif // SANITIZER_INTERCEPT_MCHECK_MPROBE
21999362Sru
22096512Sru
22196512Sru// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
22296512Sru#define OPERATOR_NEW_BODY(nothrow)\
22396512Sru  ENSURE_LSAN_INITED;\
22492491Smarkm  GET_STACK_TRACE_MALLOC;\
22596512Sru  void *res = lsan_malloc(size, stack);\
22696512Sru  if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
22792491Smarkm  return res;
22892491Smarkm#define OPERATOR_NEW_BODY_ALIGN(nothrow)\
2291638Srgrimes  ENSURE_LSAN_INITED;\
23096512Sru  GET_STACK_TRACE_MALLOC;\
23196512Sru  void *res = lsan_memalign((uptr)align, size, stack);\
23296512Sru  if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
23396512Sru  return res;
23496512Sru
23596512Sru#define OPERATOR_DELETE_BODY\
2361638Srgrimes  ENSURE_LSAN_INITED;\
2371638Srgrimes  lsan_free(ptr);
23896529Sru
23996529Sru// On OS X it's not enough to just provide our own 'operator new' and
24098870Sjmallett// 'operator delete' implementations, because they're going to be in the runtime
24196529Sru// dylib, and the main executable will depend on both the runtime dylib and
24298870Sjmallett// libstdc++, each of has its implementation of new and delete.
24396529Sru// To make sure that C++ allocation/deallocation operators are overridden on
24496529Sru// OS X we need to intercept them using their mangled names.
24599362Sru#if !SANITIZER_MAC
24696529Sru
24799362SruINTERCEPTOR_ATTRIBUTE
24896529Sruvoid *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
24996529SruINTERCEPTOR_ATTRIBUTE
25099362Sruvoid *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
25199362SruINTERCEPTOR_ATTRIBUTE
25296529Sruvoid *operator new(size_t size, std::nothrow_t const&)
25399362Sru{ OPERATOR_NEW_BODY(true /*nothrow*/); }
25496529SruINTERCEPTOR_ATTRIBUTE
25599362Sruvoid *operator new[](size_t size, std::nothrow_t const&)
25699362Sru{ OPERATOR_NEW_BODY(true /*nothrow*/); }
25796529SruINTERCEPTOR_ATTRIBUTE
25899362Sruvoid *operator new(size_t size, std::align_val_t align)
25999362Sru{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
26099362SruINTERCEPTOR_ATTRIBUTE
26199362Sruvoid *operator new[](size_t size, std::align_val_t align)
26299362Sru{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
26396529SruINTERCEPTOR_ATTRIBUTE
26496529Sruvoid *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
26596529Sru{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
26699362SruINTERCEPTOR_ATTRIBUTE
26796529Sruvoid *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
26899362Sru{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
26996529Sru
27096529SruINTERCEPTOR_ATTRIBUTE
27196529Sruvoid operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
27296529SruINTERCEPTOR_ATTRIBUTE
27396529Sruvoid operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
27434179SbdeINTERCEPTOR_ATTRIBUTE
27524750Sbdevoid operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
27642450SjdpINTERCEPTOR_ATTRIBUTE
27724750Sbdevoid operator delete[](void *ptr, std::nothrow_t const &)
27824750Sbde{ OPERATOR_DELETE_BODY; }
27942915SjdpINTERCEPTOR_ATTRIBUTE
28038655Sjbvoid operator delete(void *ptr, size_t size) NOEXCEPT
28142915Sjdp{ OPERATOR_DELETE_BODY; }
28291011SruINTERCEPTOR_ATTRIBUTE
28325468Sjdpvoid operator delete[](void *ptr, size_t size) NOEXCEPT
28428945Speter{ OPERATOR_DELETE_BODY; }
28531809SbdeINTERCEPTOR_ATTRIBUTE
28642915Sjdpvoid operator delete(void *ptr, std::align_val_t) NOEXCEPT
28727910Sasami{ OPERATOR_DELETE_BODY; }
28828945SpeterINTERCEPTOR_ATTRIBUTE
28928945Spetervoid operator delete[](void *ptr, std::align_val_t) NOEXCEPT
2901638Srgrimes{ OPERATOR_DELETE_BODY; }
2911638SrgrimesINTERCEPTOR_ATTRIBUTE
2921638Srgrimesvoid operator delete(void *ptr, std::align_val_t, std::nothrow_t const&)
29348204Sjmg{ OPERATOR_DELETE_BODY; }
2942298SwollmanINTERCEPTOR_ATTRIBUTE
2952298Swollmanvoid operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&)
2962298Swollman{ OPERATOR_DELETE_BODY; }
29749328ShoekINTERCEPTOR_ATTRIBUTE
29849328Shoekvoid operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT
29949328Shoek{ OPERATOR_DELETE_BODY; }
30049328ShoekINTERCEPTOR_ATTRIBUTE
30156971Sruvoid operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT
30249328Shoek{ OPERATOR_DELETE_BODY; }
30349328Shoek
30449328Shoek#else  // SANITIZER_MAC
30549328Shoek
30699362SruINTERCEPTOR(void *, _Znwm, size_t size)
30795306Sru{ OPERATOR_NEW_BODY(false /*nothrow*/); }
30899343SruINTERCEPTOR(void *, _Znam, size_t size)
30995306Sru{ OPERATOR_NEW_BODY(false /*nothrow*/); }
31099362SruINTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&)
31192980Sdes{ OPERATOR_NEW_BODY(true /*nothrow*/); }
31249328ShoekINTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&)
31396512Sru{ OPERATOR_NEW_BODY(true /*nothrow*/); }
31499362Sru
31592980SdesINTERCEPTOR(void, _ZdlPv, void *ptr)
31649328Shoek{ OPERATOR_DELETE_BODY; }
3171638SrgrimesINTERCEPTOR(void, _ZdaPv, void *ptr)
31842915Sjdp{ OPERATOR_DELETE_BODY; }
31948204SjmgINTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
32049328Shoek{ OPERATOR_DELETE_BODY; }
32142915SjdpINTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
32242915Sjdp{ OPERATOR_DELETE_BODY; }
32396512Sru
3241844Swollman#endif  // !SANITIZER_MAC
32528945Speter
32699362Sru
3271844Swollman///// Thread initialization and finalization. /////
32849328Shoek
3291844Swollman#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA
33099362Srustatic unsigned g_thread_finalize_key;
33196462Sru
33296462Srustatic void thread_finalize(void *v) {
33396462Sru  uptr iter = (uptr)v;
33499362Sru  if (iter > 1) {
33596462Sru    if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
33697769Sru      Report("LeakSanitizer: failed to set thread key.\n");
33796668Sru      Die();
33899256Sru    }
33996462Sru    return;
34096162Sru  }
34196164Sru  ThreadFinish();
34299343Sru}
34396162Sru#endif
34496162Sru
3451638Srgrimes#if SANITIZER_NETBSD
3461638SrgrimesINTERCEPTOR(void, _lwp_exit) {
3471638Srgrimes  ENSURE_LSAN_INITED;
34895306Sru  ThreadFinish();
34992553Sru  REAL(_lwp_exit)();
3501638Srgrimes}
3511638Srgrimes#define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit)
3521844Swollman#else
3531638Srgrimes#define LSAN_MAYBE_INTERCEPT__LWP_EXIT
35474842Sru#endif
3551844Swollman
3561844Swollman#if SANITIZER_INTERCEPT_THR_EXIT
35734092SbdeINTERCEPTOR(void, thr_exit, tid_t *state) {
35899362Sru  ENSURE_LSAN_INITED;
35996512Sru  ThreadFinish();
36099362Sru  REAL(thr_exit)(state);
36134092Sbde}
36299362Sru#define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit)
36399362Sru#else
36499362Sru#define LSAN_MAYBE_INTERCEPT_THR_EXIT
36596512Sru#endif
36699362Sru
36734092Sbde#if SANITIZER_INTERCEPT___CXA_ATEXIT
36816663SjkhINTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
36976861Skris            void *dso_handle) {
37076861Skris  __lsan::ScopedInterceptorDisabler disabler;
371  return REAL(__cxa_atexit)(func, arg, dso_handle);
372}
373#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
374#else
375#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
376#endif
377
378#if SANITIZER_INTERCEPT_ATEXIT
379INTERCEPTOR(int, atexit, void (*f)()) {
380  __lsan::ScopedInterceptorDisabler disabler;
381  return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0);
382}
383#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
384#else
385#define LSAN_MAYBE_INTERCEPT_ATEXIT
386#endif
387
388#if SANITIZER_INTERCEPT_PTHREAD_ATFORK
389extern "C" {
390extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
391                           void (*child)());
392};
393
394INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
395            void (*child)()) {
396  __lsan::ScopedInterceptorDisabler disabler;
397  // REAL(pthread_atfork) cannot be called due to symbol indirections at least
398  // on NetBSD
399  return _pthread_atfork(prepare, parent, child);
400}
401#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
402#else
403#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
404#endif
405
406#if SANITIZER_INTERCEPT_STRERROR
407INTERCEPTOR(char *, strerror, int errnum) {
408  __lsan::ScopedInterceptorDisabler disabler;
409  return REAL(strerror)(errnum);
410}
411#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
412#else
413#define LSAN_MAYBE_INTERCEPT_STRERROR
414#endif
415
416#if SANITIZER_POSIX
417
418struct ThreadParam {
419  void *(*callback)(void *arg);
420  void *param;
421  atomic_uintptr_t tid;
422};
423
424extern "C" void *__lsan_thread_start_func(void *arg) {
425  ThreadParam *p = (ThreadParam*)arg;
426  void* (*callback)(void *arg) = p->callback;
427  void *param = p->param;
428  // Wait until the last iteration to maximize the chance that we are the last
429  // destructor to run.
430#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
431  if (pthread_setspecific(g_thread_finalize_key,
432                          (void*)GetPthreadDestructorIterations())) {
433    Report("LeakSanitizer: failed to set thread key.\n");
434    Die();
435  }
436#endif
437  int tid = 0;
438  while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
439    internal_sched_yield();
440  ThreadStart(tid, GetTid());
441  atomic_store(&p->tid, 0, memory_order_release);
442  return callback(param);
443}
444
445INTERCEPTOR(int, pthread_create, void *th, void *attr,
446            void *(*callback)(void *), void *param) {
447  ENSURE_LSAN_INITED;
448  EnsureMainThreadIDIsCorrect();
449  __sanitizer_pthread_attr_t myattr;
450  if (!attr) {
451    pthread_attr_init(&myattr);
452    attr = &myattr;
453  }
454  AdjustStackSize(attr);
455  int detached = 0;
456  pthread_attr_getdetachstate(attr, &detached);
457  ThreadParam p;
458  p.callback = callback;
459  p.param = param;
460  atomic_store(&p.tid, 0, memory_order_relaxed);
461  int res;
462  {
463    // Ignore all allocations made by pthread_create: thread stack/TLS may be
464    // stored by pthread for future reuse even after thread destruction, and
465    // the linked list it's stored in doesn't even hold valid pointers to the
466    // objects, the latter are calculated by obscure pointer arithmetic.
467    ScopedInterceptorDisabler disabler;
468    res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p);
469  }
470  if (res == 0) {
471    int tid = ThreadCreate(GetCurrentThread(), *(uptr *)th,
472                           IsStateDetached(detached));
473    CHECK_NE(tid, kMainTid);
474    atomic_store(&p.tid, tid, memory_order_release);
475    while (atomic_load(&p.tid, memory_order_acquire) != 0)
476      internal_sched_yield();
477  }
478  if (attr == &myattr)
479    pthread_attr_destroy(&myattr);
480  return res;
481}
482
483INTERCEPTOR(int, pthread_join, void *th, void **ret) {
484  ENSURE_LSAN_INITED;
485  int tid = ThreadTid((uptr)th);
486  int res = REAL(pthread_join)(th, ret);
487  if (res == 0)
488    ThreadJoin(tid);
489  return res;
490}
491
492INTERCEPTOR(int, pthread_detach, void *th) {
493  ENSURE_LSAN_INITED;
494  int tid = ThreadTid((uptr)th);
495  int res = REAL(pthread_detach)(th);
496  if (res == 0)
497    ThreadDetach(tid);
498  return res;
499}
500
501INTERCEPTOR(void, _exit, int status) {
502  if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode;
503  REAL(_exit)(status);
504}
505
506#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
507#include "sanitizer_common/sanitizer_signal_interceptors.inc"
508
509#endif  // SANITIZER_POSIX
510
511namespace __lsan {
512
513void InitializeInterceptors() {
514  // Fuchsia doesn't use interceptors that require any setup.
515#if !SANITIZER_FUCHSIA
516  InitializeSignalInterceptors();
517
518  INTERCEPT_FUNCTION(malloc);
519  INTERCEPT_FUNCTION(free);
520  LSAN_MAYBE_INTERCEPT_CFREE;
521  INTERCEPT_FUNCTION(calloc);
522  INTERCEPT_FUNCTION(realloc);
523  LSAN_MAYBE_INTERCEPT_MEMALIGN;
524  LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
525  LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;
526  INTERCEPT_FUNCTION(posix_memalign);
527  INTERCEPT_FUNCTION(valloc);
528  LSAN_MAYBE_INTERCEPT_PVALLOC;
529  LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
530  LSAN_MAYBE_INTERCEPT_MALLINFO;
531  LSAN_MAYBE_INTERCEPT_MALLOPT;
532  INTERCEPT_FUNCTION(pthread_create);
533  INTERCEPT_FUNCTION(pthread_detach);
534  INTERCEPT_FUNCTION(pthread_join);
535  INTERCEPT_FUNCTION(_exit);
536
537  LSAN_MAYBE_INTERCEPT__LWP_EXIT;
538  LSAN_MAYBE_INTERCEPT_THR_EXIT;
539
540  LSAN_MAYBE_INTERCEPT___CXA_ATEXIT;
541  LSAN_MAYBE_INTERCEPT_ATEXIT;
542  LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
543
544  LSAN_MAYBE_INTERCEPT_STRERROR;
545
546#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
547  if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
548    Report("LeakSanitizer: failed to create thread key.\n");
549    Die();
550  }
551#endif
552
553#endif  // !SANITIZER_FUCHSIA
554}
555
556} // namespace __lsan
557