• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- asan_thread_registry.cc -------------------------------------------===//
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 // AsanThreadRegistry-related code. AsanThreadRegistry is a container
13 // for summaries of all created threads.
14 //===----------------------------------------------------------------------===//
15 
16 #include "asan_stack.h"
17 #include "asan_thread.h"
18 #include "asan_thread_registry.h"
19 #include "sanitizer_common/sanitizer_common.h"
20 
21 namespace __asan {
22 
23 static AsanThreadRegistry asan_thread_registry(LINKER_INITIALIZED);
24 
asanThreadRegistry()25 AsanThreadRegistry &asanThreadRegistry() {
26   return asan_thread_registry;
27 }
28 
AsanThreadRegistry(LinkerInitialized x)29 AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
30     : main_thread_(x),
31       main_thread_summary_(x),
32       accumulated_stats_(x),
33       mu_(x) { }
34 
Init()35 void AsanThreadRegistry::Init() {
36   AsanTSDInit(AsanThreadSummary::TSDDtor);
37   main_thread_.set_summary(&main_thread_summary_);
38   main_thread_summary_.set_thread(&main_thread_);
39   RegisterThread(&main_thread_);
40   SetCurrent(&main_thread_);
41   // At this point only one thread exists.
42   inited_ = true;
43 }
44 
RegisterThread(AsanThread * thread)45 void AsanThreadRegistry::RegisterThread(AsanThread *thread) {
46   ScopedLock lock(&mu_);
47   u32 tid = n_threads_;
48   n_threads_++;
49   CHECK(n_threads_ < kMaxNumberOfThreads);
50 
51   AsanThreadSummary *summary = thread->summary();
52   CHECK(summary != 0);
53   summary->set_tid(tid);
54   thread_summaries_[tid] = summary;
55 }
56 
UnregisterThread(AsanThread * thread)57 void AsanThreadRegistry::UnregisterThread(AsanThread *thread) {
58   ScopedLock lock(&mu_);
59   FlushToAccumulatedStatsUnlocked(&thread->stats());
60   AsanThreadSummary *summary = thread->summary();
61   CHECK(summary);
62   summary->set_thread(0);
63 }
64 
GetMain()65 AsanThread *AsanThreadRegistry::GetMain() {
66   return &main_thread_;
67 }
68 
GetCurrent()69 AsanThread *AsanThreadRegistry::GetCurrent() {
70   AsanThreadSummary *summary = (AsanThreadSummary *)AsanTSDGet();
71   if (!summary) {
72 #if ASAN_ANDROID
73     // On Android, libc constructor is called _after_ asan_init, and cleans up
74     // TSD. Try to figure out if this is still the main thread by the stack
75     // address. We are not entirely sure that we have correct main thread
76     // limits, so only do this magic on Android, and only if the found thread is
77     // the main thread.
78     AsanThread* thread = FindThreadByStackAddress((uptr)&summary);
79     if (thread && thread->tid() == 0) {
80       SetCurrent(thread);
81       return thread;
82     }
83 #endif
84     return 0;
85   }
86   return summary->thread();
87 }
88 
SetCurrent(AsanThread * t)89 void AsanThreadRegistry::SetCurrent(AsanThread *t) {
90   CHECK(t->summary());
91   if (flags()->verbosity >= 2) {
92     Report("SetCurrent: %p for thread %p\n",
93            t->summary(), (void*)GetThreadSelf());
94   }
95   // Make sure we do not reset the current AsanThread.
96   CHECK(AsanTSDGet() == 0);
97   AsanTSDSet(t->summary());
98   CHECK(AsanTSDGet() == t->summary());
99 }
100 
GetCurrentThreadStats()101 AsanStats &AsanThreadRegistry::GetCurrentThreadStats() {
102   AsanThread *t = GetCurrent();
103   return (t) ? t->stats() : main_thread_.stats();
104 }
105 
GetAccumulatedStats()106 AsanStats AsanThreadRegistry::GetAccumulatedStats() {
107   ScopedLock lock(&mu_);
108   UpdateAccumulatedStatsUnlocked();
109   return accumulated_stats_;
110 }
111 
GetCurrentAllocatedBytes()112 uptr AsanThreadRegistry::GetCurrentAllocatedBytes() {
113   ScopedLock lock(&mu_);
114   UpdateAccumulatedStatsUnlocked();
115   return accumulated_stats_.malloced - accumulated_stats_.freed;
116 }
117 
GetHeapSize()118 uptr AsanThreadRegistry::GetHeapSize() {
119   ScopedLock lock(&mu_);
120   UpdateAccumulatedStatsUnlocked();
121   return accumulated_stats_.mmaped;
122 }
123 
GetFreeBytes()124 uptr AsanThreadRegistry::GetFreeBytes() {
125   ScopedLock lock(&mu_);
126   UpdateAccumulatedStatsUnlocked();
127   return accumulated_stats_.mmaped
128          - accumulated_stats_.malloced
129          - accumulated_stats_.malloced_redzones
130          + accumulated_stats_.really_freed
131          + accumulated_stats_.really_freed_redzones;
132 }
133 
FindByTid(u32 tid)134 AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) {
135   CHECK(tid < n_threads_);
136   CHECK(thread_summaries_[tid]);
137   return thread_summaries_[tid];
138 }
139 
FindThreadByStackAddress(uptr addr)140 AsanThread *AsanThreadRegistry::FindThreadByStackAddress(uptr addr) {
141   ScopedLock lock(&mu_);
142   for (u32 tid = 0; tid < n_threads_; tid++) {
143     AsanThread *t = thread_summaries_[tid]->thread();
144     if (!t || !(t->fake_stack().StackSize())) continue;
145     if (t->fake_stack().AddrIsInFakeStack(addr) || t->AddrIsInStack(addr)) {
146       return t;
147     }
148   }
149   return 0;
150 }
151 
UpdateAccumulatedStatsUnlocked()152 void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() {
153   for (u32 tid = 0; tid < n_threads_; tid++) {
154     AsanThread *t = thread_summaries_[tid]->thread();
155     if (t != 0) {
156       FlushToAccumulatedStatsUnlocked(&t->stats());
157     }
158   }
159 }
160 
FlushToAccumulatedStatsUnlocked(AsanStats * stats)161 void AsanThreadRegistry::FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
162   // AsanStats consists of variables of type uptr only.
163   uptr *dst = (uptr*)&accumulated_stats_;
164   uptr *src = (uptr*)stats;
165   uptr num_fields = sizeof(AsanStats) / sizeof(uptr);
166   for (uptr i = 0; i < num_fields; i++) {
167     dst[i] += src[i];
168     src[i] = 0;
169   }
170 }
171 
172 }  // namespace __asan
173