]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/hwasan/hwasan_thread.cc
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / hwasan / hwasan_thread.cc
1
2 #include "hwasan.h"
3 #include "hwasan_mapping.h"
4 #include "hwasan_thread.h"
5 #include "hwasan_poisoning.h"
6 #include "hwasan_interface_internal.h"
7
8 #include "sanitizer_common/sanitizer_file.h"
9 #include "sanitizer_common/sanitizer_placement_new.h"
10 #include "sanitizer_common/sanitizer_tls_get_addr.h"
11
12
13 namespace __hwasan {
14
15 static u32 RandomSeed() {
16   u32 seed;
17   do {
18     if (UNLIKELY(!GetRandom(reinterpret_cast<void *>(&seed), sizeof(seed),
19                             /*blocking=*/false))) {
20       seed = static_cast<u32>(
21           (NanoTime() >> 12) ^
22           (reinterpret_cast<uptr>(__builtin_frame_address(0)) >> 4));
23     }
24   } while (!seed);
25   return seed;
26 }
27
28 void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size) {
29   static u64 unique_id;
30   unique_id_ = unique_id++;
31   random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
32   if (auto sz = flags()->heap_history_size)
33     heap_allocations_ = HeapAllocationsRingBuffer::New(sz);
34
35   HwasanTSDThreadInit();  // Only needed with interceptors.
36   uptr *ThreadLong = GetCurrentThreadLongPtr();
37   // The following implicitly sets (this) as the current thread.
38   stack_allocations_ = new (ThreadLong)
39       StackAllocationsRingBuffer((void *)stack_buffer_start, stack_buffer_size);
40   // Check that it worked.
41   CHECK_EQ(GetCurrentThread(), this);
42
43   // ScopedTaggingDisable needs GetCurrentThread to be set up.
44   ScopedTaggingDisabler disabler;
45
46   uptr tls_size;
47   uptr stack_size;
48   GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size, &tls_begin_,
49                        &tls_size);
50   stack_top_ = stack_bottom_ + stack_size;
51   tls_end_ = tls_begin_ + tls_size;
52
53   if (stack_bottom_) {
54     int local;
55     CHECK(AddrIsInStack((uptr)&local));
56     CHECK(MemIsApp(stack_bottom_));
57     CHECK(MemIsApp(stack_top_ - 1));
58   }
59
60   if (flags()->verbose_threads) {
61     if (IsMainThread()) {
62       Printf("sizeof(Thread): %zd sizeof(HeapRB): %zd sizeof(StackRB): %zd\n",
63              sizeof(Thread), heap_allocations_->SizeInBytes(),
64              stack_allocations_->size() * sizeof(uptr));
65     }
66     Print("Creating  : ");
67   }
68 }
69
70 void Thread::ClearShadowForThreadStackAndTLS() {
71   if (stack_top_ != stack_bottom_)
72     TagMemory(stack_bottom_, stack_top_ - stack_bottom_, 0);
73   if (tls_begin_ != tls_end_)
74     TagMemory(tls_begin_, tls_end_ - tls_begin_, 0);
75 }
76
77 void Thread::Destroy() {
78   if (flags()->verbose_threads)
79     Print("Destroying: ");
80   AllocatorSwallowThreadLocalCache(allocator_cache());
81   ClearShadowForThreadStackAndTLS();
82   if (heap_allocations_)
83     heap_allocations_->Delete();
84   DTLS_Destroy();
85 }
86
87 void Thread::Print(const char *Prefix) {
88   Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix,
89          unique_id_, this, stack_bottom(), stack_top(),
90          stack_top() - stack_bottom(),
91          tls_begin(), tls_end());
92 }
93
94 static u32 xorshift(u32 state) {
95   state ^= state << 13;
96   state ^= state >> 17;
97   state ^= state << 5;
98   return state;
99 }
100
101 // Generate a (pseudo-)random non-zero tag.
102 tag_t Thread::GenerateRandomTag() {
103   if (tagging_disabled_) return 0;
104   tag_t tag;
105   do {
106     if (flags()->random_tags) {
107       if (!random_buffer_)
108         random_buffer_ = random_state_ = xorshift(random_state_);
109       CHECK(random_buffer_);
110       tag = random_buffer_ & 0xFF;
111       random_buffer_ >>= 8;
112     } else {
113       tag = random_state_ = (random_state_ + 1) & 0xFF;
114     }
115   } while (!tag);
116   return tag;
117 }
118
119 } // namespace __hwasan