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 void Init(uptr stack_buffer_start, uptr stack_buffer_size); // Must be called from the thread itself. 27 void InitRandomState(); 28 void Destroy(); 29 30 uptr stack_top() { return stack_top_; } 31 uptr stack_bottom() { return stack_bottom_; } 32 uptr stack_size() { return stack_top() - stack_bottom(); } 33 uptr tls_begin() { return tls_begin_; } 34 uptr tls_end() { return tls_end_; } 35 bool IsMainThread() { return unique_id_ == 0; } 36 37 bool AddrIsInStack(uptr addr) { 38 return addr >= stack_bottom_ && addr < stack_top_; 39 } 40 41 bool InSignalHandler() { return in_signal_handler_; } 42 void EnterSignalHandler() { in_signal_handler_++; } 43 void LeaveSignalHandler() { in_signal_handler_--; } 44 45 bool InSymbolizer() { return in_symbolizer_; } 46 void EnterSymbolizer() { in_symbolizer_++; } 47 void LeaveSymbolizer() { in_symbolizer_--; } 48 49 AllocatorCache *allocator_cache() { return &allocator_cache_; } 50 HeapAllocationsRingBuffer *heap_allocations() { return heap_allocations_; } 51 StackAllocationsRingBuffer *stack_allocations() { return stack_allocations_; } 52 53 tag_t GenerateRandomTag(); 54 55 void DisableTagging() { tagging_disabled_++; } 56 void EnableTagging() { tagging_disabled_--; } 57 bool TaggingIsDisabled() const { return 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 unsigned in_signal_handler_; 80 unsigned in_symbolizer_; 81 82 u32 random_state_; 83 u32 random_buffer_; 84 85 AllocatorCache allocator_cache_; 86 HeapAllocationsRingBuffer *heap_allocations_; 87 StackAllocationsRingBuffer *stack_allocations_; 88 89 static void InsertIntoThreadList(Thread *t); 90 static void RemoveFromThreadList(Thread *t); 91 Thread *next_; // All live threads form a linked list. 92 93 u64 unique_id_; // counting from zero. 94 95 u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread. 96 97 bool announced_; 98 99 friend struct ThreadListHead; 100 }; 101 102 Thread *GetCurrentThread(); 103 uptr *GetCurrentThreadLongPtr(); 104 105 struct ScopedTaggingDisabler { 106 ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); } 107 ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); } 108 }; 109 110 } // namespace __hwasan 111 112 #endif // HWASAN_THREAD_H 113