Path: blob/main/contrib/llvm-project/compiler-rt/lib/lsan/lsan_fuchsia.cpp
35233 views
//=-- lsan_fuchsia.cpp ---------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===---------------------------------------------------------------------===//7//8// This file is a part of LeakSanitizer.9// Standalone LSan RTL code specific to Fuchsia.10//11//===---------------------------------------------------------------------===//1213#include "sanitizer_common/sanitizer_platform.h"1415#if SANITIZER_FUCHSIA16#include <zircon/sanitizer.h>1718#include "lsan.h"19#include "lsan_allocator.h"2021using namespace __lsan;2223namespace __lsan {2425void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {}2627ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}2829struct OnCreatedArgs {30uptr stack_begin, stack_end;31};3233// On Fuchsia, the stack bounds of a new thread are available before34// the thread itself has started running.35void ThreadContext::OnCreated(void *arg) {36// Stack bounds passed through from __sanitizer_before_thread_create_hook37// or InitializeMainThread.38auto args = reinterpret_cast<const OnCreatedArgs *>(arg);39stack_begin_ = args->stack_begin;40stack_end_ = args->stack_end;41}4243struct OnStartedArgs {44uptr cache_begin, cache_end;45};4647void ThreadContext::OnStarted(void *arg) {48ThreadContextLsanBase::OnStarted(arg);49auto args = reinterpret_cast<const OnStartedArgs *>(arg);50cache_begin_ = args->cache_begin;51cache_end_ = args->cache_end;52}5354void ThreadStart(u32 tid) {55OnStartedArgs args;56GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);57CHECK_EQ(args.cache_end - args.cache_begin, sizeof(AllocatorCache));58ThreadContextLsanBase::ThreadStart(tid, GetTid(), ThreadType::Regular, &args);59}6061void InitializeMainThread() {62OnCreatedArgs args;63__sanitizer::GetThreadStackTopAndBottom(true, &args.stack_end,64&args.stack_begin);65u32 tid = ThreadCreate(kMainTid, true, &args);66CHECK_EQ(tid, 0);67ThreadStart(tid);68}6970void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {71GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(72[](ThreadContextBase *tctx, void *arg) {73auto ctx = static_cast<ThreadContext *>(tctx);74static_cast<decltype(caches)>(arg)->push_back(ctx->cache_begin());75},76caches);77}7879// On Fuchsia, leak detection is done by a special hook after atexit hooks.80// So this doesn't install any atexit hook like on other platforms.81void InstallAtExitCheckLeaks() {}82void InstallAtForkHandler() {}8384// ASan defines this to check its `halt_on_error` flag.85bool UseExitcodeOnLeak() { return true; }8687} // namespace __lsan8889// These are declared (in extern "C") by <zircon/sanitizer.h>.90// The system runtime will call our definitions directly.9192// This is called before each thread creation is attempted. So, in93// its first call, the calling thread is the initial and sole thread.94void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,95const char *name, void *stack_base,96size_t stack_size) {97ENSURE_LSAN_INITED;98EnsureMainThreadIDIsCorrect();99OnCreatedArgs args;100args.stack_begin = reinterpret_cast<uptr>(stack_base);101args.stack_end = args.stack_begin + stack_size;102u32 parent_tid = GetCurrentThreadId();103u32 tid = ThreadCreate(parent_tid, detached, &args);104return reinterpret_cast<void *>(static_cast<uptr>(tid));105}106107// This is called after creating a new thread (in the creating thread),108// with the pointer returned by __sanitizer_before_thread_create_hook (above).109void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {110u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));111// On success, there is nothing to do here.112if (error != thrd_success) {113// Clean up the thread registry for the thread creation that didn't happen.114GetLsanThreadRegistryLocked()->FinishThread(tid);115}116}117118// This is called in the newly-created thread before it runs anything else,119// with the pointer returned by __sanitizer_before_thread_create_hook (above).120void __sanitizer_thread_start_hook(void *hook, thrd_t self) {121u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));122ThreadStart(tid);123}124125// Each thread runs this just before it exits,126// with the pointer returned by BeforeThreadCreateHook (above).127// All per-thread destructors have already been called.128void __sanitizer_thread_exit_hook(void *hook, thrd_t self) { ThreadFinish(); }129130#endif // SANITIZER_FUCHSIA131132133