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

source code of compiler-rt/lib/lsan/lsan_interceptors.cpp