140 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of HWAddressSanitizer.10//11//===----------------------------------------------------------------------===//12 13#ifndef HWASAN_THREAD_H14#define HWASAN_THREAD_H15 16#include "hwasan_allocator.h"17#include "sanitizer_common/sanitizer_common.h"18#include "sanitizer_common/sanitizer_ring_buffer.h"19 20namespace __hwasan {21 22typedef __sanitizer::CompactRingBuffer<uptr> StackAllocationsRingBuffer;23 24class 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();45 uptr stack_bottom();46 uptr stack_size();47 uptr tls_begin() { return tls_begin_; }48 uptr tls_end() { return tls_end_; }49 DTLS *dtls() { return dtls_; }50 bool IsMainThread() { return unique_id_ == 0; }51 52 bool AddrIsInStack(uptr addr) {53 return addr >= stack_bottom_ && addr < stack_top_;54 }55 56 void StartSwitchFiber(uptr bottom, uptr size);57 void FinishSwitchFiber(uptr *bottom_old, uptr *size_old);58 59 AllocatorCache *allocator_cache() { return &allocator_cache_; }60 HeapAllocationsRingBuffer *heap_allocations() { return heap_allocations_; }61 StackAllocationsRingBuffer *stack_allocations() { return stack_allocations_; }62 63 tag_t GenerateRandomTag(uptr num_bits = kTagBits);64 65 void DisableTagging() { tagging_disabled_++; }66 void EnableTagging() { tagging_disabled_--; }67 68 u32 unique_id() const { return unique_id_; }69 void Announce() {70 if (announced_) return;71 announced_ = true;72 Print("Thread: ");73 }74 75 ThreadID os_id() const { return os_id_; }76 void set_os_id(ThreadID os_id) { os_id_ = os_id; }77 78 uptr &vfork_spill() { return vfork_spill_; }79 80 private:81 // NOTE: There is no Thread constructor. It is allocated82 // via mmap() and *must* be valid in zero-initialized state.83 void ClearShadowForThreadStackAndTLS();84 void Print(const char *prefix);85 void InitRandomState();86 87 struct StackBounds {88 uptr bottom;89 uptr top;90 };91 StackBounds GetStackBounds() const;92 93 uptr vfork_spill_;94 uptr stack_top_;95 uptr stack_bottom_;96 // these variables are used when the thread is about to switch stack97 uptr next_stack_top_;98 uptr next_stack_bottom_;99 // true if switching is in progress100 atomic_uint8_t stack_switching_;101 102 uptr tls_begin_;103 uptr tls_end_;104 DTLS *dtls_;105 106 u32 random_state_;107 u32 random_buffer_;108 109 AllocatorCache allocator_cache_;110 HeapAllocationsRingBuffer *heap_allocations_;111 StackAllocationsRingBuffer *stack_allocations_;112 113 u32 unique_id_; // counting from zero.114 115 ThreadID os_id_;116 117 u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread.118 119 bool announced_;120 121 bool random_state_inited_; // Whether InitRandomState() has been called.122 123 friend struct ThreadListHead;124};125 126Thread *GetCurrentThread();127uptr *GetCurrentThreadLongPtr();128 129// Used to handle fork().130void EnsureMainThreadIDIsCorrect();131 132struct ScopedTaggingDisabler {133 ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); }134 ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); }135};136 137} // namespace __hwasan138 139#endif // HWASAN_THREAD_H140