1 //=-- lsan_interceptors.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of LeakSanitizer.
10 // Interceptors for standalone LSan.
12 //===----------------------------------------------------------------------===//
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"
27 #include "sanitizer_common/sanitizer_posix.h"
30 #include "lsan_allocator.h"
31 #include "lsan_common.h"
32 #include "lsan_thread.h"
36 using namespace __lsan
;
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
);
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
);
55 static void OnFree(const void *ptr
, uptr size
) {
56 #if CAN_SANITIZE_LEAKS
57 __lsan_unregister_root_region(ptr
, size
);
62 ///// Malloc/free interceptors. /////
66 enum class align_val_t
: size_t;
70 INTERCEPTOR(void*, malloc
, uptr size
) {
71 if (DlsymAlloc::Use())
72 return DlsymAlloc::Allocate(size
);
74 GET_STACK_TRACE_MALLOC
;
75 return lsan_malloc(size
, stack
);
78 INTERCEPTOR(void, free
, void *p
) {
81 if (DlsymAlloc::PointerIsMine(p
))
82 return DlsymAlloc::Free(p
);
87 INTERCEPTOR(void*, calloc
, uptr nmemb
, uptr size
) {
88 if (DlsymAlloc::Use())
89 return DlsymAlloc::Callocate(nmemb
, size
);
91 GET_STACK_TRACE_MALLOC
;
92 return lsan_calloc(nmemb
, size
, stack
);
95 INTERCEPTOR(void *, realloc
, void *ptr
, uptr size
) {
96 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr
))
97 return DlsymAlloc::Realloc(ptr
, size
);
99 GET_STACK_TRACE_MALLOC
;
100 return lsan_realloc(ptr
, size
, stack
);
103 INTERCEPTOR(void*, reallocarray
, void *q
, uptr nmemb
, uptr size
) {
105 GET_STACK_TRACE_MALLOC
;
106 return lsan_reallocarray(q
, nmemb
, size
, stack
);
109 INTERCEPTOR(int, posix_memalign
, void **memptr
, uptr alignment
, uptr size
) {
111 GET_STACK_TRACE_MALLOC
;
112 return lsan_posix_memalign(memptr
, alignment
, size
, stack
);
115 INTERCEPTOR(void*, valloc
, uptr size
) {
117 GET_STACK_TRACE_MALLOC
;
118 return lsan_valloc(size
, stack
);
120 #endif // !SANITIZER_APPLE
122 #if SANITIZER_INTERCEPT_MEMALIGN
123 INTERCEPTOR(void*, memalign
, uptr alignment
, uptr size
) {
125 GET_STACK_TRACE_MALLOC
;
126 return lsan_memalign(alignment
, size
, stack
);
128 #define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
130 #define LSAN_MAYBE_INTERCEPT_MEMALIGN
131 #endif // SANITIZER_INTERCEPT_MEMALIGN
133 #if SANITIZER_INTERCEPT___LIBC_MEMALIGN
134 INTERCEPTOR(void *, __libc_memalign
, uptr alignment
, uptr size
) {
136 GET_STACK_TRACE_MALLOC
;
137 return lsan_memalign(alignment
, size
, stack
);
139 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
141 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
142 #endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN
144 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
145 INTERCEPTOR(void*, aligned_alloc
, uptr alignment
, uptr size
) {
147 GET_STACK_TRACE_MALLOC
;
148 return lsan_aligned_alloc(alignment
, size
, stack
);
150 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)
152 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC
155 #if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE
156 INTERCEPTOR(uptr
, malloc_usable_size
, void *ptr
) {
158 return GetMallocUsableSize(ptr
);
160 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
161 INTERCEPT_FUNCTION(malloc_usable_size)
163 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
166 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
167 struct fake_mallinfo
{
171 INTERCEPTOR(struct fake_mallinfo
, mallinfo
, void) {
172 struct fake_mallinfo res
;
173 internal_memset(&res
, 0, sizeof(res
));
176 #define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
178 INTERCEPTOR(int, mallopt
, int cmd
, int value
) {
181 #define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
183 #define LSAN_MAYBE_INTERCEPT_MALLINFO
184 #define LSAN_MAYBE_INTERCEPT_MALLOPT
185 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
187 #if SANITIZER_INTERCEPT_PVALLOC
188 INTERCEPTOR(void*, pvalloc
, uptr size
) {
190 GET_STACK_TRACE_MALLOC
;
191 return lsan_pvalloc(size
, stack
);
193 #define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
195 #define LSAN_MAYBE_INTERCEPT_PVALLOC
196 #endif // SANITIZER_INTERCEPT_PVALLOC
198 #if SANITIZER_INTERCEPT_CFREE
199 INTERCEPTOR(void, cfree
, void *p
) ALIAS(WRAP(free
));
200 #define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
202 #define LSAN_MAYBE_INTERCEPT_CFREE
203 #endif // SANITIZER_INTERCEPT_CFREE
205 #if SANITIZER_INTERCEPT_MCHECK_MPROBE
206 INTERCEPTOR(int, mcheck
, void (*abortfunc
)(int mstatus
)) {
210 INTERCEPTOR(int, mcheck_pedantic
, void (*abortfunc
)(int mstatus
)) {
214 INTERCEPTOR(int, mprobe
, void *ptr
) {
217 #endif // SANITIZER_INTERCEPT_MCHECK_MPROBE
220 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
221 #define OPERATOR_NEW_BODY(nothrow)\
223 GET_STACK_TRACE_MALLOC;\
224 void *res = lsan_malloc(size, stack);\
225 if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
227 #define OPERATOR_NEW_BODY_ALIGN(nothrow)\
229 GET_STACK_TRACE_MALLOC;\
230 void *res = lsan_memalign((uptr)align, size, stack);\
231 if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
234 #define OPERATOR_DELETE_BODY\
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.
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*/); }
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
; }
303 #else // SANITIZER_APPLE
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*/); }
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
; }
323 #endif // !SANITIZER_APPLE
326 ///// Thread initialization and finalization. /////
328 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA
329 static unsigned g_thread_finalize_key
;
331 static void thread_finalize(void *v
) {
334 if (pthread_setspecific(g_thread_finalize_key
, (void*)(iter
- 1))) {
335 Report("LeakSanitizer: failed to set thread key.\n");
345 INTERCEPTOR(void, _lwp_exit
) {
350 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit)
352 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT
355 #if SANITIZER_INTERCEPT_THR_EXIT
356 INTERCEPTOR(void, thr_exit
, tid_t
*state
) {
359 REAL(thr_exit
)(state
);
361 #define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit)
363 #define LSAN_MAYBE_INTERCEPT_THR_EXIT
366 #if SANITIZER_INTERCEPT___CXA_ATEXIT
367 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
369 __lsan::ScopedInterceptorDisabler disabler
;
370 return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
372 #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
374 #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
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);
382 #define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
384 #define LSAN_MAYBE_INTERCEPT_ATEXIT
387 #if SANITIZER_INTERCEPT_PTHREAD_ATFORK
389 extern int _pthread_atfork(void (*prepare
)(), void (*parent
)(),
393 INTERCEPTOR(int, pthread_atfork
, void (*prepare
)(), void (*parent
)(),
395 __lsan::ScopedInterceptorDisabler disabler
;
396 // REAL(pthread_atfork) cannot be called due to symbol indirections at least
398 return _pthread_atfork(prepare
, parent
, child
);
400 #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
402 #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
405 #if SANITIZER_INTERCEPT_STRERROR
406 INTERCEPTOR(char *, strerror
, int errnum
) {
407 __lsan::ScopedInterceptorDisabler disabler
;
408 return REAL(strerror
)(errnum
);
410 #define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
412 #define LSAN_MAYBE_INTERCEPT_STRERROR
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");
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
);
438 INTERCEPTOR(int, pthread_create
, void *th
, void *attr
,
439 void *(*callback
)(void *), void *param
) {
441 EnsureMainThreadIDIsCorrect();
443 bool detached
= [attr
]() {
445 return attr
&& !pthread_attr_getdetachstate(attr
, &d
) && IsStateDetached(d
);
448 __sanitizer_pthread_attr_t myattr
;
450 pthread_attr_init(&myattr
);
453 AdjustStackSize(attr
);
454 uptr this_tid
= GetCurrentThreadId();
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>,
466 return result
? 0 : *(uptr
*)(th
);
470 pthread_attr_destroy(&myattr
);
474 INTERCEPTOR(int, pthread_join
, void *thread
, void **retval
) {
476 GetThreadArgRetval().Join((uptr
)thread
, [&]() {
477 result
= REAL(pthread_join
)(thread
, retval
);
483 INTERCEPTOR(int, pthread_detach
, void *thread
) {
485 GetThreadArgRetval().Detach((uptr
)thread
, [&]() {
486 result
= REAL(pthread_detach
)(thread
);
492 INTERCEPTOR(void, pthread_exit
, void *retval
) {
493 GetThreadArgRetval().Finish(GetThreadSelf(), retval
);
494 REAL(pthread_exit
)(retval
);
497 # if SANITIZER_INTERCEPT_TRYJOIN
498 INTERCEPTOR(int, pthread_tryjoin_np
, void *thread
, void **ret
) {
500 GetThreadArgRetval().Join((uptr
)thread
, [&]() {
501 result
= REAL(pthread_tryjoin_np
)(thread
, ret
);
506 # define LSAN_MAYBE_INTERCEPT_TRYJOIN INTERCEPT_FUNCTION(pthread_tryjoin_np)
508 # define LSAN_MAYBE_INTERCEPT_TRYJOIN
509 # endif // SANITIZER_INTERCEPT_TRYJOIN
511 # if SANITIZER_INTERCEPT_TIMEDJOIN
512 INTERCEPTOR(int, pthread_timedjoin_np
, void *thread
, void **ret
,
513 const struct timespec
*abstime
) {
515 GetThreadArgRetval().Join((uptr
)thread
, [&]() {
516 result
= REAL(pthread_timedjoin_np
)(thread
, ret
, abstime
);
521 # define LSAN_MAYBE_INTERCEPT_TIMEDJOIN \
522 INTERCEPT_FUNCTION(pthread_timedjoin_np)
524 # define LSAN_MAYBE_INTERCEPT_TIMEDJOIN
525 # endif // SANITIZER_INTERCEPT_TIMEDJOIN
527 DEFINE_INTERNAL_PTHREAD_FUNCTIONS
529 INTERCEPTOR(void, _exit
, int status
) {
530 if (status
== 0 && HasReportedLeaks()) status
= common_flags()->exitcode
;
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"
538 #endif // SANITIZER_POSIX
542 void InitializeInterceptors() {
543 // Fuchsia doesn't use interceptors that require any setup.
544 #if !SANITIZER_FUCHSIA
545 __interception::DoesNotSupportStaticLinking();
546 InitializeSignalInterceptors();
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
);
570 LSAN_MAYBE_INTERCEPT__LWP_EXIT
;
571 LSAN_MAYBE_INTERCEPT_THR_EXIT
;
573 LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
;
574 LSAN_MAYBE_INTERCEPT_ATEXIT
;
575 LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
;
577 LSAN_MAYBE_INTERCEPT_STRERROR
;
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");
586 #endif // !SANITIZER_FUCHSIA
589 } // namespace __lsan