aboutsummaryrefslogblamecommitdiffstats
path: root/util/system/sanitizers.cpp
blob: bb799a9e2e77993525922f718c6b7972a9ed67c1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                       







                                                                                                           
                           
                                                          
            



                                                              
 
         
           










                                                    
 
          
      


                                       


                                                          



                            



                                                                   
 
                                                                                          

                     
                           
                                                                 
      
 


                                                              

                                          















                                                                                    










                                                        
                                                               
                                                                                      
              
      
                           
                                                                   
      


                                            





                                                               





                                                              
                                                              
                                             
                                                          
 
                                                                
                                               
                                                                      

                                                                      
#include "sanitizers.h"
#include "thread.h"

#if defined(_asan_enabled_)
extern "C" {
    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(_tsan_enabled_)
    #if defined(__clang_major__) && (__clang_major__ >= 9)
extern "C" {
    void* __tsan_get_current_fiber(void);
    void* __tsan_create_fiber(unsigned flags);
    void __tsan_destroy_fiber(void* fiber);
    void __tsan_switch_to_fiber(void* fiber, unsigned flags);
    void __tsan_set_fiber_name(void* fiber, const char* name);
}
    #else
namespace {
    void* __tsan_get_current_fiber(void) {
        return nullptr;
    }
    void* __tsan_create_fiber(unsigned) {
        return nullptr;
    }
    void __tsan_destroy_fiber(void*) {
    }
    void __tsan_switch_to_fiber(void*, unsigned) {
    }
    void __tsan_set_fiber_name(void*, const char*) {
    }
}
    #endif
#endif

using namespace NSan;

TFiberContext::TFiberContext() noexcept
    : Token_(nullptr)
    , IsMainFiber_(true)
#if defined(_tsan_enabled_)
    , CurrentTSanFiberContext_(__tsan_get_current_fiber())
#endif
{
    TCurrentThreadLimits sl;

    Stack_ = sl.StackBegin;
    Len_ = sl.StackLength;

#if defined(_tsan_enabled_)
    static constexpr char MainFiberName[] = "main_fiber";
    __tsan_set_fiber_name(CurrentTSanFiberContext_, MainFiberName);
#endif
}

TFiberContext::TFiberContext(const void* stack, size_t len, const char* contName) noexcept
    : Token_(nullptr)
    , Stack_(stack)
    , Len_(len)
    , IsMainFiber_(false)
#if defined(_tsan_enabled_)
    , CurrentTSanFiberContext_(__tsan_create_fiber(/*flags =*/0))
#endif
{
    (void)contName;
#if defined(_tsan_enabled_)
    __tsan_set_fiber_name(CurrentTSanFiberContext_, contName);
#endif
}

TFiberContext::~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
    }
}

void TFiberContext::BeforeFinish() noexcept {
#if defined(_asan_enabled_)
    __sanitizer_start_switch_fiber(nullptr, nullptr, 0);
#else
    (void)Token_;
    (void)Stack_;
    (void)Len_;
#endif
}

void TFiberContext::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 TFiberContext::AfterSwitch() noexcept {
#if defined(_asan_enabled_)
    __sanitizer_finish_switch_fiber(Token_, nullptr, nullptr);
#endif
}

void TFiberContext::AfterStart() noexcept {
#if defined(_asan_enabled_)
    __sanitizer_finish_switch_fiber(nullptr, nullptr, nullptr);
#endif
}

#if defined(_tsan_enabled_)
extern "C" {
    // This function should not be directly exposed in headers
    // due to signature variations among contrib headers.
    void AnnotateBenignRaceSized(const char* file, int line,
                                 const volatile void* address,
                                 size_t size,
                                 const char* description);
}
void NSan::AnnotateBenignRaceSized(const char* file, int line,
                                   const volatile void* address,
                                   size_t size,
                                   const char* description) noexcept {
    ::AnnotateBenignRaceSized(file, line, address, size, description);
}
#endif