124 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| //=-- lsan_fuchsia.cpp ---------------------------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===---------------------------------------------------------------------===//
 | |
| //
 | |
| // This file is a part of LeakSanitizer.
 | |
| // Standalone LSan RTL code specific to Fuchsia.
 | |
| //
 | |
| //===---------------------------------------------------------------------===//
 | |
| 
 | |
| #include "sanitizer_common/sanitizer_platform.h"
 | |
| 
 | |
| #if SANITIZER_FUCHSIA
 | |
| #include <zircon/sanitizer.h>
 | |
| 
 | |
| #include "lsan.h"
 | |
| #include "lsan_allocator.h"
 | |
| 
 | |
| using namespace __lsan;
 | |
| 
 | |
| namespace __lsan {
 | |
| 
 | |
| void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {}
 | |
| 
 | |
| ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}
 | |
| 
 | |
| struct OnCreatedArgs {
 | |
|   uptr stack_begin, stack_end;
 | |
| };
 | |
| 
 | |
| // On Fuchsia, the stack bounds of a new thread are available before
 | |
| // the thread itself has started running.
 | |
| void ThreadContext::OnCreated(void *arg) {
 | |
|   // Stack bounds passed through from __sanitizer_before_thread_create_hook
 | |
|   // or InitializeMainThread.
 | |
|   auto args = reinterpret_cast<const OnCreatedArgs *>(arg);
 | |
|   stack_begin_ = args->stack_begin;
 | |
|   stack_end_ = args->stack_end;
 | |
| }
 | |
| 
 | |
| struct OnStartedArgs {
 | |
|   uptr cache_begin, cache_end;
 | |
| };
 | |
| 
 | |
| void ThreadContext::OnStarted(void *arg) {
 | |
|   auto args = reinterpret_cast<const OnStartedArgs *>(arg);
 | |
|   cache_begin_ = args->cache_begin;
 | |
|   cache_end_ = args->cache_end;
 | |
| }
 | |
| 
 | |
| void ThreadStart(u32 tid) {
 | |
|   OnStartedArgs args;
 | |
|   GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
 | |
|   CHECK_EQ(args.cache_end - args.cache_begin, sizeof(AllocatorCache));
 | |
|   ThreadContextLsanBase::ThreadStart(tid, GetTid(), ThreadType::Regular, &args);
 | |
| }
 | |
| 
 | |
| void InitializeMainThread() {
 | |
|   OnCreatedArgs args;
 | |
|   __sanitizer::GetThreadStackTopAndBottom(true, &args.stack_end,
 | |
|                                           &args.stack_begin);
 | |
|   u32 tid = ThreadCreate(0, GetThreadSelf(), true, &args);
 | |
|   CHECK_EQ(tid, 0);
 | |
|   ThreadStart(tid);
 | |
| }
 | |
| 
 | |
| void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {
 | |
|   GetThreadRegistryLocked()->RunCallbackForEachThreadLocked(
 | |
|       [](ThreadContextBase *tctx, void *arg) {
 | |
|         auto ctx = static_cast<ThreadContext *>(tctx);
 | |
|         static_cast<decltype(caches)>(arg)->push_back(ctx->cache_begin());
 | |
|       },
 | |
|       caches);
 | |
| }
 | |
| 
 | |
| }  // namespace __lsan
 | |
| 
 | |
| // These are declared (in extern "C") by <zircon/sanitizer.h>.
 | |
| // The system runtime will call our definitions directly.
 | |
| 
 | |
| // This is called before each thread creation is attempted.  So, in
 | |
| // its first call, the calling thread is the initial and sole thread.
 | |
| void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,
 | |
|                                             const char *name, void *stack_base,
 | |
|                                             size_t stack_size) {
 | |
|   uptr user_id = reinterpret_cast<uptr>(thread);
 | |
|   ENSURE_LSAN_INITED;
 | |
|   EnsureMainThreadIDIsCorrect();
 | |
|   OnCreatedArgs args;
 | |
|   args.stack_begin = reinterpret_cast<uptr>(stack_base);
 | |
|   args.stack_end = args.stack_begin + stack_size;
 | |
|   u32 parent_tid = GetCurrentThread();
 | |
|   u32 tid = ThreadCreate(parent_tid, user_id, detached, &args);
 | |
|   return reinterpret_cast<void *>(static_cast<uptr>(tid));
 | |
| }
 | |
| 
 | |
| // This is called after creating a new thread (in the creating thread),
 | |
| // with the pointer returned by __sanitizer_before_thread_create_hook (above).
 | |
| void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {
 | |
|   u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));
 | |
|   // On success, there is nothing to do here.
 | |
|   if (error != thrd_success) {
 | |
|     // Clean up the thread registry for the thread creation that didn't happen.
 | |
|     GetThreadRegistryLocked()->FinishThread(tid);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // This is called in the newly-created thread before it runs anything else,
 | |
| // with the pointer returned by __sanitizer_before_thread_create_hook (above).
 | |
| void __sanitizer_thread_start_hook(void *hook, thrd_t self) {
 | |
|   u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));
 | |
|   ThreadStart(tid);
 | |
| }
 | |
| 
 | |
| // Each thread runs this just before it exits,
 | |
| // with the pointer returned by BeforeThreadCreateHook (above).
 | |
| // All per-thread destructors have already been called.
 | |
| void __sanitizer_thread_exit_hook(void *hook, thrd_t self) { ThreadFinish(); }
 | |
| 
 | |
| #endif  // SANITIZER_FUCHSIA
 |