blob: a84c855aca7e9b818470fe036b32e2f5d548180f [file] [log] [blame]
Kostya Serebryany1e172b42011-11-30 01:07:02 +00001//===-- asan_thread.h -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// ASan-private header for asan_thread.cc.
13//===----------------------------------------------------------------------===//
14#ifndef ASAN_THREAD_H
15#define ASAN_THREAD_H
16
17#include "asan_allocator.h"
18#include "asan_internal.h"
Kostya Serebryany244384d2013-04-11 11:39:19 +000019#include "asan_fake_stack.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000020#include "asan_stats.h"
Sergey Matveeve86e35f2013-10-14 12:01:05 +000021#include "sanitizer_common/sanitizer_common.h"
Kostya Serebryanyb134ffa2012-07-17 07:20:13 +000022#include "sanitizer_common/sanitizer_libc.h"
Alexey Samsonovdef1be92013-03-21 11:23:41 +000023#include "sanitizer_common/sanitizer_thread_registry.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000024
25namespace __asan {
26
Kostya Serebryanye0cff0b2012-06-06 15:06:58 +000027const u32 kInvalidTid = 0xffffff; // Must fit into 24 bits.
Alexey Samsonovdef1be92013-03-21 11:23:41 +000028const u32 kMaxNumberOfThreads = (1 << 22); // 4M
Kostya Serebryanye0cff0b2012-06-06 15:06:58 +000029
Kostya Serebryany1e172b42011-11-30 01:07:02 +000030class AsanThread;
31
32// These objects are created for every thread and are never deleted,
33// so we can find them by tid even if the thread is long dead.
Alexey Samsonovdef1be92013-03-21 11:23:41 +000034class AsanThreadContext : public ThreadContextBase {
Kostya Serebryany1e172b42011-11-30 01:07:02 +000035 public:
Alexey Samsonovdef1be92013-03-21 11:23:41 +000036 explicit AsanThreadContext(int tid)
37 : ThreadContextBase(tid),
38 announced(false),
Sergey Matveeve86e35f2013-10-14 12:01:05 +000039 destructor_iterations(kPthreadDestructorIterations),
Kostya Serebryany6d958692013-10-18 14:50:44 +000040 stack_id(0),
Alexey Samsonovdef1be92013-03-21 11:23:41 +000041 thread(0) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +000042 }
Alexey Samsonovdef1be92013-03-21 11:23:41 +000043 bool announced;
Kostya Serebryany6d958692013-10-18 14:50:44 +000044 u8 destructor_iterations;
45 u32 stack_id;
Alexey Samsonovdef1be92013-03-21 11:23:41 +000046 AsanThread *thread;
Kostya Serebryanyf58f9982012-02-07 00:27:15 +000047
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070048 void OnCreated(void *arg) override;
49 void OnFinished() override;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000050};
51
Alexey Samsonovdef1be92013-03-21 11:23:41 +000052// AsanThreadContext objects are never freed, so we need many of them.
Kostya Serebryany6d958692013-10-18 14:50:44 +000053COMPILER_CHECK(sizeof(AsanThreadContext) <= 256);
Kostya Serebryany716e2f22012-12-07 15:15:01 +000054
Kostya Serebryany1e172b42011-11-30 01:07:02 +000055// AsanThread are stored in TSD and destroyed when the thread dies.
56class AsanThread {
57 public:
Stephen Hines86277eb2015-03-23 12:06:32 -070058 static AsanThread *Create(thread_callback_t start_routine, void *arg,
59 u32 parent_tid, StackTrace *stack, bool detached);
Alexey Samsonovdef1be92013-03-21 11:23:41 +000060 static void TSDDtor(void *tsd);
Kostya Serebryanya6b52262012-01-06 19:44:11 +000061 void Destroy();
Kostya Serebryany1e172b42011-11-30 01:07:02 +000062
Kostya Serebryany69eca732011-12-16 19:13:35 +000063 void Init(); // Should be called from the thread itself.
Stephen Hines86277eb2015-03-23 12:06:32 -070064 thread_return_t ThreadStart(uptr os_id,
65 atomic_uintptr_t *signal_thread_is_registered);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000066
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000067 uptr stack_top() { return stack_top_; }
68 uptr stack_bottom() { return stack_bottom_; }
Kostya Serebryany621770a2013-09-19 14:59:52 +000069 uptr stack_size() { return stack_size_; }
Sergey Matveev12d01ba2013-05-29 13:09:44 +000070 uptr tls_begin() { return tls_begin_; }
71 uptr tls_end() { return tls_end_; }
Alexey Samsonovdef1be92013-03-21 11:23:41 +000072 u32 tid() { return context_->tid; }
73 AsanThreadContext *context() { return context_; }
74 void set_context(AsanThreadContext *context) { context_ = context; }
Kostya Serebryany1e172b42011-11-30 01:07:02 +000075
Stephen Hines6d186232014-11-26 17:56:19 -080076 struct StackFrameAccess {
77 uptr offset;
78 uptr frame_pc;
79 const char *frame_descr;
80 };
81 bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000082
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000083 bool AddrIsInStack(uptr addr) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +000084 return addr >= stack_bottom_ && addr < stack_top_;
85 }
86
Stephen Hines2d1fdb22014-05-28 23:58:16 -070087 void DeleteFakeStack(int tid) {
Kostya Serebryany7a0bba42013-06-26 12:16:05 +000088 if (!fake_stack_) return;
Kostya Serebryany9433af32013-09-13 06:32:26 +000089 FakeStack *t = fake_stack_;
90 fake_stack_ = 0;
91 SetTLSFakeStack(0);
Stephen Hines2d1fdb22014-05-28 23:58:16 -070092 t->Destroy(tid);
Kostya Serebryany7a0bba42013-06-26 12:16:05 +000093 }
Kostya Serebryanyac3ae5d2013-09-12 07:11:58 +000094
Kostya Serebryanydcf98bf2013-09-12 08:43:44 +000095 bool has_fake_stack() {
96 return (reinterpret_cast<uptr>(fake_stack_) > 1);
97 }
98
Kostya Serebryanyac3ae5d2013-09-12 07:11:58 +000099 FakeStack *fake_stack() {
Kostya Serebryany230e52f2013-09-18 10:35:12 +0000100 if (!__asan_option_detect_stack_use_after_return)
101 return 0;
Kostya Serebryanydcf98bf2013-09-12 08:43:44 +0000102 if (!has_fake_stack())
Kostya Serebryanyc98fc1f2013-09-12 08:34:50 +0000103 return AsyncSignalSafeLazyInitFakeStack();
Kostya Serebryanyac3ae5d2013-09-12 07:11:58 +0000104 return fake_stack_;
105 }
Kostya Serebryany7a0bba42013-06-26 12:16:05 +0000106
Evgeniy Stepanov96a575f2013-09-12 08:16:28 +0000107 // True is this thread is currently unwinding stack (i.e. collecting a stack
108 // trace). Used to prevent deadlocks on platforms where libc unwinder calls
109 // malloc internally. See PR17116 for more details.
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700110 bool isUnwinding() const { return unwinding_; }
111 void setUnwinding(bool b) { unwinding_ = b; }
Evgeniy Stepanov96a575f2013-09-12 08:16:28 +0000112
Stephen Hines6d186232014-11-26 17:56:19 -0800113 // True if we are in a deadly signal handler.
114 bool isInDeadlySignal() const { return in_deadly_signal_; }
115 void setInDeadlySignal(bool b) { in_deadly_signal_ = b; }
116
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000117 AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
118 AsanStats &stats() { return stats_; }
119
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000120 private:
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700121 // NOTE: There is no AsanThread constructor. It is allocated
122 // via mmap() and *must* be valid in zero-initialized state.
Sergey Matveev12d01ba2013-05-29 13:09:44 +0000123 void SetThreadStackAndTls();
124 void ClearShadowForThreadStackAndTLS();
Kostya Serebryanyc98fc1f2013-09-12 08:34:50 +0000125 FakeStack *AsyncSignalSafeLazyInitFakeStack();
126
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000127 AsanThreadContext *context_;
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000128 thread_callback_t start_routine_;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000129 void *arg_;
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700130 uptr stack_top_;
131 uptr stack_bottom_;
Kostya Serebryany621770a2013-09-19 14:59:52 +0000132 // stack_size_ == stack_top_ - stack_bottom_;
133 // It needs to be set in a async-signal-safe manner.
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700134 uptr stack_size_;
Sergey Matveev12d01ba2013-05-29 13:09:44 +0000135 uptr tls_begin_;
136 uptr tls_end_;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000137
Kostya Serebryany7a0bba42013-06-26 12:16:05 +0000138 FakeStack *fake_stack_;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000139 AsanThreadLocalMallocStorage malloc_storage_;
140 AsanStats stats_;
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700141 bool unwinding_;
Stephen Hines6d186232014-11-26 17:56:19 -0800142 bool in_deadly_signal_;
Evgeniy Stepanov96a575f2013-09-12 08:16:28 +0000143};
144
145// ScopedUnwinding is a scope for stacktracing member of a context
146class ScopedUnwinding {
147 public:
148 explicit ScopedUnwinding(AsanThread *t) : thread(t) {
149 t->setUnwinding(true);
150 }
151 ~ScopedUnwinding() { thread->setUnwinding(false); }
152
153 private:
154 AsanThread *thread;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000155};
156
Stephen Hines6d186232014-11-26 17:56:19 -0800157// ScopedDeadlySignal is a scope for handling deadly signals.
158class ScopedDeadlySignal {
159 public:
160 explicit ScopedDeadlySignal(AsanThread *t) : thread(t) {
161 if (thread) thread->setInDeadlySignal(true);
162 }
163 ~ScopedDeadlySignal() {
164 if (thread) thread->setInDeadlySignal(false);
165 }
166
167 private:
168 AsanThread *thread;
169};
170
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000171// Returns a single instance of registry.
172ThreadRegistry &asanThreadRegistry();
173
174// Must be called under ThreadRegistryLock.
175AsanThreadContext *GetThreadContextByTidLocked(u32 tid);
176
Alexey Samsonov89c13842013-03-20 09:23:28 +0000177// Get the current thread. May return 0.
178AsanThread *GetCurrentThread();
179void SetCurrentThread(AsanThread *t);
180u32 GetCurrentTidOrInvalid();
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000181AsanThread *FindThreadByStackAddress(uptr addr);
Alexey Samsonov89c13842013-03-20 09:23:28 +0000182
Sergey Matveevc6ac98d2013-07-08 12:57:24 +0000183// Used to handle fork().
184void EnsureMainThreadIDIsCorrect();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000185} // namespace __asan
186
187#endif // ASAN_THREAD_H