llvm-project
131 строка · 4.6 Кб
1//=-- lsan_fuchsia.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// Standalone LSan RTL code specific to Fuchsia.
11//
12//===---------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_platform.h"15
16#if SANITIZER_FUCHSIA17#include <zircon/sanitizer.h>18
19#include "lsan.h"20#include "lsan_allocator.h"21
22using namespace __lsan;23
24namespace __lsan {25
26void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {}27
28ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}29
30struct OnCreatedArgs {31uptr stack_begin, stack_end;32};33
34// On Fuchsia, the stack bounds of a new thread are available before
35// the thread itself has started running.
36void ThreadContext::OnCreated(void *arg) {37// Stack bounds passed through from __sanitizer_before_thread_create_hook38// or InitializeMainThread.39auto args = reinterpret_cast<const OnCreatedArgs *>(arg);40stack_begin_ = args->stack_begin;41stack_end_ = args->stack_end;42}
43
44struct OnStartedArgs {45uptr cache_begin, cache_end;46};47
48void ThreadContext::OnStarted(void *arg) {49ThreadContextLsanBase::OnStarted(arg);50auto args = reinterpret_cast<const OnStartedArgs *>(arg);51cache_begin_ = args->cache_begin;52cache_end_ = args->cache_end;53}
54
55void ThreadStart(u32 tid) {56OnStartedArgs args;57GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);58CHECK_EQ(args.cache_end - args.cache_begin, sizeof(AllocatorCache));59ThreadContextLsanBase::ThreadStart(tid, GetTid(), ThreadType::Regular, &args);60}
61
62void InitializeMainThread() {63OnCreatedArgs args;64__sanitizer::GetThreadStackTopAndBottom(true, &args.stack_end,65&args.stack_begin);66u32 tid = ThreadCreate(kMainTid, true, &args);67CHECK_EQ(tid, 0);68ThreadStart(tid);69}
70
71void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {72GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(73[](ThreadContextBase *tctx, void *arg) {74auto ctx = static_cast<ThreadContext *>(tctx);75static_cast<decltype(caches)>(arg)->push_back(ctx->cache_begin());76},77caches);78}
79
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.
82void InstallAtExitCheckLeaks() {}83void InstallAtForkHandler() {}84
85// ASan defines this to check its `halt_on_error` flag.
86bool UseExitcodeOnLeak() { return true; }87
88} // namespace __lsan89
90// These are declared (in extern "C") by <zircon/sanitizer.h>.
91// The system runtime will call our definitions directly.
92
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.
95void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,96const char *name, void *stack_base,97size_t stack_size) {98ENSURE_LSAN_INITED;99EnsureMainThreadIDIsCorrect();100OnCreatedArgs args;101args.stack_begin = reinterpret_cast<uptr>(stack_base);102args.stack_end = args.stack_begin + stack_size;103u32 parent_tid = GetCurrentThreadId();104u32 tid = ThreadCreate(parent_tid, detached, &args);105return reinterpret_cast<void *>(static_cast<uptr>(tid));106}
107
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).
110void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {111u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));112// On success, there is nothing to do here.113if (error != thrd_success) {114// Clean up the thread registry for the thread creation that didn't happen.115GetLsanThreadRegistryLocked()->FinishThread(tid);116}117}
118
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).
121void __sanitizer_thread_start_hook(void *hook, thrd_t self) {122u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));123ThreadStart(tid);124}
125
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.
129void __sanitizer_thread_exit_hook(void *hook, thrd_t self) { ThreadFinish(); }130
131#endif // SANITIZER_FUCHSIA132