AddressSanitizer: create AsanThreadSummary together with AsanThread (in parent thread)
llvm-svn: 148286
This commit is contained in:
parent
37b10ef250
commit
2d3a67b73b
|
@ -280,8 +280,8 @@ int WRAP(pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
void *(*start_routine) (void *), void *arg) {
|
void *(*start_routine) (void *), void *arg) {
|
||||||
GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false);
|
GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false);
|
||||||
int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
|
int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
|
||||||
AsanThread *t = AsanThread::Create(current_tid, start_routine, arg);
|
AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
|
||||||
asanThreadRegistry().RegisterThread(t, current_tid, &stack);
|
asanThreadRegistry().RegisterThread(t);
|
||||||
return real_pthread_create(thread, attr, asan_thread_start, t);
|
return real_pthread_create(thread, attr, asan_thread_start, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,8 +246,8 @@ void asan_dispatch_call_block_and_release(void *block) {
|
||||||
}
|
}
|
||||||
AsanThread *t = asanThreadRegistry().GetCurrent();
|
AsanThread *t = asanThreadRegistry().GetCurrent();
|
||||||
if (!t) {
|
if (!t) {
|
||||||
t = AsanThread::Create(context->parent_tid, NULL, NULL);
|
t = AsanThread::Create(context->parent_tid, NULL, NULL, &stack);
|
||||||
asanThreadRegistry().RegisterThread(t, context->parent_tid, &stack);
|
asanThreadRegistry().RegisterThread(t);
|
||||||
t->Init();
|
t->Init();
|
||||||
asanThreadRegistry().SetCurrent(t);
|
asanThreadRegistry().SetCurrent(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,10 @@ struct AsanStackTrace {
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
|
||||||
|
// as early as possible (in functions exposed to the user), as we generally
|
||||||
|
// don't want stack trace to contain functions from ASan internals.
|
||||||
|
|
||||||
#define GET_STACK_TRACE_HERE(max_size, fast_unwind) \
|
#define GET_STACK_TRACE_HERE(max_size, fast_unwind) \
|
||||||
GET_STACK_TRACE_WITH_PC_AND_BP(max_size, fast_unwind, \
|
GET_STACK_TRACE_WITH_PC_AND_BP(max_size, fast_unwind, \
|
||||||
AsanStackTrace::GetCurrentPc(), GET_CURRENT_FRAME()) \
|
AsanStackTrace::GetCurrentPc(), GET_CURRENT_FRAME()) \
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "asan_allocator.h"
|
#include "asan_allocator.h"
|
||||||
#include "asan_interceptors.h"
|
#include "asan_interceptors.h"
|
||||||
#include "asan_procmaps.h"
|
#include "asan_procmaps.h"
|
||||||
|
#include "asan_stack.h"
|
||||||
#include "asan_thread.h"
|
#include "asan_thread.h"
|
||||||
#include "asan_thread_registry.h"
|
#include "asan_thread_registry.h"
|
||||||
#include "asan_mapping.h"
|
#include "asan_mapping.h"
|
||||||
|
@ -26,42 +27,41 @@ AsanThread::AsanThread(LinkerInitialized x)
|
||||||
stats_(x) { }
|
stats_(x) { }
|
||||||
|
|
||||||
AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *),
|
AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *),
|
||||||
void *arg) {
|
void *arg, AsanStackTrace *stack) {
|
||||||
size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
|
size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
|
||||||
AsanThread *res = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
|
AsanThread *thread = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
|
||||||
res->start_routine_ = start_routine;
|
thread->start_routine_ = start_routine;
|
||||||
res->arg_ = arg;
|
thread->arg_ = arg;
|
||||||
return res;
|
|
||||||
|
AsanThreadSummary *summary = new AsanThreadSummary(parent_tid, stack);
|
||||||
|
summary->set_thread(thread);
|
||||||
|
thread->set_summary(summary);
|
||||||
|
|
||||||
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsanThread::Destroy() {
|
void AsanThread::Destroy() {
|
||||||
fake_stack().Cleanup();
|
|
||||||
// We also clear the shadow on thread destruction because
|
// We also clear the shadow on thread destruction because
|
||||||
// some code may still be executing in later TSD destructors
|
// some code may still be executing in later TSD destructors
|
||||||
// and we don't want it to have any poisoned stack.
|
// and we don't want it to have any poisoned stack.
|
||||||
ClearShadowForThreadStack();
|
ClearShadowForThreadStack();
|
||||||
|
fake_stack().Cleanup();
|
||||||
size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
|
size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
|
||||||
AsanUnmapOrDie(this, size);
|
AsanUnmapOrDie(this, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsanThread::ClearShadowForThreadStack() {
|
|
||||||
PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsanThread::Init() {
|
void AsanThread::Init() {
|
||||||
SetThreadStackTopAndBottom();
|
SetThreadStackTopAndBottom();
|
||||||
fake_stack_.Init(stack_size());
|
CHECK(AddrIsInMem(stack_bottom_));
|
||||||
|
CHECK(AddrIsInMem(stack_top_));
|
||||||
|
ClearShadowForThreadStack();
|
||||||
if (FLAG_v >= 1) {
|
if (FLAG_v >= 1) {
|
||||||
int local = 0;
|
int local = 0;
|
||||||
Report("T%d: stack [%p,%p) size 0x%lx; local=%p\n",
|
Report("T%d: stack [%p,%p) size 0x%lx; local=%p\n",
|
||||||
tid(), stack_bottom_, stack_top_,
|
tid(), stack_bottom_, stack_top_,
|
||||||
stack_top_ - stack_bottom_, &local);
|
stack_top_ - stack_bottom_, &local);
|
||||||
}
|
}
|
||||||
|
fake_stack_.Init(stack_size());
|
||||||
CHECK(AddrIsInMem(stack_bottom_));
|
|
||||||
CHECK(AddrIsInMem(stack_top_));
|
|
||||||
|
|
||||||
ClearShadowForThreadStack();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *AsanThread::ThreadStart() {
|
void *AsanThread::ThreadStart() {
|
||||||
|
@ -88,6 +88,10 @@ void *AsanThread::ThreadStart() {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsanThread::ClearShadowForThreadStack() {
|
||||||
|
PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) {
|
const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) {
|
||||||
uintptr_t bottom = 0;
|
uintptr_t bottom = 0;
|
||||||
bool is_fake_stack = false;
|
bool is_fake_stack = false;
|
||||||
|
|
|
@ -30,10 +30,10 @@ class AsanThread;
|
||||||
class AsanThreadSummary {
|
class AsanThreadSummary {
|
||||||
public:
|
public:
|
||||||
explicit AsanThreadSummary(LinkerInitialized) { } // for T0.
|
explicit AsanThreadSummary(LinkerInitialized) { } // for T0.
|
||||||
AsanThreadSummary(int tid, int parent_tid, AsanStackTrace *stack)
|
AsanThreadSummary(int parent_tid, AsanStackTrace *stack)
|
||||||
: tid_(tid),
|
: parent_tid_(parent_tid),
|
||||||
parent_tid_(parent_tid),
|
|
||||||
announced_(false) {
|
announced_(false) {
|
||||||
|
tid_ = -1;
|
||||||
if (stack) {
|
if (stack) {
|
||||||
stack_ = *stack;
|
stack_ = *stack;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ class AsanThreadSummary {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int tid() { return tid_; }
|
int tid() { return tid_; }
|
||||||
|
void set_tid(int tid) { tid_ = tid; }
|
||||||
AsanThread *thread() { return thread_; }
|
AsanThread *thread() { return thread_; }
|
||||||
void set_thread(AsanThread *thread) { thread_ = thread; }
|
void set_thread(AsanThread *thread) { thread_ = thread; }
|
||||||
private:
|
private:
|
||||||
|
@ -63,7 +64,7 @@ class AsanThread {
|
||||||
public:
|
public:
|
||||||
explicit AsanThread(LinkerInitialized); // for T0.
|
explicit AsanThread(LinkerInitialized); // for T0.
|
||||||
static AsanThread *Create(int parent_tid, void *(*start_routine) (void *),
|
static AsanThread *Create(int parent_tid, void *(*start_routine) (void *),
|
||||||
void *arg);
|
void *arg, AsanStackTrace *stack);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
void Init(); // Should be called from the thread itself.
|
void Init(); // Should be called from the thread itself.
|
||||||
|
|
|
@ -35,22 +35,20 @@ void AsanThreadRegistry::Init() {
|
||||||
AsanTSDInit();
|
AsanTSDInit();
|
||||||
main_thread_.set_summary(&main_thread_summary_);
|
main_thread_.set_summary(&main_thread_summary_);
|
||||||
main_thread_summary_.set_thread(&main_thread_);
|
main_thread_summary_.set_thread(&main_thread_);
|
||||||
|
RegisterThread(&main_thread_);
|
||||||
SetCurrent(&main_thread_);
|
SetCurrent(&main_thread_);
|
||||||
thread_summaries_[0] = &main_thread_summary_;
|
|
||||||
n_threads_ = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsanThreadRegistry::RegisterThread(AsanThread *thread, int parent_tid,
|
void AsanThreadRegistry::RegisterThread(AsanThread *thread) {
|
||||||
AsanStackTrace *stack) {
|
|
||||||
ScopedLock lock(&mu_);
|
ScopedLock lock(&mu_);
|
||||||
CHECK(n_threads_ > 0);
|
|
||||||
int tid = n_threads_;
|
int tid = n_threads_;
|
||||||
n_threads_++;
|
n_threads_++;
|
||||||
CHECK(n_threads_ < kMaxNumberOfThreads);
|
CHECK(n_threads_ < kMaxNumberOfThreads);
|
||||||
AsanThreadSummary *summary = new AsanThreadSummary(tid, parent_tid, stack);
|
|
||||||
summary->set_thread(thread);
|
AsanThreadSummary *summary = thread->summary();
|
||||||
|
CHECK(summary != NULL);
|
||||||
|
summary->set_tid(tid);
|
||||||
thread_summaries_[tid] = summary;
|
thread_summaries_[tid] = summary;
|
||||||
thread->set_summary(summary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsanThreadRegistry::UnregisterThread(AsanThread *thread) {
|
void AsanThreadRegistry::UnregisterThread(AsanThread *thread) {
|
||||||
|
|
|
@ -30,8 +30,7 @@ class AsanThreadRegistry {
|
||||||
public:
|
public:
|
||||||
explicit AsanThreadRegistry(LinkerInitialized);
|
explicit AsanThreadRegistry(LinkerInitialized);
|
||||||
void Init();
|
void Init();
|
||||||
void RegisterThread(AsanThread *thread, int parent_tid,
|
void RegisterThread(AsanThread *thread);
|
||||||
AsanStackTrace *stack);
|
|
||||||
void UnregisterThread(AsanThread *thread);
|
void UnregisterThread(AsanThread *thread);
|
||||||
|
|
||||||
AsanThread *GetMain();
|
AsanThread *GetMain();
|
||||||
|
|
Loading…
Reference in New Issue