[PATCH] [ASan] Speed up stack trace unwinding for stacks of size 2.

Alexey Samsonov samsonov at google.com
Tue Mar 4 05:03:46 PST 2014


Hi eugenis, ygribov,

We don't need to do any work in this case - just take
the current PC and caller PC.

http://llvm-reviews.chandlerc.com/D2936

Files:
  lib/asan/asan_linux.cc
  lib/asan/asan_stack.h
  lib/asan/asan_allocator2.cc
  lib/asan/asan_thread.h
  test/asan/TestCases/malloc_context_size.cc

Index: lib/asan/asan_linux.cc
===================================================================
--- lib/asan/asan_linux.cc
+++ lib/asan/asan_linux.cc
@@ -18,6 +18,7 @@
 #include "asan_interceptors.h"
 #include "asan_internal.h"
 #include "asan_thread.h"
+#include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
 
Index: lib/asan/asan_stack.h
===================================================================
--- lib/asan/asan_stack.h
+++ lib/asan/asan_stack.h
@@ -19,48 +19,64 @@
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
 
+namespace __asan {
+
 // Get the stack trace with the given pc and bp.
 // 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.
+ALWAYS_INLINE
+void GetStackTraceWithPcBpAndContext(StackTrace *stack, uptr max_depth, uptr pc,
+                                     uptr bp, void *context, bool fast) {
 #if SANITIZER_WINDOWS
-#define GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(max_s, pc, bp, context, fast) \
-  StackTrace stack;                                                          \
-  stack.Unwind(max_s, pc, bp, context, 0, 0, fast)
+  stack->Unwind(max_depth, pc, bp, context, 0, 0, fast);
 #else
-#define GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(max_s, pc, bp, context, fast)   \
-  StackTrace stack;                                                            \
-  {                                                                            \
-    AsanThread *t;                                                             \
-    stack.size = 0;                                                            \
-    if (asan_inited) {                                                         \
-      if ((t = GetCurrentThread()) && !t->isUnwinding()) {                     \
-        uptr stack_top = t->stack_top();                                       \
-        uptr stack_bottom = t->stack_bottom();                                 \
-        ScopedUnwinding unwind_scope(t);                                       \
-        stack.Unwind(max_s, pc, bp, context, stack_top, stack_bottom, fast);   \
-      } else if (t == 0 && !fast) {                                            \
-        /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ \
-        stack.Unwind(max_s, pc, bp, context, 0, 0, false);                     \
-      }                                                                        \
-    }                                                                          \
+  AsanThread *t;
+  stack->size = 0;
+  if (asan_inited) {
+    if ((t = GetCurrentThread()) && !t->isUnwinding()) {
+      uptr stack_top = t->stack_top();
+      uptr stack_bottom = t->stack_bottom();
+      ScopedUnwinding unwind_scope(t);
+      stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast);
+    } else if (t == 0 && !fast) {
+      /* If GetCurrentThread() has failed, try to do slow unwind anyways. */
+      stack->Unwind(max_depth, pc, bp, context, 0, 0, false);
+    }
   }
 #endif  // SANITIZER_WINDOWS
+}
+
+}  // namespace __asan
 
 // 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(max_size, fast)                                        \
-  GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(max_size, StackTrace::GetCurrentPc(), \
-                                         GET_CURRENT_FRAME(), 0, fast)
+  StackTrace stack;                                                            \
+  if (max_size <= 2) {                                                         \
+    stack.size = max_size;                                                     \
+    if (max_size > 0) {                                                        \
+      stack.top_frame_bp = GET_CURRENT_FRAME();                                \
+      stack.trace[0] = StackTrace::GetCurrentPc();                             \
+    }                                                                          \
+    if (max_size > 1)                                                          \
+      stack.trace[1] = GET_CALLER_PC();                                        \
+  } else {                                                                     \
+    GetStackTraceWithPcBpAndContext(&stack, max_size,                          \
+                                    StackTrace::GetCurrentPc(),                \
+                                    GET_CURRENT_FRAME(), 0, fast);             \
+  }
 
-#define GET_STACK_TRACE_FATAL(pc, bp)                               \
-  GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(kStackTraceMax, pc, bp, 0, \
-                                         common_flags()->fast_unwind_on_fatal)
-
-#define GET_STACK_TRACE_SIGNAL(pc, bp, context)                           \
-  GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(kStackTraceMax, pc, bp, context, \
-                                         common_flags()->fast_unwind_on_fatal)
+#define GET_STACK_TRACE_FATAL(pc, bp)                                          \
+  StackTrace stack;                                                            \
+  GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0,           \
+                                  common_flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_SIGNAL(pc, bp, context)                                \
+  StackTrace stack;                                                            \
+  GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context,     \
+                                  common_flags()->fast_unwind_on_fatal)
 
 #define GET_STACK_TRACE_FATAL_HERE                                \
   GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
Index: lib/asan/asan_allocator2.cc
===================================================================
--- lib/asan/asan_allocator2.cc
+++ lib/asan/asan_allocator2.cc
@@ -19,6 +19,7 @@
 #include "asan_mapping.h"
 #include "asan_poisoning.h"
 #include "asan_report.h"
+#include "asan_stack.h"
 #include "asan_thread.h"
 #include "sanitizer_common/sanitizer_allocator.h"
 #include "sanitizer_common/sanitizer_flags.h"
Index: lib/asan/asan_thread.h
===================================================================
--- lib/asan/asan_thread.h
+++ lib/asan/asan_thread.h
@@ -17,7 +17,6 @@
 #include "asan_allocator.h"
 #include "asan_internal.h"
 #include "asan_fake_stack.h"
-#include "asan_stack.h"
 #include "asan_stats.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_libc.h"
Index: test/asan/TestCases/malloc_context_size.cc
===================================================================
--- test/asan/TestCases/malloc_context_size.cc
+++ test/asan/TestCases/malloc_context_size.cc
@@ -3,6 +3,7 @@
 // RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os
 // RUN: ASAN_OPTIONS=malloc_context_size=1:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os
 // RUN: ASAN_OPTIONS=malloc_context_size=1:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os
+// RUN: ASAN_OPTIONS=malloc_context_size=2 not %t 2>&1 | FileCheck %s --check-prefix=TWO
 
 int main() {
   char *x = new char[20];
@@ -24,4 +25,9 @@
   // CHECK-NOT: #1 0x{{.*}}
 
   // CHECK: SUMMARY: AddressSanitizer: heap-use-after-free
+
+  // TWO: previously allocated by thread T{{.*}} here:
+  // TWO-NEXT: #0 0x{{.*}}
+  // TWO-NEXT: #1 0x{{.*}} in main {{.*}}malloc_context_size.cc
+  // TWO: SUMMARY: AddressSanitizer: heap-use-after-free
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2936.1.patch
Type: text/x-patch
Size: 7867 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140304/d0e350f5/attachment.bin>


More information about the llvm-commits mailing list