xref: /llvm-project/compiler-rt/lib/lsan/lsan_interceptors.cpp (revision b07f1be92c1350d8d5b0952f49a2c3aeedcccb2f)
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 
36 using namespace __lsan;
37 
38 extern "C" {
39 int pthread_attr_init(void *attr);
40 int pthread_attr_destroy(void *attr);
41 int pthread_attr_getdetachstate(void *attr, int *v);
42 int pthread_key_create(unsigned *key, void (*destructor)(void* v));
43 int pthread_setspecific(unsigned key, const void *v);
44 }
45 
46 struct 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(ptr, size);
53 #endif
54   }
55   static void OnFree(const void *ptr, uptr size) {
56 #if CAN_SANITIZE_LEAKS
57     __lsan_unregister_root_region(ptr, size);
58 #endif
59   }
60 };
61 
62 ///// Malloc/free interceptors. /////
63 
64 namespace std {
65   struct nothrow_t;
66   enum class align_val_t: size_t;
67 }
68 
69 #if !SANITIZER_APPLE
70 INTERCEPTOR(void*, malloc, uptr size) {
71   if (DlsymAlloc::Use())
72     return DlsymAlloc::Allocate(size);
73   ENSURE_LSAN_INITED;
74   GET_STACK_TRACE_MALLOC;
75   return lsan_malloc(size, stack);
76 }
77 
78 INTERCEPTOR(void, free, void *p) {
79   if (UNLIKELY(!p))
80     return;
81   if (DlsymAlloc::PointerIsMine(p))
82     return DlsymAlloc::Free(p);
83   ENSURE_LSAN_INITED;
84   lsan_free(p);
85 }
86 
87 INTERCEPTOR(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 
95 INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
96   if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
97     return DlsymAlloc::Realloc(ptr, size);
98   ENSURE_LSAN_INITED;
99   GET_STACK_TRACE_MALLOC;
100   return lsan_realloc(ptr, size, stack);
101 }
102 
103 INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) {
104   ENSURE_LSAN_INITED;
105   GET_STACK_TRACE_MALLOC;
106   return lsan_reallocarray(q, nmemb, size, stack);
107 }
108 
109 INTERCEPTOR(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 
115 INTERCEPTOR(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
123 INTERCEPTOR(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
134 INTERCEPTOR(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
145 INTERCEPTOR(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
156 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
157   ENSURE_LSAN_INITED;
158   return GetMallocUsableSize(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
167 struct fake_mallinfo {
168   int x[10];
169 };
170 
171 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
172   struct fake_mallinfo res;
173   internal_memset(&res, 0, sizeof(res));
174   return res;
175 }
176 #define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
177 
178 INTERCEPTOR(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
188 INTERCEPTOR(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
199 INTERCEPTOR(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
206 INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
207   return 0;
208 }
209 
210 INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
211   return 0;
212 }
213 
214 INTERCEPTOR(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 
246 INTERCEPTOR_ATTRIBUTE
247 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
248 INTERCEPTOR_ATTRIBUTE
249 void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
250 INTERCEPTOR_ATTRIBUTE
251 void *operator new(size_t size, std::nothrow_t const&)
252 { OPERATOR_NEW_BODY(true /*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::align_val_t align)
258 { OPERATOR_NEW_BODY_ALIGN(false /*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, std::nothrow_t const&)
264 { OPERATOR_NEW_BODY_ALIGN(true /*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 
269 INTERCEPTOR_ATTRIBUTE
270 void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
271 INTERCEPTOR_ATTRIBUTE
272 void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
273 INTERCEPTOR_ATTRIBUTE
274 void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
275 INTERCEPTOR_ATTRIBUTE
276 void operator delete[](void *ptr, std::nothrow_t const &)
277 { OPERATOR_DELETE_BODY; }
278 INTERCEPTOR_ATTRIBUTE
279 void operator delete(void *ptr, size_t size) NOEXCEPT
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, std::align_val_t) 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, std::nothrow_t const&)
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, size_t size, std::align_val_t) NOEXCEPT
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 
303 #else  // SANITIZER_APPLE
304 
305 INTERCEPTOR(void *, _Znwm, size_t size)
306 { OPERATOR_NEW_BODY(false /*nothrow*/); }
307 INTERCEPTOR(void *, _Znam, size_t size)
308 { OPERATOR_NEW_BODY(false /*nothrow*/); }
309 INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&)
310 { OPERATOR_NEW_BODY(true /*nothrow*/); }
311 INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&)
312 { OPERATOR_NEW_BODY(true /*nothrow*/); }
313 
314 INTERCEPTOR(void, _ZdlPv, void *ptr)
315 { OPERATOR_DELETE_BODY; }
316 INTERCEPTOR(void, _ZdaPv, void *ptr)
317 { OPERATOR_DELETE_BODY; }
318 INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
319 { OPERATOR_DELETE_BODY; }
320 INTERCEPTOR(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
329 static unsigned g_thread_finalize_key;
330 
331 static void thread_finalize(void *v) {
332   uptr iter = (uptr)v;
333   if (iter > 1) {
334     if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
335       Report("LeakSanitizer: failed to set thread key.\n");
336       Die();
337     }
338     return;
339   }
340   ThreadFinish();
341 }
342 #endif
343 
344 #if SANITIZER_NETBSD
345 INTERCEPTOR(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
356 INTERCEPTOR(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
367 INTERCEPTOR(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
378 INTERCEPTOR(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
388 extern "C" {
389 extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
390                            void (*child)());
391 }
392 
393 INTERCEPTOR(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
406 INTERCEPTOR(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 
417 template <bool Detached>
418 static void *ThreadStartFunc(void *arg) {
419   u32 parent_tid = (uptr)arg;
420   uptr tid = ThreadCreate(parent_tid, 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(g_thread_finalize_key,
425                           (void*)GetPthreadDestructorIterations())) {
426     Report("LeakSanitizer: failed to set thread key.\n");
427     Die();
428   }
429 #  endif
430   ThreadStart(tid, GetTid());
431   auto self = GetThreadSelf();
432   auto args = GetThreadArgRetval().GetArgs(self);
433   void *retval = (*args.routine)(args.arg_retval);
434   GetThreadArgRetval().Finish(self, retval);
435   return retval;
436 }
437 
438 INTERCEPTOR(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, &d) && IsStateDetached(d);
446   }();
447 
448   __sanitizer_pthread_attr_t myattr;
449   if (!attr) {
450     pthread_attr_init(&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, {callback, param}, [&]() -> 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(&myattr);
471   return result;
472 }
473 
474 INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
475   int result;
476   GetThreadArgRetval().Join((uptr)thread, [&]() {
477     result = REAL(pthread_join)(thread, retval);
478     return !result;
479   });
480   return result;
481 }
482 
483 INTERCEPTOR(int, pthread_detach, void *thread) {
484   int result;
485   GetThreadArgRetval().Detach((uptr)thread, [&]() {
486     result = REAL(pthread_detach)(thread);
487     return !result;
488   });
489   return result;
490 }
491 
492 INTERCEPTOR(void, pthread_exit, void *retval) {
493   GetThreadArgRetval().Finish(GetThreadSelf(), retval);
494   REAL(pthread_exit)(retval);
495 }
496 
497 #  if SANITIZER_INTERCEPT_TRYJOIN
498 INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) {
499   int result;
500   GetThreadArgRetval().Join((uptr)thread, [&]() {
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
512 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret,
513             const struct timespec *abstime) {
514   int result;
515   GetThreadArgRetval().Join((uptr)thread, [&]() {
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 
527 DEFINE_INTERNAL_PTHREAD_FUNCTIONS
528 
529 INTERCEPTOR(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 
540 namespace __lsan {
541 
542 void 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(&g_thread_finalize_key, &thread_finalize)) {
581     Report("LeakSanitizer: failed to create thread key.\n");
582     Die();
583   }
584 #endif
585 
586 #endif  // !SANITIZER_FUCHSIA
587 }
588 
589 } // namespace __lsan
590