13cab2bb3Spatrick //===-- hwasan_thread.h -----------------------------------------*- C++ -*-===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // 93cab2bb3Spatrick // This file is a part of HWAddressSanitizer. 103cab2bb3Spatrick // 113cab2bb3Spatrick //===----------------------------------------------------------------------===// 123cab2bb3Spatrick 133cab2bb3Spatrick #ifndef HWASAN_THREAD_H 143cab2bb3Spatrick #define HWASAN_THREAD_H 153cab2bb3Spatrick 163cab2bb3Spatrick #include "hwasan_allocator.h" 173cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h" 183cab2bb3Spatrick #include "sanitizer_common/sanitizer_ring_buffer.h" 193cab2bb3Spatrick 203cab2bb3Spatrick namespace __hwasan { 213cab2bb3Spatrick 223cab2bb3Spatrick typedef __sanitizer::CompactRingBuffer<uptr> StackAllocationsRingBuffer; 233cab2bb3Spatrick 243cab2bb3Spatrick class Thread { 253cab2bb3Spatrick public: 26d89ec533Spatrick // These are optional parameters that can be passed to Init. 27d89ec533Spatrick struct InitState; 28d89ec533Spatrick 29d89ec533Spatrick void Init(uptr stack_buffer_start, uptr stack_buffer_size, 30d89ec533Spatrick const InitState *state = nullptr); 31*810390e3Srobert 32d89ec533Spatrick void InitStackAndTls(const InitState *state = nullptr); 33d89ec533Spatrick 34d89ec533Spatrick // Must be called from the thread itself. 35d89ec533Spatrick void InitStackRingBuffer(uptr stack_buffer_start, uptr stack_buffer_size); 36d89ec533Spatrick EnsureRandomStateInited()37*810390e3Srobert inline void EnsureRandomStateInited() { 38*810390e3Srobert if (UNLIKELY(!random_state_inited_)) 39*810390e3Srobert InitRandomState(); 40*810390e3Srobert } 41*810390e3Srobert 423cab2bb3Spatrick void Destroy(); 433cab2bb3Spatrick stack_top()443cab2bb3Spatrick uptr stack_top() { return stack_top_; } stack_bottom()453cab2bb3Spatrick uptr stack_bottom() { return stack_bottom_; } stack_size()463cab2bb3Spatrick uptr stack_size() { return stack_top() - stack_bottom(); } tls_begin()473cab2bb3Spatrick uptr tls_begin() { return tls_begin_; } tls_end()483cab2bb3Spatrick uptr tls_end() { return tls_end_; } dtls()49*810390e3Srobert DTLS *dtls() { return dtls_; } IsMainThread()503cab2bb3Spatrick bool IsMainThread() { return unique_id_ == 0; } 513cab2bb3Spatrick AddrIsInStack(uptr addr)523cab2bb3Spatrick bool AddrIsInStack(uptr addr) { 533cab2bb3Spatrick return addr >= stack_bottom_ && addr < stack_top_; 543cab2bb3Spatrick } 553cab2bb3Spatrick allocator_cache()563cab2bb3Spatrick AllocatorCache *allocator_cache() { return &allocator_cache_; } heap_allocations()573cab2bb3Spatrick HeapAllocationsRingBuffer *heap_allocations() { return heap_allocations_; } stack_allocations()583cab2bb3Spatrick StackAllocationsRingBuffer *stack_allocations() { return stack_allocations_; } 593cab2bb3Spatrick 60d89ec533Spatrick tag_t GenerateRandomTag(uptr num_bits = kTagBits); 613cab2bb3Spatrick DisableTagging()623cab2bb3Spatrick void DisableTagging() { tagging_disabled_++; } EnableTagging()633cab2bb3Spatrick void EnableTagging() { tagging_disabled_--; } 643cab2bb3Spatrick unique_id()65*810390e3Srobert u32 unique_id() const { return unique_id_; } Announce()663cab2bb3Spatrick void Announce() { 673cab2bb3Spatrick if (announced_) return; 683cab2bb3Spatrick announced_ = true; 693cab2bb3Spatrick Print("Thread: "); 703cab2bb3Spatrick } 713cab2bb3Spatrick os_id()72*810390e3Srobert tid_t os_id() const { return os_id_; } set_os_id(tid_t os_id)73*810390e3Srobert void set_os_id(tid_t os_id) { os_id_ = os_id; } 74*810390e3Srobert vfork_spill()753cab2bb3Spatrick uptr &vfork_spill() { return vfork_spill_; } 763cab2bb3Spatrick 773cab2bb3Spatrick private: 783cab2bb3Spatrick // NOTE: There is no Thread constructor. It is allocated 793cab2bb3Spatrick // via mmap() and *must* be valid in zero-initialized state. 803cab2bb3Spatrick void ClearShadowForThreadStackAndTLS(); 813cab2bb3Spatrick void Print(const char *prefix); 82*810390e3Srobert void InitRandomState(); 833cab2bb3Spatrick uptr vfork_spill_; 843cab2bb3Spatrick uptr stack_top_; 853cab2bb3Spatrick uptr stack_bottom_; 863cab2bb3Spatrick uptr tls_begin_; 873cab2bb3Spatrick uptr tls_end_; 88*810390e3Srobert DTLS *dtls_; 893cab2bb3Spatrick 903cab2bb3Spatrick u32 random_state_; 913cab2bb3Spatrick u32 random_buffer_; 923cab2bb3Spatrick 933cab2bb3Spatrick AllocatorCache allocator_cache_; 943cab2bb3Spatrick HeapAllocationsRingBuffer *heap_allocations_; 953cab2bb3Spatrick StackAllocationsRingBuffer *stack_allocations_; 963cab2bb3Spatrick 97*810390e3Srobert u32 unique_id_; // counting from zero. 98*810390e3Srobert 99*810390e3Srobert tid_t os_id_; 1003cab2bb3Spatrick 1013cab2bb3Spatrick u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread. 1023cab2bb3Spatrick 1033cab2bb3Spatrick bool announced_; 1043cab2bb3Spatrick 105*810390e3Srobert bool random_state_inited_; // Whether InitRandomState() has been called. 106*810390e3Srobert 1073cab2bb3Spatrick friend struct ThreadListHead; 1083cab2bb3Spatrick }; 1093cab2bb3Spatrick 1103cab2bb3Spatrick Thread *GetCurrentThread(); 1113cab2bb3Spatrick uptr *GetCurrentThreadLongPtr(); 1123cab2bb3Spatrick 1133cab2bb3Spatrick struct ScopedTaggingDisabler { ScopedTaggingDisablerScopedTaggingDisabler1143cab2bb3Spatrick ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); } ~ScopedTaggingDisablerScopedTaggingDisabler1153cab2bb3Spatrick ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); } 1163cab2bb3Spatrick }; 1173cab2bb3Spatrick 1183cab2bb3Spatrick } // namespace __hwasan 1193cab2bb3Spatrick 1203cab2bb3Spatrick #endif // HWASAN_THREAD_H 121