blob: 27fa2fe98e394ad18d6c0eb90c5f68f4cc41898b [file] [log] [blame]
Kostya Serebryany1e172b42011-11-30 01:07:02 +00001//===-- asan_thread.cc ------------------------------------------*- 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// Thread-related code.
13//===----------------------------------------------------------------------===//
14#include "asan_allocator.h"
15#include "asan_interceptors.h"
16#include "asan_thread.h"
17#include "asan_thread_registry.h"
18#include "asan_mapping.h"
19
20#include <sys/mman.h>
21#include <pthread.h>
22#include <stdlib.h>
23#include <string.h>
24
25namespace __asan {
26
27AsanThread::AsanThread(LinkerInitialized x)
28 : fake_stack_(x),
29 malloc_storage_(x),
30 stats_(x) { }
31
32AsanThread::AsanThread(int parent_tid, void *(*start_routine) (void *),
33 void *arg, AsanStackTrace *stack)
34 : start_routine_(start_routine),
35 arg_(arg) {
36 asanThreadRegistry().RegisterThread(this, parent_tid, stack);
37}
38
39AsanThread::~AsanThread() {
40 asanThreadRegistry().UnregisterThread(this);
41 fake_stack().Cleanup();
42 // We also clear the shadow on thread destruction because
43 // some code may still be executing in later TSD destructors
44 // and we don't want it to have any poisoned stack.
45 ClearShadowForThreadStack();
46}
47
48void AsanThread::ClearShadowForThreadStack() {
49 uintptr_t shadow_bot = MemToShadow(stack_bottom_);
50 uintptr_t shadow_top = MemToShadow(stack_top_);
51 real_memset((void*)shadow_bot, 0, shadow_top - shadow_bot);
52}
53
54void *AsanThread::ThreadStart() {
55 SetThreadStackTopAndBottom();
56 fake_stack_.Init(stack_size());
57 if (FLAG_v >= 1) {
58 int local = 0;
59 Report("T%d: stack [%p,%p) size 0x%lx; local=%p, pthread_self=%p\n",
60 tid(), stack_bottom_, stack_top_,
61 stack_top_ - stack_bottom_, &local, pthread_self());
62 }
63
64 CHECK(AddrIsInMem(stack_bottom_));
65 CHECK(AddrIsInMem(stack_top_));
66
67 ClearShadowForThreadStack();
68
69 if (!start_routine_) {
70 // start_routine_ == NULL if we're on the main thread or on one of the
71 // OS X libdispatch worker threads. But nobody is supposed to call
72 // ThreadStart() for the worker threads.
73 CHECK(tid() == 0);
74 return 0;
75 }
76
77 void *res = start_routine_(arg_);
78 malloc_storage().CommitBack();
79
80 if (FLAG_v >= 1) {
81 Report("T%d exited\n", tid());
82 }
83
84 return res;
85}
86
87const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) {
88 uintptr_t bottom = 0;
89 bool is_fake_stack = false;
90 if (AddrIsInStack(addr)) {
91 bottom = stack_bottom();
92 } else {
93 bottom = fake_stack().AddrIsInFakeStack(addr);
94 CHECK(bottom);
95 is_fake_stack = true;
96 }
97 uintptr_t aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr.
98 uintptr_t *ptr = (uintptr_t*)aligned_addr;
99 while (ptr >= (uintptr_t*)bottom) {
100 if (ptr[0] == kCurrentStackFrameMagic ||
101 (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)) {
102 *offset = addr - (uintptr_t)ptr;
103 return (const char*)ptr[1];
104 }
105 ptr--;
106 }
107 *offset = 0;
108 return "UNKNOWN";
109}
110
111void AsanThread::SetThreadStackTopAndBottom() {
112#ifdef __APPLE__
113 size_t stacksize = pthread_get_stacksize_np(pthread_self());
114 void *stackaddr = pthread_get_stackaddr_np(pthread_self());
115 stack_top_ = (uintptr_t)stackaddr;
116 stack_bottom_ = stack_top_ - stacksize;
117 int local;
118 CHECK(AddrIsInStack((uintptr_t)&local));
119#else
120 pthread_attr_t attr;
121 CHECK(pthread_getattr_np(pthread_self(), &attr) == 0);
122 size_t stacksize = 0;
123 void *stackaddr = NULL;
124 pthread_attr_getstack(&attr, &stackaddr, &stacksize);
125 pthread_attr_destroy(&attr);
126
127 stack_top_ = (uintptr_t)stackaddr + stacksize;
128 stack_bottom_ = (uintptr_t)stackaddr;
129 // When running with unlimited stack size, we still want to set some limit.
130 // The unlimited stack size is caused by 'ulimit -s unlimited'.
131 // Also, for some reason, GNU make spawns subrocesses with unlimited stack.
132 if (stacksize > kMaxThreadStackSize) {
133 stack_bottom_ = stack_top_ - kMaxThreadStackSize;
134 }
135 CHECK(AddrIsInStack((uintptr_t)&attr));
136#endif
137}
138
139} // namespace __asan