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