123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- #pragma once
- #include "defaults.h"
- extern "C" { // sanitizers API
- #if defined(_asan_enabled_) || defined(_lsan_enabled_)
- void __lsan_ignore_object(const void* p);
- #endif
- #if defined(_asan_enabled_)
- void __sanitizer_start_switch_fiber(void** fake_stack_save, const void* bottom, size_t size);
- void __sanitizer_finish_switch_fiber(void* fake_stack_save, const void** old_bottom, size_t* old_size);
- #endif
- #if defined(_msan_enabled_)
- void __msan_unpoison(const volatile void* a, size_t size);
- void __msan_poison(const volatile void* a, size_t size);
- void __msan_check_mem_is_initialized(const volatile void* x, size_t size);
- #endif
- #if defined(_tsan_enabled_)
- void __tsan_acquire(void* a);
- void __tsan_release(void* a);
- void* __tsan_get_current_fiber(void);
- void __tsan_destroy_fiber(void* fiber);
- void __tsan_switch_to_fiber(void* fiber, unsigned flags);
- #endif
- } // sanitizers API
- namespace NSan {
- class TFiberContext {
- public:
- TFiberContext() noexcept;
- TFiberContext(const void* stack, size_t len, const char* contName) noexcept;
- ~TFiberContext() noexcept {
- if (!IsMainFiber_) {
- #if defined(_asan_enabled_)
- if (Token_) {
- // destroy saved FakeStack
- void* activeFakeStack = nullptr;
- const void* activeStack = nullptr;
- size_t activeStackSize = 0;
- __sanitizer_start_switch_fiber(&activeFakeStack, (char*)Stack_, Len_);
- __sanitizer_finish_switch_fiber(Token_, &activeStack, &activeStackSize);
- __sanitizer_start_switch_fiber(nullptr, activeStack, activeStackSize);
- __sanitizer_finish_switch_fiber(activeFakeStack, nullptr, nullptr);
- }
- #endif
- #if defined(_tsan_enabled_)
- __tsan_destroy_fiber(CurrentTSanFiberContext_);
- #endif
- }
- }
- Y_FORCE_INLINE void BeforeSwitch(TFiberContext* old) noexcept {
- #if defined(_asan_enabled_)
- __sanitizer_start_switch_fiber(old ? &old->Token_ : nullptr, (char*)Stack_, Len_);
- #else
- (void)old;
- #endif
- #if defined(_tsan_enabled_)
- __tsan_switch_to_fiber(CurrentTSanFiberContext_, /*flags =*/0);
- #endif
- }
- void AfterSwitch() noexcept {
- #if defined(_asan_enabled_)
- __sanitizer_finish_switch_fiber(Token_, nullptr, nullptr);
- #endif
- }
- private:
- void* Token_;
- const void* Stack_;
- size_t Len_;
- const bool IsMainFiber_;
- #if defined(_tsan_enabled_)
- void* const CurrentTSanFiberContext_;
- #endif
- };
- // Returns plain if no sanitizer enabled or sanitized otherwise
- // Ment to be used in test code for constants (timeouts, etc)
- template <typename T>
- inline constexpr static T PlainOrUnderSanitizer(T plain, T sanitized) noexcept {
- #if defined(_tsan_enabled_) || defined(_msan_enabled_) || defined(_asan_enabled_)
- Y_UNUSED(plain);
- return sanitized;
- #else
- Y_UNUSED(sanitized);
- return plain;
- #endif
- }
- // Determines if asan present
- inline constexpr static bool ASanIsOn() noexcept {
- #if defined(_asan_enabled_)
- return true;
- #else
- return false;
- #endif
- }
- // Determines if tsan present
- inline constexpr static bool TSanIsOn() noexcept {
- #if defined(_tsan_enabled_)
- return true;
- #else
- return false;
- #endif
- }
- // Determines if msan present
- inline constexpr static bool MSanIsOn() noexcept {
- #if defined(_msan_enabled_)
- return true;
- #else
- return false;
- #endif
- }
- // Make memory region fully initialized (without changing its contents).
- inline static void Unpoison(const volatile void* a, size_t size) noexcept {
- #if defined(_msan_enabled_)
- __msan_unpoison(a, size);
- #else
- Y_UNUSED(a);
- Y_UNUSED(size);
- #endif
- }
- // Make memory region fully uninitialized (without changing its contents).
- // This is a legacy interface that does not update origin information. Use __msan_allocated_memory() instead.
- inline static void Poison(const volatile void* a, size_t size) noexcept {
- #if defined(_msan_enabled_)
- __msan_poison(a, size);
- #else
- Y_UNUSED(a);
- Y_UNUSED(size);
- #endif
- }
- // Checks that memory range is fully initialized, and reports an error if it is not.
- inline static void CheckMemIsInitialized(const volatile void* a, size_t size) noexcept {
- #if defined(_msan_enabled_)
- __msan_check_mem_is_initialized(a, size);
- #else
- Y_UNUSED(a);
- Y_UNUSED(size);
- #endif
- }
- inline static void MarkAsIntentionallyLeaked(const void* ptr) noexcept {
- #if defined(_asan_enabled_) || defined(_lsan_enabled_)
- __lsan_ignore_object(ptr);
- #else
- Y_UNUSED(ptr);
- #endif
- }
- #if defined(_tsan_enabled_)
- // defined in .cpp to avoid exposing problematic C-linkage version of AnnotateBenignRaceSized(...)
- void AnnotateBenignRaceSized(const char* file, int line,
- const volatile void* address,
- size_t size,
- const char* description) noexcept;
- #else
- inline static void AnnotateBenignRaceSized(const char* file, int line,
- const volatile void* address,
- size_t size,
- const char* description) noexcept {
- Y_UNUSED(file);
- Y_UNUSED(line);
- Y_UNUSED(address);
- Y_UNUSED(size);
- Y_UNUSED(description);
- }
- #endif
- inline static void Acquire(void* a) {
- #if defined(_tsan_enabled_)
- __tsan_acquire(a);
- #else
- Y_UNUSED(a);
- #endif
- }
- inline static void Release(void* a) {
- #if defined(_tsan_enabled_)
- __tsan_release(a);
- #else
- Y_UNUSED(a);
- #endif
- }
- } // namespace NSan
|