lsan_fuchsia.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. #include "sanitizer_common/sanitizer_platform.h"
  14. #if SANITIZER_FUCHSIA
  15. #error #include <zircon/sanitizer.h>
  16. #include "lsan.h"
  17. #include "lsan_allocator.h"
  18. using namespace __lsan;
  19. namespace __lsan {
  20. void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {}
  21. ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}
  22. struct OnCreatedArgs {
  23. uptr stack_begin, stack_end;
  24. };
  25. // On Fuchsia, the stack bounds of a new thread are available before
  26. // the thread itself has started running.
  27. void ThreadContext::OnCreated(void *arg) {
  28. // Stack bounds passed through from __sanitizer_before_thread_create_hook
  29. // or InitializeMainThread.
  30. auto args = reinterpret_cast<const OnCreatedArgs *>(arg);
  31. stack_begin_ = args->stack_begin;
  32. stack_end_ = args->stack_end;
  33. }
  34. struct OnStartedArgs {
  35. uptr cache_begin, cache_end;
  36. };
  37. void ThreadContext::OnStarted(void *arg) {
  38. ThreadContextLsanBase::OnStarted(arg);
  39. auto args = reinterpret_cast<const OnStartedArgs *>(arg);
  40. cache_begin_ = args->cache_begin;
  41. cache_end_ = args->cache_end;
  42. }
  43. void ThreadStart(u32 tid) {
  44. OnStartedArgs args;
  45. GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
  46. CHECK_EQ(args.cache_end - args.cache_begin, sizeof(AllocatorCache));
  47. ThreadContextLsanBase::ThreadStart(tid, GetTid(), ThreadType::Regular, &args);
  48. }
  49. void InitializeMainThread() {
  50. OnCreatedArgs args;
  51. __sanitizer::GetThreadStackTopAndBottom(true, &args.stack_end,
  52. &args.stack_begin);
  53. u32 tid = ThreadCreate(kMainTid, true, &args);
  54. CHECK_EQ(tid, 0);
  55. ThreadStart(tid);
  56. }
  57. void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {
  58. GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
  59. [](ThreadContextBase *tctx, void *arg) {
  60. auto ctx = static_cast<ThreadContext *>(tctx);
  61. static_cast<decltype(caches)>(arg)->push_back(ctx->cache_begin());
  62. },
  63. caches);
  64. }
  65. // On Fuchsia, leak detection is done by a special hook after atexit hooks.
  66. // So this doesn't install any atexit hook like on other platforms.
  67. void InstallAtExitCheckLeaks() {}
  68. void InstallAtForkHandler() {}
  69. // ASan defines this to check its `halt_on_error` flag.
  70. bool UseExitcodeOnLeak() { return true; }
  71. } // namespace __lsan
  72. // These are declared (in extern "C") by <zircon/sanitizer.h>.
  73. // The system runtime will call our definitions directly.
  74. // This is called before each thread creation is attempted. So, in
  75. // its first call, the calling thread is the initial and sole thread.
  76. void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,
  77. const char *name, void *stack_base,
  78. size_t stack_size) {
  79. ENSURE_LSAN_INITED;
  80. EnsureMainThreadIDIsCorrect();
  81. OnCreatedArgs args;
  82. args.stack_begin = reinterpret_cast<uptr>(stack_base);
  83. args.stack_end = args.stack_begin + stack_size;
  84. u32 parent_tid = GetCurrentThreadId();
  85. u32 tid = ThreadCreate(parent_tid, detached, &args);
  86. return reinterpret_cast<void *>(static_cast<uptr>(tid));
  87. }
  88. // This is called after creating a new thread (in the creating thread),
  89. // with the pointer returned by __sanitizer_before_thread_create_hook (above).
  90. void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {
  91. u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));
  92. // On success, there is nothing to do here.
  93. if (error != thrd_success) {
  94. // Clean up the thread registry for the thread creation that didn't happen.
  95. GetLsanThreadRegistryLocked()->FinishThread(tid);
  96. }
  97. }
  98. // This is called in the newly-created thread before it runs anything else,
  99. // with the pointer returned by __sanitizer_before_thread_create_hook (above).
  100. void __sanitizer_thread_start_hook(void *hook, thrd_t self) {
  101. u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));
  102. ThreadStart(tid);
  103. }
  104. // Each thread runs this just before it exits,
  105. // with the pointer returned by BeforeThreadCreateHook (above).
  106. // All per-thread destructors have already been called.
  107. void __sanitizer_thread_exit_hook(void *hook, thrd_t self) { ThreadFinish(); }
  108. #endif // SANITIZER_FUCHSIA