1 //=-- lsan_fuchsia.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 // Standalone LSan RTL code specific to Fuchsia.
12 //===---------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_platform.h"
17 #include <zircon/sanitizer.h>
20 #include "lsan_allocator.h"
22 using namespace __lsan
;
26 void LsanOnDeadlySignal(int signo
, void *siginfo
, void *context
) {}
28 ThreadContext::ThreadContext(int tid
) : ThreadContextLsanBase(tid
) {}
30 struct OnCreatedArgs
{
31 uptr stack_begin
, stack_end
;
34 // On Fuchsia, the stack bounds of a new thread are available before
35 // the thread itself has started running.
36 void ThreadContext::OnCreated(void *arg
) {
37 // Stack bounds passed through from __sanitizer_before_thread_create_hook
38 // or InitializeMainThread.
39 auto args
= reinterpret_cast<const OnCreatedArgs
*>(arg
);
40 stack_begin_
= args
->stack_begin
;
41 stack_end_
= args
->stack_end
;
44 struct OnStartedArgs
{
45 uptr cache_begin
, cache_end
;
48 void ThreadContext::OnStarted(void *arg
) {
49 ThreadContextLsanBase::OnStarted(arg
);
50 auto args
= reinterpret_cast<const OnStartedArgs
*>(arg
);
51 cache_begin_
= args
->cache_begin
;
52 cache_end_
= args
->cache_end
;
55 void ThreadStart(u32 tid
) {
57 GetAllocatorCacheRange(&args
.cache_begin
, &args
.cache_end
);
58 CHECK_EQ(args
.cache_end
- args
.cache_begin
, sizeof(AllocatorCache
));
59 ThreadContextLsanBase::ThreadStart(tid
, GetTid(), ThreadType::Regular
, &args
);
62 void InitializeMainThread() {
64 __sanitizer::GetThreadStackTopAndBottom(true, &args
.stack_end
,
66 u32 tid
= ThreadCreate(kMainTid
, true, &args
);
71 void GetAllThreadAllocatorCachesLocked(InternalMmapVector
<uptr
> *caches
) {
72 GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
73 [](ThreadContextBase
*tctx
, void *arg
) {
74 auto ctx
= static_cast<ThreadContext
*>(tctx
);
75 static_cast<decltype(caches
)>(arg
)->push_back(ctx
->cache_begin());
80 // On Fuchsia, leak detection is done by a special hook after atexit hooks.
81 // So this doesn't install any atexit hook like on other platforms.
82 void InstallAtExitCheckLeaks() {}
83 void InstallAtForkHandler() {}
85 // ASan defines this to check its `halt_on_error` flag.
86 bool UseExitcodeOnLeak() { return true; }
90 // These are declared (in extern "C") by <zircon/sanitizer.h>.
91 // The system runtime will call our definitions directly.
93 // This is called before each thread creation is attempted. So, in
94 // its first call, the calling thread is the initial and sole thread.
95 void *__sanitizer_before_thread_create_hook(thrd_t thread
, bool detached
,
96 const char *name
, void *stack_base
,
99 EnsureMainThreadIDIsCorrect();
101 args
.stack_begin
= reinterpret_cast<uptr
>(stack_base
);
102 args
.stack_end
= args
.stack_begin
+ stack_size
;
103 u32 parent_tid
= GetCurrentThreadId();
104 u32 tid
= ThreadCreate(parent_tid
, detached
, &args
);
105 return reinterpret_cast<void *>(static_cast<uptr
>(tid
));
108 // This is called after creating a new thread (in the creating thread),
109 // with the pointer returned by __sanitizer_before_thread_create_hook (above).
110 void __sanitizer_thread_create_hook(void *hook
, thrd_t thread
, int error
) {
111 u32 tid
= static_cast<u32
>(reinterpret_cast<uptr
>(hook
));
112 // On success, there is nothing to do here.
113 if (error
!= thrd_success
) {
114 // Clean up the thread registry for the thread creation that didn't happen.
115 GetLsanThreadRegistryLocked()->FinishThread(tid
);
119 // This is called in the newly-created thread before it runs anything else,
120 // with the pointer returned by __sanitizer_before_thread_create_hook (above).
121 void __sanitizer_thread_start_hook(void *hook
, thrd_t self
) {
122 u32 tid
= static_cast<u32
>(reinterpret_cast<uptr
>(hook
));
126 // Each thread runs this just before it exits,
127 // with the pointer returned by BeforeThreadCreateHook (above).
128 // All per-thread destructors have already been called.
129 void __sanitizer_thread_exit_hook(void *hook
, thrd_t self
) { ThreadFinish(); }
131 #endif // SANITIZER_FUCHSIA