[asan] add two asan flags: fast_unwind_on_fatal and fast_unwind_on_malloc to allow...
authorKostya Serebryany <kcc@google.com>
Thu, 13 Dec 2012 09:34:23 +0000 (09:34 +0000)
committerKostya Serebryany <kcc@google.com>
Thu, 13 Dec 2012 09:34:23 +0000 (09:34 +0000)
llvm-svn: 170117

14 files changed:
compiler-rt/lib/asan/asan_allocator.cc
compiler-rt/lib/asan/asan_flags.h
compiler-rt/lib/asan/asan_interceptors.cc
compiler-rt/lib/asan/asan_linux.cc
compiler-rt/lib/asan/asan_mac.cc
compiler-rt/lib/asan/asan_malloc_linux.cc
compiler-rt/lib/asan/asan_malloc_mac.cc
compiler-rt/lib/asan/asan_malloc_win.cc
compiler-rt/lib/asan/asan_new_delete.cc
compiler-rt/lib/asan/asan_report.cc
compiler-rt/lib/asan/asan_rtl.cc
compiler-rt/lib/asan/asan_stack.h
compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h

index 484f9e1..b6ae3c8 100644 (file)
@@ -819,7 +819,7 @@ uptr __asan_get_allocated_size(const void *p) {
   uptr allocated_size = malloc_info.AllocationSize((uptr)p);
   // Die if p is not malloced or if it is already freed.
   if (allocated_size == 0) {
-    GET_STACK_TRACE_HERE(kStackTraceMax);
+    GET_STACK_TRACE_FATAL_HERE;
     ReportAsanGetAllocatedSizeNotOwned((uptr)p, &stack);
   }
   return allocated_size;
index 989784d..ded2b24 100644 (file)
@@ -45,7 +45,7 @@ struct Flags {
   int  report_globals;
   // If set, attempts to catch initialization order issues.
   bool check_initialization_order;
-  // Max number of stack frames kept for each allocation.
+  // Max number of stack frames kept for each allocation/deallocation.
   int  malloc_context_size;
   // If set, uses custom wrappers and replacements for libc string functions
   // to find more errors.
@@ -95,6 +95,10 @@ struct Flags {
   bool print_full_thread_history;
   // ASan will write logs to "log_path.pid" instead of stderr.
   const char *log_path;
+  // Use fast (frame-pointer-based) unwinder on fatal errors (if available).
+  bool fast_unwind_on_fatal;
+  // Use fast (frame-pointer-based) unwinder on malloc/free (if available).
+  bool fast_unwind_on_malloc;
 };
 
 Flags *flags();
index 595f0ed..d3969ed 100644 (file)
@@ -71,7 +71,7 @@ static inline bool RangesOverlap(const char *offset1, uptr length1,
   const char *offset1 = (const char*)_offset1; \
   const char *offset2 = (const char*)_offset2; \
   if (RangesOverlap(offset1, length1, offset2, length2)) { \
-    GET_STACK_TRACE_HERE(kStackTraceMax); \
+    GET_STACK_TRACE_FATAL_HERE; \
     ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
                                             offset2, length2, &stack); \
   } \
@@ -112,7 +112,7 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
 #if ASAN_INTERCEPT_PTHREAD_CREATE
 INTERCEPTOR(int, pthread_create, void *thread,
     void *attr, void *(*start_routine)(void*), void *arg) {
-  GET_STACK_TRACE_HERE(kStackTraceMax);
+  GET_STACK_TRACE_THREAD;
   u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
   AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
   asanThreadRegistry().RegisterThread(t);
@@ -647,7 +647,7 @@ INTERCEPTOR_WINAPI(DWORD, CreateThread,
                    void* security, uptr stack_size,
                    DWORD (__stdcall *start_routine)(void*), void* arg,
                    DWORD flags, void* tid) {
-  GET_STACK_TRACE_HERE(kStackTraceMax);
+  GET_STACK_TRACE_THREAD;
   u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
   AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
   asanThreadRegistry().RegisterThread(t);
index 068f7b1..02a3d14 100644 (file)
@@ -122,53 +122,21 @@ void AsanLock::Unlock() {
   pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_);
 }
 
-#ifdef __arm__
-#define UNWIND_STOP _URC_END_OF_STACK
-#define UNWIND_CONTINUE _URC_NO_REASON
-#else
-#define UNWIND_STOP _URC_NORMAL_STOP
-#define UNWIND_CONTINUE _URC_NO_REASON
-#endif
-
-uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
-#ifdef __arm__
-  uptr val;
-  _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
-      15 /* r15 = PC */, _UVRSD_UINT32, &val);
-  CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
-  // Clear the Thumb bit.
-  return val & ~(uptr)1;
-#else
-  return _Unwind_GetIP(ctx);
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
+#if defined(__arm__) || \
+    defined(__powerpc__) || defined(__powerpc64__) || \
+    defined(__sparc__)
+  fast = false;
 #endif
-}
-
-_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
-    void *param) {
-  StackTrace *b = (StackTrace*)param;
-  CHECK(b->size < b->max_size);
-  uptr pc = Unwind_GetIP(ctx);
-  b->trace[b->size++] = pc;
-  if (b->size == b->max_size) return UNWIND_STOP;
-  return UNWIND_CONTINUE;
-}
-
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
+  if (!fast)
+    return stack->SlowUnwindStack(pc, max_s, 3);
   stack->size = 0;
   stack->trace[0] = pc;
-  if ((max_s) > 1) {
+  if (max_s > 1) {
     stack->max_size = max_s;
-#if defined(__arm__) || \
-    defined(__powerpc__) || defined(__powerpc64__) || \
-    defined(__sparc__)
-    _Unwind_Backtrace(Unwind_Trace, stack);
-    // Pop off the two ASAN functions from the backtrace.
-    stack->PopStackFrames(2);
-#else
     if (!asan_inited) return;
     if (AsanThread *t = asanThreadRegistry().GetCurrent())
       stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
-#endif
   }
 }
 
index 7abe9a4..11e6a13 100644 (file)
@@ -160,7 +160,7 @@ void AsanLock::Unlock() {
   OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
 }
 
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
   stack->size = 0;
   stack->trace[0] = pc;
   if ((max_s) > 1) {
@@ -308,7 +308,7 @@ void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
 // alloc_asan_context().
 extern "C"
 void asan_dispatch_call_block_and_release(void *block) {
-  GET_STACK_TRACE_HERE(kStackTraceMax);
+  GET_STACK_TRACE_THREAD;
   asan_block_context_t *context = (asan_block_context_t*)block;
   if (flags()->verbosity >= 2) {
     Report("asan_dispatch_call_block_and_release(): "
@@ -343,7 +343,7 @@ asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
 #define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f)                                \
   INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt,            \
                                   dispatch_function_t func) {                 \
-    GET_STACK_TRACE_HERE(kStackTraceMax);                                     \
+    GET_STACK_TRACE_THREAD;                                                   \
     asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); \
     if (flags()->verbosity >= 2) {                                            \
       Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n",             \
@@ -361,7 +361,7 @@ INTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f)
 INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
                                     dispatch_queue_t dq, void *ctxt,
                                     dispatch_function_t func) {
-  GET_STACK_TRACE_HERE(kStackTraceMax);
+  GET_STACK_TRACE_THREAD;
   asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
   if (flags()->verbosity >= 2) {
     Report("dispatch_after_f: %p\n", asan_ctxt);
@@ -374,7 +374,7 @@ INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
 INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
                                           dispatch_queue_t dq, void *ctxt,
                                           dispatch_function_t func) {
-  GET_STACK_TRACE_HERE(kStackTraceMax);
+  GET_STACK_TRACE_THREAD;
   asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
   if (flags()->verbosity >= 2) {
     Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n",
@@ -409,7 +409,7 @@ void dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void));
   void (^asan_block)(void);  \
   int parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); \
   asan_block = ^(void) { \
-    GET_STACK_TRACE_HERE(kStackTraceMax); \
+    GET_STACK_TRACE_THREAD; \
     asan_register_worker_thread(parent_tid, &stack); \
     work(); \
   }
@@ -459,7 +459,7 @@ void *wrap_workitem_func(void *arg) {
   asan_block_context_t *ctxt = (asan_block_context_t*)arg;
   worker_t fn = (worker_t)(ctxt->func);
   void *result =  fn(ctxt->block);
-  GET_STACK_TRACE_HERE(kStackTraceMax);
+  GET_STACK_TRACE_THREAD;
   asan_free(arg, &stack);
   return result;
 }
@@ -467,7 +467,7 @@ void *wrap_workitem_func(void *arg) {
 INTERCEPTOR(int, pthread_workqueue_additem_np, pthread_workqueue_t workq,
     void *(*workitem_func)(void *), void * workitem_arg,
     pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp) {
-  GET_STACK_TRACE_HERE(kStackTraceMax);
+  GET_STACK_TRACE_THREAD;
   asan_block_context_t *asan_ctxt =
       (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), &stack);
   asan_ctxt->block = workitem_arg;
index 5eb23dd..1bf9051 100644 (file)
@@ -59,17 +59,17 @@ void ReplaceSystemMalloc() {
 using namespace __asan;  // NOLINT
 
 INTERCEPTOR(void, free, void *ptr) {
-  GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+  GET_STACK_TRACE_FREE;
   asan_free(ptr, &stack);
 }
 
 INTERCEPTOR(void, cfree, void *ptr) {
-  GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+  GET_STACK_TRACE_FREE;
   asan_free(ptr, &stack);
 }
 
 INTERCEPTOR(void*, malloc, uptr size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_malloc(size, &stack);
 }
 
@@ -85,17 +85,17 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
     CHECK(allocated < kCallocPoolSize);
     return mem;
   }
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_calloc(nmemb, size, &stack);
 }
 
 INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_realloc(ptr, size, &stack);
 }
 
 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_memalign(boundary, size, &stack);
 }
 
@@ -103,7 +103,7 @@ INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
   ALIAS("memalign");
 
 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_malloc_usable_size(ptr, &stack);
 }
 
@@ -126,18 +126,18 @@ INTERCEPTOR(int, mallopt, int cmd, int value) {
 }
 
 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   // Printf("posix_memalign: %zx %zu\n", alignment, size);
   return asan_posix_memalign(memptr, alignment, size, &stack);
 }
 
 INTERCEPTOR(void*, valloc, uptr size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_valloc(size, &stack);
 }
 
 INTERCEPTOR(void*, pvalloc, uptr size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_pvalloc(size, &stack);
 }
 
index b32c18e..15d166d 100644 (file)
@@ -92,7 +92,7 @@ INTERCEPTOR(void, free, void *ptr) {
 #endif
   } else {
     if (!asan_mz_size(ptr)) ptr = get_saved_cfallocator_ref(ptr);
-    GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+    GET_STACK_TRACE_FREE;
     asan_free(ptr, &stack);
   }
 }
@@ -130,7 +130,7 @@ void *mz_malloc(malloc_zone_t *zone, size_t size) {
     CHECK(system_malloc_zone);
     return malloc_zone_malloc(system_malloc_zone, size);
   }
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_malloc(size, &stack);
 }
 
@@ -139,7 +139,7 @@ void *cf_malloc(CFIndex size, CFOptionFlags hint, void *info) {
     CHECK(system_malloc_zone);
     return malloc_zone_malloc(system_malloc_zone, size);
   }
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_malloc(size, &stack);
 }
 
@@ -155,7 +155,7 @@ void *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
     CHECK(allocated < kCallocPoolSize);
     return mem;
   }
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_calloc(nmemb, size, &stack);
 }
 
@@ -164,7 +164,7 @@ void *mz_valloc(malloc_zone_t *zone, size_t size) {
     CHECK(system_malloc_zone);
     return malloc_zone_valloc(system_malloc_zone, size);
   }
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_memalign(GetPageSizeCached(), size, &stack);
 }
 
@@ -175,7 +175,7 @@ void *mz_valloc(malloc_zone_t *zone, size_t size) {
 void ALWAYS_INLINE free_common(void *context, void *ptr) {
   if (!ptr) return;
   if (asan_mz_size(ptr)) {
-    GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+    GET_STACK_TRACE_FREE;
     asan_free(ptr, &stack);
   } else {
     // If the pointer does not belong to any of the zones, use one of the
@@ -190,7 +190,7 @@ void ALWAYS_INLINE free_common(void *context, void *ptr) {
       // If the memory chunk pointer was moved to store additional
       // CFAllocatorRef, fix it back.
       ptr = get_saved_cfallocator_ref(ptr);
-      GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+      GET_STACK_TRACE_FREE;
       if (!flags()->mac_ignore_invalid_free) {
         asan_free(ptr, &stack);
       } else {
@@ -213,17 +213,17 @@ void cf_free(void *ptr, void *info) {
 
 void *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) {
   if (!ptr) {
-    GET_STACK_TRACE_HERE_FOR_MALLOC;
+    GET_STACK_TRACE_MALLOC;
     return asan_malloc(size, &stack);
   } else {
     if (asan_mz_size(ptr)) {
-      GET_STACK_TRACE_HERE_FOR_MALLOC;
+      GET_STACK_TRACE_MALLOC;
       return asan_realloc(ptr, size, &stack);
     } else {
       // We can't recover from reallocating an unknown address, because
       // this would require reading at most |size| bytes from
       // potentially unaccessible memory.
-      GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+      GET_STACK_TRACE_FREE;
       GET_ZONE_FOR_PTR(ptr);
       ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
     }
@@ -232,17 +232,17 @@ void *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) {
 
 void *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) {
   if (!ptr) {
-    GET_STACK_TRACE_HERE_FOR_MALLOC;
+    GET_STACK_TRACE_MALLOC;
     return asan_malloc(size, &stack);
   } else {
     if (asan_mz_size(ptr)) {
-      GET_STACK_TRACE_HERE_FOR_MALLOC;
+      GET_STACK_TRACE_MALLOC;
       return asan_realloc(ptr, size, &stack);
     } else {
       // We can't recover from reallocating an unknown address, because
       // this would require reading at most |size| bytes from
       // potentially unaccessible memory.
-      GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+      ET_STACK_TRACE_FREE(ptr);
       GET_ZONE_FOR_PTR(ptr);
       ReportMacCfReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
     }
@@ -261,7 +261,7 @@ void *mz_memalign(malloc_zone_t *zone, size_t align, size_t size) {
     CHECK(system_malloc_zone);
     return malloc_zone_memalign(system_malloc_zone, align, size);
   }
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_memalign(align, size, &stack);
 }
 
index 3ec76d8..0ddc3ca 100644 (file)
@@ -31,7 +31,7 @@ using namespace __asan;  // NOLINT
 
 extern "C" {
 void free(void *ptr) {
-  GET_STACK_TRACE_HERE_FOR_FREE(ptr);
+  GET_STACK_TRACE_FREE;
   return asan_free(ptr, &stack);
 }
 
@@ -44,7 +44,7 @@ void cfree(void *ptr) {
 }
 
 void *malloc(size_t size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_malloc(size, &stack);
 }
 
@@ -53,7 +53,7 @@ void* _malloc_dbg(size_t size, int , const char*, int) {
 }
 
 void *calloc(size_t nmemb, size_t size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_calloc(nmemb, size, &stack);
 }
 
@@ -66,7 +66,7 @@ void *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) {
 }
 
 void *realloc(void *ptr, size_t size) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_realloc(ptr, size, &stack);
 }
 
@@ -85,7 +85,7 @@ void* _recalloc(void* p, size_t n, size_t elem_size) {
 }
 
 size_t _msize(void *ptr) {
-  GET_STACK_TRACE_HERE_FOR_MALLOC;
+  GET_STACK_TRACE_MALLOC;
   return asan_malloc_usable_size(ptr, &stack);
 }
 
index 756810d..e21aa45 100644 (file)
@@ -36,7 +36,7 @@ struct nothrow_t {};
 }  // namespace std
 
 #define OPERATOR_NEW_BODY \
-  GET_STACK_TRACE_HERE_FOR_MALLOC;\
+  GET_STACK_TRACE_MALLOC;\
   return asan_memalign(0, size, &stack);
 
 INTERCEPTOR_ATTRIBUTE
@@ -49,7 +49,7 @@ INTERCEPTOR_ATTRIBUTE
 void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
 
 #define OPERATOR_DELETE_BODY \
-  GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
+  GET_STACK_TRACE_FREE;\
   asan_free(ptr, &stack);
 
 INTERCEPTOR_ATTRIBUTE
index 558e4f2..5ad9115 100644 (file)
@@ -358,7 +358,7 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
              (void*)addr, (void*)pc, (void*)sp, (void*)bp,
              asanThreadRegistry().GetCurrentTidOrInvalid());
   Printf("AddressSanitizer can not provide additional info.\n");
-  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
+  GET_STACK_TRACE_FATAL(pc, bp);
   PrintStack(&stack);
 }
 
@@ -506,7 +506,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
              access_size, (void*)addr, curr_tid,
              ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
 
-  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
+  GET_STACK_TRACE_FATAL(pc, bp);
   PrintStack(&stack);
 
   DescribeAddress(addr, access_size);
index 37c9583..e186d95 100644 (file)
@@ -104,6 +104,8 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
   ParseFlag(str, &f->allow_reexec, "allow_reexec");
   ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
   ParseFlag(str, &f->log_path, "log_path");
+  ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
+  ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
 }
 
 void InitializeFlags(Flags *f, const char *env) {
@@ -137,6 +139,8 @@ void InitializeFlags(Flags *f, const char *env) {
   f->allow_reexec = true;
   f->print_full_thread_history = true;
   f->log_path = 0;
+  f->fast_unwind_on_fatal = true;
+  f->fast_unwind_on_malloc = true;
 
   // Override from user-specified string.
   ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
index 99f2cac..46c9f34 100644 (file)
 #define ASAN_STACK_H
 
 #include "sanitizer_common/sanitizer_stacktrace.h"
+#include "asan_flags.h"
 
 namespace __asan {
 
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp);
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast);
 void PrintStack(StackTrace *stack);
 
 }  // namespace __asan
@@ -27,27 +28,38 @@ void PrintStack(StackTrace *stack);
 // The pc will be in the position 0 of the resulting stack trace.
 // The bp may refer to the current frame or to the caller's frame.
 // fast_unwind is currently unused.
-#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp)               \
+#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast)     \
   StackTrace stack;                                             \
-  GetStackTrace(&stack, max_s, pc, bp)
+  GetStackTrace(&stack, max_s, pc, bp, fast)
 
 // 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)                        \
+#define GET_STACK_TRACE(max_size, fast)                       \
   GET_STACK_TRACE_WITH_PC_AND_BP(max_size,                    \
-      StackTrace::GetCurrentPc(), GET_CURRENT_FRAME())
+      StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), fast)
 
-#define GET_STACK_TRACE_HERE_FOR_MALLOC                             \
-  GET_STACK_TRACE_HERE(flags()->malloc_context_size)
+#define GET_STACK_TRACE_FATAL(pc, bp)                                 \
+  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp,              \
+                                 flags()->fast_unwind_on_fatal)
 
-#define GET_STACK_TRACE_HERE_FOR_FREE(ptr)                          \
-  GET_STACK_TRACE_HERE(flags()->malloc_context_size)
+#define GET_STACK_TRACE_FATAL_HERE                           \
+  GET_STACK_TRACE(kStackTraceMax, flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_THREAD                              \
+  GET_STACK_TRACE(kStackTraceMax, true)
+
+#define GET_STACK_TRACE_MALLOC                             \
+  GET_STACK_TRACE(flags()->malloc_context_size,            \
+                  flags()->fast_unwind_on_malloc)
+
+#define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
 
 #define PRINT_CURRENT_STACK()                    \
   {                                              \
-    GET_STACK_TRACE_HERE(kStackTraceMax);        \
+    GET_STACK_TRACE(kStackTraceMax,              \
+      flags()->fast_unwind_on_fatal);            \
     PrintStack(&stack);                          \
   }
 
index 5be76e9..6a0f261 100644 (file)
@@ -19,6 +19,7 @@
 #include "sanitizer_mutex.h"
 #include "sanitizer_placement_new.h"
 #include "sanitizer_procmaps.h"
+#include "sanitizer_stacktrace.h"
 
 #include <fcntl.h>
 #include <pthread.h>
@@ -30,6 +31,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <unwind.h>
 #include <errno.h>
 #include <sys/prctl.h>
 
@@ -378,6 +380,47 @@ bool SanitizerGetThreadName(char *name, int max_len) {
   return true;
 }
 
+//------------------------- SlowUnwindStack -----------------------------------
+#ifdef __arm__
+#define UNWIND_STOP _URC_END_OF_STACK
+#define UNWIND_CONTINUE _URC_NO_REASON
+#else
+#define UNWIND_STOP _URC_NORMAL_STOP
+#define UNWIND_CONTINUE _URC_NO_REASON
+#endif
+
+uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
+#ifdef __arm__
+  uptr val;
+  _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
+      15 /* r15 = PC */, _UVRSD_UINT32, &val);
+  CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
+  // Clear the Thumb bit.
+  return val & ~(uptr)1;
+#else
+  return _Unwind_GetIP(ctx);
+#endif
+}
+
+_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
+  StackTrace *b = (StackTrace*)param;
+  CHECK(b->size < b->max_size);
+  uptr pc = Unwind_GetIP(ctx);
+  b->trace[b->size++] = pc;
+  if (b->size == b->max_size) return UNWIND_STOP;
+  return UNWIND_CONTINUE;
+}
+
+void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth, uptr frames_to_pop) {
+  this->size = 0;
+  this->trace[0] = pc;
+  this->max_size = max_depth;
+  if (max_depth > 1) {
+    _Unwind_Backtrace(Unwind_Trace, this);
+    this->PopStackFrames(frames_to_pop);
+  }
+}
+
 }  // namespace __sanitizer
 
 #endif  // __linux__
index fe2dcf0..64979ec 100644 (file)
@@ -44,6 +44,7 @@ struct StackTrace {
   }
 
   void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom);
+  void SlowUnwindStack(uptr pc, uptr max_depth, uptr frames_to_pop);
 
   void PopStackFrames(uptr count);