1 //===-- hwasan_thread.h -----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of HWAddressSanitizer. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef HWASAN_THREAD_H 14 #define HWASAN_THREAD_H 15 16 #include "hwasan_allocator.h" 17 #include "sanitizer_common/sanitizer_common.h" 18 #include "sanitizer_common/sanitizer_ring_buffer.h" 19 20 namespace __hwasan { 21 22 typedef __sanitizer::CompactRingBuffer<uptr> StackAllocationsRingBuffer; 23 24 class Thread { 25 public: 26 // These are optional parameters that can be passed to Init. 27 struct InitState; 28 29 void Init(uptr stack_buffer_start, uptr stack_buffer_size, 30 const InitState *state = nullptr); 31 32 void InitStackAndTls(const InitState *state = nullptr); 33 34 // Must be called from the thread itself. 35 void InitStackRingBuffer(uptr stack_buffer_start, uptr stack_buffer_size); 36 37 inline void EnsureRandomStateInited() { 38 if (UNLIKELY(!random_state_inited_)) 39 InitRandomState(); 40 } 41 42 void Destroy(); 43 44 uptr stack_top() { return stack_top_; } 45 uptr stack_bottom() { return stack_bottom_; } 46 uptr stack_size() { return stack_top() - stack_bottom(); } 47 uptr tls_begin() { return tls_begin_; } 48 uptr tls_end() { return tls_end_; } 49 bool IsMainThread() { return unique_id_ == 0; } 50 51 bool AddrIsInStack(uptr addr) { 52 return addr >= stack_bottom_ && addr < stack_top_; 53 } 54 55 AllocatorCache *allocator_cache() { return &allocator_cache_; } 56 HeapAllocationsRingBuffer *heap_allocations() { return heap_allocations_; } 57 StackAllocationsRingBuffer *stack_allocations() { return stack_allocations_; } 58 59 tag_t GenerateRandomTag(uptr num_bits = kTagBits); 60 61 void DisableTagging() { tagging_disabled_++; } 62 void EnableTagging() { tagging_disabled_--; } 63 64 u64 unique_id() const { return unique_id_; } 65 void Announce() { 66 if (announced_) return; 67 announced_ = true; 68 Print("Thread: "); 69 } 70 71 uptr &vfork_spill() { return vfork_spill_; } 72 73 private: 74 // NOTE: There is no Thread constructor. It is allocated 75 // via mmap() and *must* be valid in zero-initialized state. 76 void ClearShadowForThreadStackAndTLS(); 77 void Print(const char *prefix); 78 void InitRandomState(); 79 uptr vfork_spill_; 80 uptr stack_top_; 81 uptr stack_bottom_; 82 uptr tls_begin_; 83 uptr tls_end_; 84 85 u32 random_state_; 86 u32 random_buffer_; 87 88 AllocatorCache allocator_cache_; 89 HeapAllocationsRingBuffer *heap_allocations_; 90 StackAllocationsRingBuffer *stack_allocations_; 91 92 u64 unique_id_; // counting from zero. 93 94 u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread. 95 96 bool announced_; 97 98 bool random_state_inited_; // Whether InitRandomState() has been called. 99 100 friend struct ThreadListHead; 101 }; 102 103 Thread *GetCurrentThread(); 104 uptr *GetCurrentThreadLongPtr(); 105 106 struct ScopedTaggingDisabler { 107 ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); } 108 ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); } 109 }; 110 111 } // namespace __hwasan 112 113 #endif // HWASAN_THREAD_H 114