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 void InitRandomState(); 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 void Destroy(); 38 39 uptr stack_top() { return stack_top_; } 40 uptr stack_bottom() { return stack_bottom_; } 41 uptr stack_size() { return stack_top() - stack_bottom(); } 42 uptr tls_begin() { return tls_begin_; } 43 uptr tls_end() { return tls_end_; } 44 bool IsMainThread() { return unique_id_ == 0; } 45 46 bool AddrIsInStack(uptr addr) { 47 return addr >= stack_bottom_ && addr < stack_top_; 48 } 49 50 AllocatorCache *allocator_cache() { return &allocator_cache_; } 51 HeapAllocationsRingBuffer *heap_allocations() { return heap_allocations_; } 52 StackAllocationsRingBuffer *stack_allocations() { return stack_allocations_; } 53 54 tag_t GenerateRandomTag(uptr num_bits = kTagBits); 55 56 void DisableTagging() { tagging_disabled_++; } 57 void EnableTagging() { tagging_disabled_--; } 58 59 u64 unique_id() const { return unique_id_; } 60 void Announce() { 61 if (announced_) return; 62 announced_ = true; 63 Print("Thread: "); 64 } 65 66 uptr &vfork_spill() { return vfork_spill_; } 67 68 private: 69 // NOTE: There is no Thread constructor. It is allocated 70 // via mmap() and *must* be valid in zero-initialized state. 71 void ClearShadowForThreadStackAndTLS(); 72 void Print(const char *prefix); 73 uptr vfork_spill_; 74 uptr stack_top_; 75 uptr stack_bottom_; 76 uptr tls_begin_; 77 uptr tls_end_; 78 79 u32 random_state_; 80 u32 random_buffer_; 81 82 AllocatorCache allocator_cache_; 83 HeapAllocationsRingBuffer *heap_allocations_; 84 StackAllocationsRingBuffer *stack_allocations_; 85 86 u64 unique_id_; // counting from zero. 87 88 u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread. 89 90 bool announced_; 91 92 friend struct ThreadListHead; 93 }; 94 95 Thread *GetCurrentThread(); 96 uptr *GetCurrentThreadLongPtr(); 97 98 struct ScopedTaggingDisabler { 99 ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); } 100 ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); } 101 }; 102 103 } // namespace __hwasan 104 105 #endif // HWASAN_THREAD_H 106