aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang14-rt/lib/hwasan/hwasan_thread.cpp
diff options
context:
space:
mode:
authornkozlovskiy <nmk@ydb.tech>2023-10-11 19:11:46 +0300
committernkozlovskiy <nmk@ydb.tech>2023-10-11 19:33:28 +0300
commit61b3971447e473726d6cdb23fc298e457b4d973c (patch)
treee2a2a864bb7717f7ae6138f6a3194a254dd2c7bb /contrib/libs/clang14-rt/lib/hwasan/hwasan_thread.cpp
parenta674dc57d88d43c2e8e90a6084d5d2c988e0402c (diff)
downloadydb-61b3971447e473726d6cdb23fc298e457b4d973c.tar.gz
add sanitizers dependencies
Diffstat (limited to 'contrib/libs/clang14-rt/lib/hwasan/hwasan_thread.cpp')
-rw-r--r--contrib/libs/clang14-rt/lib/hwasan/hwasan_thread.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/contrib/libs/clang14-rt/lib/hwasan/hwasan_thread.cpp b/contrib/libs/clang14-rt/lib/hwasan/hwasan_thread.cpp
new file mode 100644
index 0000000000..c776ae179c
--- /dev/null
+++ b/contrib/libs/clang14-rt/lib/hwasan/hwasan_thread.cpp
@@ -0,0 +1,150 @@
+
+#include "hwasan_thread.h"
+
+#include "hwasan.h"
+#include "hwasan_interface_internal.h"
+#include "hwasan_mapping.h"
+#include "hwasan_poisoning.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_file.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+namespace __hwasan {
+
+static u32 RandomSeed() {
+ u32 seed;
+ do {
+ if (UNLIKELY(!GetRandom(reinterpret_cast<void *>(&seed), sizeof(seed),
+ /*blocking=*/false))) {
+ seed = static_cast<u32>(
+ (NanoTime() >> 12) ^
+ (reinterpret_cast<uptr>(__builtin_frame_address(0)) >> 4));
+ }
+ } while (!seed);
+ return seed;
+}
+
+void Thread::InitRandomState() {
+ random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
+ random_state_inited_ = true;
+
+ // Push a random number of zeros onto the ring buffer so that the first stack
+ // tag base will be random.
+ for (tag_t i = 0, e = GenerateRandomTag(); i != e; ++i)
+ stack_allocations_->push(0);
+}
+
+void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size,
+ const InitState *state) {
+ CHECK_EQ(0, unique_id_); // try to catch bad stack reuse
+ CHECK_EQ(0, stack_top_);
+ CHECK_EQ(0, stack_bottom_);
+
+ static atomic_uint64_t unique_id;
+ unique_id_ = atomic_fetch_add(&unique_id, 1, memory_order_relaxed);
+
+ if (auto sz = flags()->heap_history_size)
+ heap_allocations_ = HeapAllocationsRingBuffer::New(sz);
+
+#if !SANITIZER_FUCHSIA
+ // Do not initialize the stack ring buffer just yet on Fuchsia. Threads will
+ // be initialized before we enter the thread itself, so we will instead call
+ // this later.
+ InitStackRingBuffer(stack_buffer_start, stack_buffer_size);
+#endif
+ InitStackAndTls(state);
+}
+
+void Thread::InitStackRingBuffer(uptr stack_buffer_start,
+ uptr stack_buffer_size) {
+ HwasanTSDThreadInit(); // Only needed with interceptors.
+ uptr *ThreadLong = GetCurrentThreadLongPtr();
+ // The following implicitly sets (this) as the current thread.
+ stack_allocations_ = new (ThreadLong)
+ StackAllocationsRingBuffer((void *)stack_buffer_start, stack_buffer_size);
+ // Check that it worked.
+ CHECK_EQ(GetCurrentThread(), this);
+
+ // ScopedTaggingDisable needs GetCurrentThread to be set up.
+ ScopedTaggingDisabler disabler;
+
+ if (stack_bottom_) {
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+ CHECK(MemIsApp(stack_bottom_));
+ CHECK(MemIsApp(stack_top_ - 1));
+ }
+
+ if (flags()->verbose_threads) {
+ if (IsMainThread()) {
+ Printf("sizeof(Thread): %zd sizeof(HeapRB): %zd sizeof(StackRB): %zd\n",
+ sizeof(Thread), heap_allocations_->SizeInBytes(),
+ stack_allocations_->size() * sizeof(uptr));
+ }
+ Print("Creating : ");
+ }
+}
+
+void Thread::ClearShadowForThreadStackAndTLS() {
+ if (stack_top_ != stack_bottom_)
+ TagMemory(stack_bottom_, stack_top_ - stack_bottom_, 0);
+ if (tls_begin_ != tls_end_)
+ TagMemory(tls_begin_, tls_end_ - tls_begin_, 0);
+}
+
+void Thread::Destroy() {
+ if (flags()->verbose_threads)
+ Print("Destroying: ");
+ AllocatorSwallowThreadLocalCache(allocator_cache());
+ ClearShadowForThreadStackAndTLS();
+ if (heap_allocations_)
+ heap_allocations_->Delete();
+ DTLS_Destroy();
+ // Unregister this as the current thread.
+ // Instrumented code can not run on this thread from this point onwards, but
+ // malloc/free can still be served. Glibc may call free() very late, after all
+ // TSD destructors are done.
+ CHECK_EQ(GetCurrentThread(), this);
+ *GetCurrentThreadLongPtr() = 0;
+}
+
+void Thread::Print(const char *Prefix) {
+ Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix, unique_id_,
+ (void *)this, stack_bottom(), stack_top(),
+ stack_top() - stack_bottom(), tls_begin(), tls_end());
+}
+
+static u32 xorshift(u32 state) {
+ state ^= state << 13;
+ state ^= state >> 17;
+ state ^= state << 5;
+ return state;
+}
+
+// Generate a (pseudo-)random non-zero tag.
+tag_t Thread::GenerateRandomTag(uptr num_bits) {
+ DCHECK_GT(num_bits, 0);
+ if (tagging_disabled_)
+ return 0;
+ tag_t tag;
+ const uptr tag_mask = (1ULL << num_bits) - 1;
+ do {
+ if (flags()->random_tags) {
+ if (!random_buffer_) {
+ EnsureRandomStateInited();
+ random_buffer_ = random_state_ = xorshift(random_state_);
+ }
+ CHECK(random_buffer_);
+ tag = random_buffer_ & tag_mask;
+ random_buffer_ >>= num_bits;
+ } else {
+ EnsureRandomStateInited();
+ random_state_ += 1;
+ tag = random_state_ & tag_mask;
+ }
+ } while (!tag);
+ return tag;
+}
+
+} // namespace __hwasan