xref: /openbsd-src/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
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