diff options
| author | Alexey Samsonov <samsonov@google.com> | 2012-09-05 07:37:15 +0000 | 
|---|---|---|
| committer | Alexey Samsonov <samsonov@google.com> | 2012-09-05 07:37:15 +0000 | 
| commit | c402cb62fd5ae6a664d0f65593dbd759e229d332 (patch) | |
| tree | c881a5a5fbc7abe2ba00a1104f8326e78f55cb70 /compiler-rt/lib | |
| parent | 2fa38f8ce07466e8a80716ee575c38066dab1f80 (diff) | |
| download | bcm5719-llvm-c402cb62fd5ae6a664d0f65593dbd759e229d332.tar.gz bcm5719-llvm-c402cb62fd5ae6a664d0f65593dbd759e229d332.zip  | |
[ASan] Add print_full_thread_history runtime option (on by default) that prints all full thread creation paths for threads involved in ASan error report
llvm-svn: 163200
Diffstat (limited to 'compiler-rt/lib')
| -rw-r--r-- | compiler-rt/lib/asan/asan_allocator.cc | 10 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_flags.h | 4 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_report.cc | 24 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_report.h | 3 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_thread.h | 12 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/lit_tests/deep_thread_stack.cc | 61 | 
7 files changed, 101 insertions, 15 deletions
diff --git a/compiler-rt/lib/asan/asan_allocator.cc b/compiler-rt/lib/asan/asan_allocator.cc index 8abba561601..dcec1ec7848 100644 --- a/compiler-rt/lib/asan/asan_allocator.cc +++ b/compiler-rt/lib/asan/asan_allocator.cc @@ -609,14 +609,14 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {                 alloc_thread->tid());      PrintStack(&alloc_stack); -    t->summary()->Announce(); -    free_thread->Announce(); -    alloc_thread->Announce(); +    DescribeThread(t->summary()); +    DescribeThread(free_thread); +    DescribeThread(alloc_thread);    } else {      Printf("allocated by thread T%d here:\n", alloc_thread->tid());      PrintStack(&alloc_stack); -    t->summary()->Announce(); -    alloc_thread->Announce(); +    DescribeThread(t->summary()); +    DescribeThread(alloc_thread);    }  } diff --git a/compiler-rt/lib/asan/asan_flags.h b/compiler-rt/lib/asan/asan_flags.h index ce30fcbd71f..de7475bc10a 100644 --- a/compiler-rt/lib/asan/asan_flags.h +++ b/compiler-rt/lib/asan/asan_flags.h @@ -89,6 +89,10 @@ struct Flags {    bool allow_reexec;    // Strips this prefix from file paths in error reports.    const char *strip_path_prefix; +  // If set, prints not only thread creation stacks for threads in error report, +  // but also thread creation stacks for threads that created those threads, +  // etc. up to main thread. +  bool print_full_thread_history;  };  Flags *flags(); diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index 71ca4003bfa..2a00c4e691c 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -184,7 +184,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {    Printf("HINT: this may be a false positive if your program uses "               "some custom stack unwind mechanism\n"               "      (longjmp and C++ exceptions *are* supported)\n"); -  t->summary()->Announce(); +  DescribeThread(t->summary());    return true;  } @@ -201,6 +201,26 @@ void DescribeAddress(uptr addr, uptr access_size) {    DescribeHeapAddress(addr, access_size);  } +// ------------------- Thread description -------------------- {{{1 + +void DescribeThread(AsanThreadSummary *summary) { +  CHECK(summary); +  // No need to announce the main thread. +  if (summary->tid() == 0 || summary->announced()) { +    return; +  } +  summary->set_announced(true); +  Printf("Thread T%d created by T%d here:\n", +         summary->tid(), summary->parent_tid()); +  PrintStack(summary->stack()); +  // Recursively described parent thread if needed. +  if (flags()->print_full_thread_history) { +    AsanThreadSummary *parent_summary = +        asanThreadRegistry().FindByTid(summary->parent_tid()); +    DescribeThread(parent_summary); +  } +} +  // -------------------- Different kinds of reports ----------------- {{{1  // Use ScopedInErrorReport to run common actions just before and @@ -238,7 +258,7 @@ class ScopedInErrorReport {      // Make sure the current thread is announced.      AsanThread *curr_thread = asanThreadRegistry().GetCurrent();      if (curr_thread) { -      curr_thread->summary()->Announce(); +      DescribeThread(curr_thread->summary());      }      // Print memory stats.      __asan_print_accumulated_stats(); diff --git a/compiler-rt/lib/asan/asan_report.h b/compiler-rt/lib/asan/asan_report.h index 08456905559..dc3bf9b01aa 100644 --- a/compiler-rt/lib/asan/asan_report.h +++ b/compiler-rt/lib/asan/asan_report.h @@ -13,6 +13,7 @@  //===----------------------------------------------------------------------===//  #include "asan_internal.h" +#include "asan_thread.h"  #include "sanitizer/asan_interface.h"  namespace __asan { @@ -27,6 +28,8 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size);  // Determines memory type on its own.  void DescribeAddress(uptr addr, uptr access_size); +void DescribeThread(AsanThreadSummary *summary); +  // Different kinds of error reports.  void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr);  void NORETURN ReportDoubleFree(uptr addr, StackTrace *stack); diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 2970fd5eae3..d2a51df549c 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -102,6 +102,7 @@ static void ParseFlagsFromString(Flags *f, const char *str) {    ParseFlag(str, &f->disable_core, "disable_core");    ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");    ParseFlag(str, &f->allow_reexec, "allow_reexec"); +  ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");  }  extern "C" { @@ -139,6 +140,7 @@ void InitializeFlags(Flags *f, const char *env) {    f->disable_core = (__WORDSIZE == 64);    f->strip_path_prefix = "";    f->allow_reexec = true; +  f->print_full_thread_history = true;    // Override from user-specified string.    ParseFlagsFromString(f, __asan_default_options()); diff --git a/compiler-rt/lib/asan/asan_thread.h b/compiler-rt/lib/asan/asan_thread.h index 8abc1d12913..4d4c43994aa 100644 --- a/compiler-rt/lib/asan/asan_thread.h +++ b/compiler-rt/lib/asan/asan_thread.h @@ -40,16 +40,12 @@ class AsanThreadSummary {      }      thread_ = 0;    } -  void Announce() { -    if (tid_ == 0) return;  // no need to announce the main thread. -    if (!announced_) { -      announced_ = true; -      Printf("Thread T%d created by T%d here:\n", tid_, parent_tid_); -      PrintStack(&stack_); -    } -  }    u32 tid() { return tid_; }    void set_tid(u32 tid) { tid_ = tid; } +  u32 parent_tid() { return parent_tid_; } +  bool announced() { return announced_; } +  void set_announced(bool announced) { announced_ = announced; } +  StackTrace *stack() { return &stack_; }    AsanThread *thread() { return thread_; }    void set_thread(AsanThread *thread) { thread_ = thread; }    static void TSDDtor(void *tsd); diff --git a/compiler-rt/lib/asan/lit_tests/deep_thread_stack.cc b/compiler-rt/lib/asan/lit_tests/deep_thread_stack.cc new file mode 100644 index 00000000000..810f4e4971b --- /dev/null +++ b/compiler-rt/lib/asan/lit_tests/deep_thread_stack.cc @@ -0,0 +1,61 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m64 -O1 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m64 -O2 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +#include <pthread.h> + +int *x; + +void *AllocThread(void *arg) { +  x = new int; +  *x = 42; +  return NULL; +} + +void *FreeThread(void *arg) { +  delete x; +  return NULL; +} + +void *AccessThread(void *arg) { +  *x = 43;  // BOOM +  return NULL; +} + +typedef void* (*callback_type)(void* arg); + +void *RunnerThread(void *function) { +  pthread_t thread; +  pthread_create(&thread, NULL, (callback_type)function, NULL); +  pthread_join(thread, NULL); +  return NULL; +} + +void RunThread(callback_type function) { +  pthread_t runner; +  pthread_create(&runner, NULL, RunnerThread, (void*)function); +  pthread_join(runner, NULL); +} + +int main(int argc, char *argv[]) { +  RunThread(AllocThread); +  RunThread(FreeThread); +  RunThread(AccessThread); +  return (x != 0); +} + +// CHECK: AddressSanitizer heap-use-after-free +// CHECK: WRITE of size 4 at 0x{{.*}} thread T[[ACCESS_THREAD:[0-9]+]] +// CHECK: freed by thread T[[FREE_THREAD:[0-9]+]] here: +// CHECK: previously allocated by thread T[[ALLOC_THREAD:[0-9]+]] here: +// CHECK: Thread T[[ACCESS_THREAD]] created by T[[ACCESS_RUNNER:[0-9]+]] here: +// CHECK: Thread T[[ACCESS_RUNNER]] created by T0 here: +// CHECK: Thread T[[FREE_THREAD]] created by T[[FREE_RUNNER:[0-9]+]] here: +// CHECK: Thread T[[FREE_RUNNER]] created by T0 here: +// CHECK: Thread T[[ALLOC_THREAD]] created by T[[ALLOC_RUNNER:[0-9]+]] here: +// CHECK: Thread T[[ALLOC_RUNNER]] created by T0 here:  | 

