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