sanitizers.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "sanitizers.h"
  2. #include "thread.h"
  3. #if defined(_asan_enabled_)
  4. extern "C" {
  5. void __sanitizer_start_switch_fiber(void** fake_stack_save, const void* bottom, size_t size);
  6. void __sanitizer_finish_switch_fiber(void* fake_stack_save, const void** old_bottom, size_t* old_size);
  7. }
  8. #endif
  9. #if defined(_tsan_enabled_)
  10. #if defined(__clang_major__) && (__clang_major__ >= 9)
  11. extern "C" {
  12. void* __tsan_get_current_fiber(void);
  13. void* __tsan_create_fiber(unsigned flags);
  14. void __tsan_destroy_fiber(void* fiber);
  15. void __tsan_switch_to_fiber(void* fiber, unsigned flags);
  16. void __tsan_set_fiber_name(void* fiber, const char* name);
  17. }
  18. #else
  19. namespace {
  20. void* __tsan_get_current_fiber(void) {
  21. return nullptr;
  22. }
  23. void* __tsan_create_fiber(unsigned) {
  24. return nullptr;
  25. }
  26. void __tsan_destroy_fiber(void*) {
  27. }
  28. void __tsan_switch_to_fiber(void*, unsigned) {
  29. }
  30. void __tsan_set_fiber_name(void*, const char*) {
  31. }
  32. }
  33. #endif
  34. #endif
  35. using namespace NSan;
  36. TFiberContext::TFiberContext() noexcept
  37. : Token_(nullptr)
  38. , IsMainFiber_(true)
  39. #if defined(_tsan_enabled_)
  40. , CurrentTSanFiberContext_(__tsan_get_current_fiber())
  41. #endif
  42. {
  43. TCurrentThreadLimits sl;
  44. Stack_ = sl.StackBegin;
  45. Len_ = sl.StackLength;
  46. #if defined(_tsan_enabled_)
  47. static constexpr char MainFiberName[] = "main_fiber";
  48. __tsan_set_fiber_name(CurrentTSanFiberContext_, MainFiberName);
  49. #endif
  50. }
  51. TFiberContext::TFiberContext(const void* stack, size_t len, const char* contName) noexcept
  52. : Token_(nullptr)
  53. , Stack_(stack)
  54. , Len_(len)
  55. , IsMainFiber_(false)
  56. #if defined(_tsan_enabled_)
  57. , CurrentTSanFiberContext_(__tsan_create_fiber(/*flags =*/0))
  58. #endif
  59. {
  60. (void)contName;
  61. #if defined(_tsan_enabled_)
  62. __tsan_set_fiber_name(CurrentTSanFiberContext_, contName);
  63. #endif
  64. }
  65. TFiberContext::~TFiberContext() noexcept {
  66. if (!IsMainFiber_) {
  67. #if defined(_asan_enabled_)
  68. if (Token_) {
  69. // destroy saved FakeStack
  70. void* activeFakeStack = nullptr;
  71. const void* activeStack = nullptr;
  72. size_t activeStackSize = 0;
  73. __sanitizer_start_switch_fiber(&activeFakeStack, (char*)Stack_, Len_);
  74. __sanitizer_finish_switch_fiber(Token_, &activeStack, &activeStackSize);
  75. __sanitizer_start_switch_fiber(nullptr, activeStack, activeStackSize);
  76. __sanitizer_finish_switch_fiber(activeFakeStack, nullptr, nullptr);
  77. }
  78. #endif
  79. #if defined(_tsan_enabled_)
  80. __tsan_destroy_fiber(CurrentTSanFiberContext_);
  81. #endif
  82. }
  83. }
  84. void TFiberContext::BeforeFinish() noexcept {
  85. #if defined(_asan_enabled_)
  86. __sanitizer_start_switch_fiber(nullptr, nullptr, 0);
  87. #else
  88. (void)Token_;
  89. (void)Stack_;
  90. (void)Len_;
  91. #endif
  92. }
  93. void TFiberContext::BeforeSwitch(TFiberContext* old) noexcept {
  94. #if defined(_asan_enabled_)
  95. __sanitizer_start_switch_fiber(old ? &old->Token_ : nullptr, (char*)Stack_, Len_);
  96. #else
  97. (void)old;
  98. #endif
  99. #if defined(_tsan_enabled_)
  100. __tsan_switch_to_fiber(CurrentTSanFiberContext_, /*flags =*/0);
  101. #endif
  102. }
  103. void TFiberContext::AfterSwitch() noexcept {
  104. #if defined(_asan_enabled_)
  105. __sanitizer_finish_switch_fiber(Token_, nullptr, nullptr);
  106. #endif
  107. }
  108. void TFiberContext::AfterStart() noexcept {
  109. #if defined(_asan_enabled_)
  110. __sanitizer_finish_switch_fiber(nullptr, nullptr, nullptr);
  111. #endif
  112. }
  113. #if defined(_tsan_enabled_)
  114. extern "C" {
  115. // This function should not be directly exposed in headers
  116. // due to signature variations among contrib headers.
  117. void AnnotateBenignRaceSized(const char* file, int line,
  118. const volatile void* address,
  119. size_t size,
  120. const char* description);
  121. }
  122. void NSan::AnnotateBenignRaceSized(const char* file, int line,
  123. const volatile void* address,
  124. size_t size,
  125. const char* description) noexcept {
  126. ::AnnotateBenignRaceSized(file, line, address, size, description);
  127. }
  128. #endif