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