summaryrefslogtreecommitdiff
path: root/libsanitizer/asan/asan_thread.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libsanitizer/asan/asan_thread.cc')
-rw-r--r--libsanitizer/asan/asan_thread.cc53
1 files changed, 36 insertions, 17 deletions
diff --git a/libsanitizer/asan/asan_thread.cc b/libsanitizer/asan/asan_thread.cc
index 1da714c6013..5a9c2dddffb 100644
--- a/libsanitizer/asan/asan_thread.cc
+++ b/libsanitizer/asan/asan_thread.cc
@@ -17,6 +17,7 @@
#include "asan_mapping.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
#include "lsan/lsan_common.h"
namespace __asan {
@@ -25,9 +26,8 @@ namespace __asan {
void AsanThreadContext::OnCreated(void *arg) {
CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
- if (args->stack) {
- internal_memcpy(&stack, args->stack, sizeof(stack));
- }
+ if (args->stack)
+ stack_id = StackDepotPut(args->stack->trace, args->stack->size);
thread = args->thread;
thread->set_context(this);
}
@@ -41,9 +41,12 @@ void AsanThreadContext::OnFinished() {
static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
static ThreadRegistry *asan_thread_registry;
+static BlockingMutex mu_for_thread_context(LINKER_INITIALIZED);
+static LowLevelAllocator allocator_for_thread_context;
+
static ThreadContextBase *GetAsanThreadContext(u32 tid) {
- void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext");
- return new(mem) AsanThreadContext(tid);
+ BlockingMutexLock lock(&mu_for_thread_context);
+ return new(allocator_for_thread_context) AsanThreadContext(tid);
}
ThreadRegistry &asanThreadRegistry() {
@@ -76,24 +79,25 @@ AsanThread *AsanThread::Create(thread_callback_t start_routine,
AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
thread->start_routine_ = start_routine;
thread->arg_ = arg;
- thread->context_ = 0;
return thread;
}
void AsanThread::TSDDtor(void *tsd) {
AsanThreadContext *context = (AsanThreadContext*)tsd;
- if (flags()->verbosity >= 1)
+ if (common_flags()->verbosity >= 1)
Report("T%d TSDDtor\n", context->tid);
if (context->thread)
context->thread->Destroy();
}
void AsanThread::Destroy() {
- if (flags()->verbosity >= 1) {
+ if (common_flags()->verbosity >= 1) {
Report("T%d exited\n", tid());
}
+ malloc_storage().CommitBack();
+ if (flags()->use_sigaltstack) UnsetAlternateSignalStack();
asanThreadRegistry().FinishThread(tid());
FlushToDeadThreadStats(&stats_);
// We also clear the shadow on thread destruction because
@@ -136,7 +140,7 @@ void AsanThread::Init() {
CHECK(AddrIsInMem(stack_bottom_));
CHECK(AddrIsInMem(stack_top_ - 1));
ClearShadowForThreadStackAndTLS();
- if (flags()->verbosity >= 1) {
+ if (common_flags()->verbosity >= 1) {
int local = 0;
Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
tid(), (void*)stack_bottom_, (void*)stack_top_,
@@ -160,10 +164,14 @@ thread_return_t AsanThread::ThreadStart(uptr os_id) {
}
thread_return_t res = start_routine_(arg_);
- malloc_storage().CommitBack();
- if (flags()->use_sigaltstack) UnsetAlternateSignalStack();
- this->Destroy();
+ // On POSIX systems we defer this to the TSD destructor. LSan will consider
+ // the thread's memory as non-live from the moment we call Destroy(), even
+ // though that memory might contain pointers to heap objects which will be
+ // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
+ // the TSD destructors have run might cause false positives in LSan.
+ if (!SANITIZER_POSIX)
+ this->Destroy();
return res;
}
@@ -257,7 +265,7 @@ AsanThread *GetCurrentThread() {
void SetCurrentThread(AsanThread *t) {
CHECK(t->context());
- if (flags()->verbosity >= 2) {
+ if (common_flags()->verbosity >= 2) {
Report("SetCurrentThread: %p for thread %p\n",
t->context(), (void*)GetThreadSelf());
}
@@ -286,6 +294,13 @@ void EnsureMainThreadIDIsCorrect() {
if (context && (context->tid == 0))
context->os_id = GetTid();
}
+
+__asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) {
+ __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
+ __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
+ if (!context) return 0;
+ return context->thread;
+}
} // namespace __asan
// --- Implementation of LSan-specific functions --- {{{1
@@ -293,10 +308,7 @@ namespace __lsan {
bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
uptr *tls_begin, uptr *tls_end,
uptr *cache_begin, uptr *cache_end) {
- __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
- __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
- if (!context) return false;
- __asan::AsanThread *t = context->thread;
+ __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
if (!t) return false;
*stack_begin = t->stack_bottom();
*stack_end = t->stack_top();
@@ -308,6 +320,13 @@ bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
return true;
}
+void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
+ void *arg) {
+ __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
+ if (t && t->has_fake_stack())
+ t->fake_stack()->ForEachFakeFrame(callback, arg);
+}
+
void LockThreadRegistry() {
__asan::asanThreadRegistry().Lock();
}