AddressSanitizer: create AsanThreadSummary together with AsanThread (in parent thread)

llvm-svn: 148286
This commit is contained in:
Alexey Samsonov 2012-01-17 06:35:31 +00:00
parent 37b10ef250
commit 2d3a67b73b
7 changed files with 40 additions and 34 deletions

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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()) \

View File

@ -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;

View File

@ -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.

View File

@ -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) {

View File

@ -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();