Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 1 | //===-- 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" |
| 19 | #include "asan_stack.h" |
| 20 | #include "asan_stats.h" |
Kostya Serebryany | 78713bc | 2012-07-17 07:20:13 +0000 | [diff] [blame] | 21 | #include "sanitizer_common/sanitizer_libc.h" |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 22 | |
| 23 | namespace __asan { |
| 24 | |
Kostya Serebryany | 79437fe | 2012-06-06 15:06:58 +0000 | [diff] [blame] | 25 | const u32 kInvalidTid = 0xffffff; // Must fit into 24 bits. |
| 26 | |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 27 | class AsanThread; |
| 28 | |
| 29 | // These objects are created for every thread and are never deleted, |
| 30 | // so we can find them by tid even if the thread is long dead. |
| 31 | class AsanThreadSummary { |
| 32 | public: |
| 33 | explicit AsanThreadSummary(LinkerInitialized) { } // for T0. |
Kostya Serebryany | 6b0d775 | 2012-08-28 11:54:30 +0000 | [diff] [blame] | 34 | void Init(u32 parent_tid, StackTrace *stack) { |
Kostya Serebryany | 78713bc | 2012-07-17 07:20:13 +0000 | [diff] [blame] | 35 | parent_tid_ = parent_tid; |
| 36 | announced_ = false; |
Kostya Serebryany | 79437fe | 2012-06-06 15:06:58 +0000 | [diff] [blame] | 37 | tid_ = kInvalidTid; |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 38 | if (stack) { |
Kostya Serebryany | 78713bc | 2012-07-17 07:20:13 +0000 | [diff] [blame] | 39 | internal_memcpy(&stack_, stack, sizeof(*stack)); |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 40 | } |
| 41 | thread_ = 0; |
Kostya Serebryany | e710822 | 2012-12-07 15:15:01 +0000 | [diff] [blame] | 42 | name_[0] = 0; |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 43 | } |
Kostya Serebryany | 79437fe | 2012-06-06 15:06:58 +0000 | [diff] [blame] | 44 | u32 tid() { return tid_; } |
| 45 | void set_tid(u32 tid) { tid_ = tid; } |
Alexey Samsonov | c402cb6 | 2012-09-05 07:37:15 +0000 | [diff] [blame] | 46 | u32 parent_tid() { return parent_tid_; } |
| 47 | bool announced() { return announced_; } |
| 48 | void set_announced(bool announced) { announced_ = announced; } |
| 49 | StackTrace *stack() { return &stack_; } |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 50 | AsanThread *thread() { return thread_; } |
| 51 | void set_thread(AsanThread *thread) { thread_ = thread; } |
Kostya Serebryany | b5eb5a7 | 2012-02-07 00:27:15 +0000 | [diff] [blame] | 52 | static void TSDDtor(void *tsd); |
Kostya Serebryany | e710822 | 2012-12-07 15:15:01 +0000 | [diff] [blame] | 53 | void set_name(const char *name) { |
| 54 | internal_strncpy(name_, name, sizeof(name_) - 1); |
| 55 | } |
| 56 | const char *name() { return name_; } |
Kostya Serebryany | b5eb5a7 | 2012-02-07 00:27:15 +0000 | [diff] [blame] | 57 | |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 58 | private: |
Kostya Serebryany | 79437fe | 2012-06-06 15:06:58 +0000 | [diff] [blame] | 59 | u32 tid_; |
| 60 | u32 parent_tid_; |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 61 | bool announced_; |
Kostya Serebryany | 6b0d775 | 2012-08-28 11:54:30 +0000 | [diff] [blame] | 62 | StackTrace stack_; |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 63 | AsanThread *thread_; |
Kostya Serebryany | e710822 | 2012-12-07 15:15:01 +0000 | [diff] [blame] | 64 | char name_[128]; |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 65 | }; |
| 66 | |
Kostya Serebryany | e710822 | 2012-12-07 15:15:01 +0000 | [diff] [blame] | 67 | // AsanThreadSummary objects are never freed, so we need many of them. |
| 68 | COMPILER_CHECK(sizeof(AsanThreadSummary) <= 4094); |
| 69 | |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 70 | // AsanThread are stored in TSD and destroyed when the thread dies. |
| 71 | class AsanThread { |
| 72 | public: |
| 73 | explicit AsanThread(LinkerInitialized); // for T0. |
Kostya Serebryany | 79437fe | 2012-06-06 15:06:58 +0000 | [diff] [blame] | 74 | static AsanThread *Create(u32 parent_tid, thread_callback_t start_routine, |
Kostya Serebryany | 6b0d775 | 2012-08-28 11:54:30 +0000 | [diff] [blame] | 75 | void *arg, StackTrace *stack); |
Kostya Serebryany | 3f4b9bb | 2012-01-06 19:44:11 +0000 | [diff] [blame] | 76 | void Destroy(); |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 77 | |
Kostya Serebryany | 6bb2f1d | 2011-12-16 19:13:35 +0000 | [diff] [blame] | 78 | void Init(); // Should be called from the thread itself. |
Timur Iskhodzhanov | 0f9c9a5 | 2012-02-24 15:28:43 +0000 | [diff] [blame] | 79 | thread_return_t ThreadStart(); |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 80 | |
Kostya Serebryany | 8d03204 | 2012-05-31 14:35:53 +0000 | [diff] [blame] | 81 | uptr stack_top() { return stack_top_; } |
| 82 | uptr stack_bottom() { return stack_bottom_; } |
| 83 | uptr stack_size() { return stack_top_ - stack_bottom_; } |
Kostya Serebryany | 79437fe | 2012-06-06 15:06:58 +0000 | [diff] [blame] | 84 | u32 tid() { return summary_->tid(); } |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 85 | AsanThreadSummary *summary() { return summary_; } |
| 86 | void set_summary(AsanThreadSummary *summary) { summary_ = summary; } |
| 87 | |
Kostya Serebryany | 8d03204 | 2012-05-31 14:35:53 +0000 | [diff] [blame] | 88 | const char *GetFrameNameByAddr(uptr addr, uptr *offset); |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 89 | |
Kostya Serebryany | 8d03204 | 2012-05-31 14:35:53 +0000 | [diff] [blame] | 90 | bool AddrIsInStack(uptr addr) { |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 91 | return addr >= stack_bottom_ && addr < stack_top_; |
| 92 | } |
| 93 | |
| 94 | FakeStack &fake_stack() { return fake_stack_; } |
| 95 | AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } |
| 96 | AsanStats &stats() { return stats_; } |
| 97 | |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 98 | private: |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 99 | void SetThreadStackTopAndBottom(); |
| 100 | void ClearShadowForThreadStack(); |
| 101 | AsanThreadSummary *summary_; |
Timur Iskhodzhanov | 0f9c9a5 | 2012-02-24 15:28:43 +0000 | [diff] [blame] | 102 | thread_callback_t start_routine_; |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 103 | void *arg_; |
Kostya Serebryany | 8d03204 | 2012-05-31 14:35:53 +0000 | [diff] [blame] | 104 | uptr stack_top_; |
| 105 | uptr stack_bottom_; |
Kostya Serebryany | 019b76f | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 106 | |
| 107 | FakeStack fake_stack_; |
| 108 | AsanThreadLocalMallocStorage malloc_storage_; |
| 109 | AsanStats stats_; |
| 110 | }; |
| 111 | |
| 112 | } // namespace __asan |
| 113 | |
| 114 | #endif // ASAN_THREAD_H |