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
20namespace __hwasan {
21
22typedef __sanitizer::CompactRingBuffer<uptr> StackAllocationsRingBuffer;
23
24class 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
102Thread *GetCurrentThread();
103uptr *GetCurrentThreadLongPtr();
104
105struct ScopedTaggingDisabler {
106  ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); }
107  ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); }
108};
109
110} // namespace __hwasan
111
112#endif // HWASAN_THREAD_H
113