xref: /freebsd/contrib/llvm-project/compiler-rt/lib/lsan/lsan_interceptors.cpp (revision 6c05f3a74f30934ee60919cc97e16ec69b542b06)
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