blob: a17a7b4dd70a75872770ccaf0192203a22b91bf5 [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_stack.h"
21#include "asan_stats.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),
39 thread(0) {
40 internal_memset(&stack, 0, sizeof(stack));
Kostya Serebryany1e172b42011-11-30 01:07:02 +000041 }
Alexey Samsonovdef1be92013-03-21 11:23:41 +000042 bool announced;
43 StackTrace stack;
44 AsanThread *thread;
Kostya Serebryanyf58f9982012-02-07 00:27:15 +000045
Alexey Samsonovdef1be92013-03-21 11:23:41 +000046 void OnCreated(void *arg);
47 void OnFinished();
Kostya Serebryany1e172b42011-11-30 01:07:02 +000048};
49
Alexey Samsonovdef1be92013-03-21 11:23:41 +000050// AsanThreadContext objects are never freed, so we need many of them.
51COMPILER_CHECK(sizeof(AsanThreadContext) <= 4096);
Kostya Serebryany716e2f22012-12-07 15:15:01 +000052
Kostya Serebryany1e172b42011-11-30 01:07:02 +000053// AsanThread are stored in TSD and destroyed when the thread dies.
54class AsanThread {
55 public:
Alexey Samsonovdef1be92013-03-21 11:23:41 +000056 static AsanThread *Create(thread_callback_t start_routine, void *arg);
57 static void TSDDtor(void *tsd);
Kostya Serebryanya6b52262012-01-06 19:44:11 +000058 void Destroy();
Kostya Serebryany1e172b42011-11-30 01:07:02 +000059
Kostya Serebryany69eca732011-12-16 19:13:35 +000060 void Init(); // Should be called from the thread itself.
Alexey Samsonovdef1be92013-03-21 11:23:41 +000061 thread_return_t ThreadStart(uptr os_id);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000062
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000063 uptr stack_top() { return stack_top_; }
64 uptr stack_bottom() { return stack_bottom_; }
65 uptr stack_size() { return stack_top_ - stack_bottom_; }
Sergey Matveev12d01ba2013-05-29 13:09:44 +000066 uptr tls_begin() { return tls_begin_; }
67 uptr tls_end() { return tls_end_; }
Alexey Samsonovdef1be92013-03-21 11:23:41 +000068 u32 tid() { return context_->tid; }
69 AsanThreadContext *context() { return context_; }
70 void set_context(AsanThreadContext *context) { context_ = context; }
Kostya Serebryany1e172b42011-11-30 01:07:02 +000071
Kostya Serebryany50f3daa2013-03-22 10:36:24 +000072 const char *GetFrameNameByAddr(uptr addr, uptr *offset, uptr *frame_pc);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000073
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000074 bool AddrIsInStack(uptr addr) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +000075 return addr >= stack_bottom_ && addr < stack_top_;
76 }
77
Kostya Serebryany7a0bba42013-06-26 12:16:05 +000078 void DeleteFakeStack() {
79 if (!fake_stack_) return;
Kostya Serebryanyac3ae5d2013-09-12 07:11:58 +000080 fake_stack_->PoisonAll(0);
81 fake_stack_->Destroy();
Kostya Serebryany7a0bba42013-06-26 12:16:05 +000082 }
Kostya Serebryanyac3ae5d2013-09-12 07:11:58 +000083
84 FakeStack *fake_stack() {
85 if (!fake_stack_) // FIXME: lazy init is not async-signal safe.
86 fake_stack_ = FakeStack::Create(Log2(RoundUpToPowerOfTwo(stack_size())));
87 return fake_stack_;
88 }
Kostya Serebryany7a0bba42013-06-26 12:16:05 +000089
Evgeniy Stepanov96a575f2013-09-12 08:16:28 +000090 // True is this thread is currently unwinding stack (i.e. collecting a stack
91 // trace). Used to prevent deadlocks on platforms where libc unwinder calls
92 // malloc internally. See PR17116 for more details.
93 bool isUnwinding() const { return unwinding; }
94 void setUnwinding(bool b) { unwinding = b; }
95
Kostya Serebryany1e172b42011-11-30 01:07:02 +000096 AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
97 AsanStats &stats() { return stats_; }
98
Kostya Serebryany1e172b42011-11-30 01:07:02 +000099 private:
Evgeniy Stepanov96a575f2013-09-12 08:16:28 +0000100 AsanThread() : unwinding(false) {}
Sergey Matveev12d01ba2013-05-29 13:09:44 +0000101 void SetThreadStackAndTls();
102 void ClearShadowForThreadStackAndTLS();
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000103 AsanThreadContext *context_;
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000104 thread_callback_t start_routine_;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000105 void *arg_;
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000106 uptr stack_top_;
107 uptr stack_bottom_;
Sergey Matveev12d01ba2013-05-29 13:09:44 +0000108 uptr tls_begin_;
109 uptr tls_end_;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000110
Kostya Serebryany7a0bba42013-06-26 12:16:05 +0000111 FakeStack *fake_stack_;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000112 AsanThreadLocalMallocStorage malloc_storage_;
113 AsanStats stats_;
Evgeniy Stepanov96a575f2013-09-12 08:16:28 +0000114 bool unwinding;
115};
116
117// ScopedUnwinding is a scope for stacktracing member of a context
118class ScopedUnwinding {
119 public:
120 explicit ScopedUnwinding(AsanThread *t) : thread(t) {
121 t->setUnwinding(true);
122 }
123 ~ScopedUnwinding() { thread->setUnwinding(false); }
124
125 private:
126 AsanThread *thread;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000127};
128
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000129struct CreateThreadContextArgs {
130 AsanThread *thread;
131 StackTrace *stack;
132};
133
134// Returns a single instance of registry.
135ThreadRegistry &asanThreadRegistry();
136
137// Must be called under ThreadRegistryLock.
138AsanThreadContext *GetThreadContextByTidLocked(u32 tid);
139
Alexey Samsonov89c13842013-03-20 09:23:28 +0000140// Get the current thread. May return 0.
141AsanThread *GetCurrentThread();
142void SetCurrentThread(AsanThread *t);
143u32 GetCurrentTidOrInvalid();
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000144AsanThread *FindThreadByStackAddress(uptr addr);
Alexey Samsonov89c13842013-03-20 09:23:28 +0000145
Sergey Matveevc6ac98d2013-07-08 12:57:24 +0000146// Used to handle fork().
147void EnsureMainThreadIDIsCorrect();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000148} // namespace __asan
149
150#endif // ASAN_THREAD_H