[sanitizer] Move GetStackTrace from ASan to sanitizer_common.

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@181424 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc
index 148b5f0..17bb4ca 100644
--- a/lib/asan/asan_linux.cc
+++ b/lib/asan/asan_linux.cc
@@ -102,24 +102,6 @@
   // Nothing here for now.
 }
 
-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
-  if (!fast)
-    return stack->SlowUnwindStack(pc, max_s);
-  stack->size = 0;
-  stack->trace[0] = pc;
-  if (max_s > 1) {
-    stack->max_size = max_s;
-    if (!asan_inited) return;
-    if (AsanThread *t = GetCurrentThread())
-      stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
-  }
-}
-
 #if !SANITIZER_ANDROID
 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   ucontext_t *ucp = (ucontext_t*)context;
diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc
index 63fb5f6..4313534 100644
--- a/lib/asan/asan_mac.cc
+++ b/lib/asan/asan_mac.cc
@@ -229,18 +229,6 @@
 void AsanPlatformThreadInit() {
 }
 
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
-  (void)fast;
-  stack->size = 0;
-  stack->trace[0] = pc;
-  if ((max_s) > 1) {
-    stack->max_size = max_s;
-    if (!asan_inited) return;
-    if (AsanThread *t = GetCurrentThread())
-      stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
-  }
-}
-
 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   UNIMPLEMENTED();
 }
diff --git a/lib/asan/asan_stack.h b/lib/asan/asan_stack.h
index cd30abb..176aa18 100644
--- a/lib/asan/asan_stack.h
+++ b/lib/asan/asan_stack.h
@@ -15,12 +15,12 @@
 #define ASAN_STACK_H
 
 #include "asan_flags.h"
+#include "asan_thread.h"
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
 
 namespace __asan {
 
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast);
 void PrintStack(StackTrace *stack);
 
 }  // namespace __asan
@@ -28,10 +28,24 @@
 // 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.
-// fast_unwind is currently unused.
+#if SANITIZER_WINDOWS
 #define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast)     \
   StackTrace stack;                                             \
-  GetStackTrace(&stack, max_s, pc, bp, fast)
+  GetStackTrace(&stack, max_s, pc, bp, 0, 0, fast)
+#else
+#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast)     \
+  StackTrace stack;                                             \
+  {                                                             \
+    uptr stack_top = 0, stack_bottom = 0;                       \
+    AsanThread *t;                                              \
+    if (asan_inited && (t = GetCurrentThread())) {              \
+      stack_top = t->stack_top();                               \
+      stack_bottom = t->stack_bottom();                         \
+    }                                                           \
+    GetStackTrace(&stack, max_s, pc, bp,                        \
+                  stack_top, stack_bottom, fast);               \
+  }
+#endif  // SANITIZER_WINDOWS
 
 // 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
diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc
index 49a3899..f74de72 100644
--- a/lib/asan/asan_win.cc
+++ b/lib/asan/asan_win.cc
@@ -32,30 +32,6 @@
 static bool dbghelp_initialized = false;
 #pragma comment(lib, "dbghelp.lib")
 
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
-  (void)fast;
-  stack->max_size = max_s;
-  void *tmp[kStackTraceMax];
-
-  // FIXME: CaptureStackBackTrace might be too slow for us.
-  // FIXME: Compare with StackWalk64.
-  // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
-  uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
-  uptr offset = 0;
-  // Skip the RTL frames by searching for the PC in the stacktrace.
-  // FIXME: this doesn't work well for the malloc/free stacks yet.
-  for (uptr i = 0; i < cs_ret; i++) {
-    if (pc != (uptr)tmp[i])
-      continue;
-    offset = i;
-    break;
-  }
-
-  stack->size = cs_ret - offset;
-  for (uptr i = 0; i < stack->size; i++)
-    stack->trace[i] = (uptr)tmp[i + offset];
-}
-
 // ---------------------- TSD ---------------- {{{1
 static bool tsd_key_inited = false;
 
diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc
index 2aae414..7fec5cf 100644
--- a/lib/sanitizer_common/sanitizer_posix.cc
+++ b/lib/sanitizer_common/sanitizer_posix.cc
@@ -18,6 +18,7 @@
 #include "sanitizer_common.h"
 #include "sanitizer_libc.h"
 #include "sanitizer_procmaps.h"
+#include "sanitizer_stacktrace.h"
 
 #include <errno.h>
 #include <pthread.h>
@@ -228,6 +229,26 @@
   return isatty(fd);
 }
 
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
+                   uptr stack_top, uptr stack_bottom, bool fast) {
+#if !SANITIZER_CAN_FAST_UNWIND
+  fast = false;
+#endif
+#if SANITIZER_MAC
+  // Always unwind fast on Mac.
+  (void)fast;
+#else
+  if (!fast || (stack_top == stack_bottom))
+    return stack->SlowUnwindStack(pc, max_s);
+#endif  // SANITIZER_MAC
+  stack->size = 0;
+  stack->trace[0] = pc;
+  if (max_s > 1) {
+    stack->max_size = max_s;
+    stack->FastUnwindStack(pc, bp, stack_top, stack_bottom);
+  }
+}
+
 }  // namespace __sanitizer
 
-#endif  // SANITIZER_LINUX || __APPLE_
+#endif  // SANITIZER_LINUX || SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_stacktrace.h b/lib/sanitizer_common/sanitizer_stacktrace.h
index b9ea9b4..fcfdd7e 100644
--- a/lib/sanitizer_common/sanitizer_stacktrace.h
+++ b/lib/sanitizer_common/sanitizer_stacktrace.h
@@ -19,6 +19,14 @@
 
 static const uptr kStackTraceMax = 256;
 
+#if SANITIZER_LINUX && (defined(__arm__) || \
+    defined(__powerpc__) || defined(__powerpc64__) || \
+    defined(__sparc__))
+#define SANITIZER_CAN_FAST_UNWIND 0
+#else
+#define SANITIZER_CAN_FAST_UNWIND 1
+#endif
+
 struct StackTrace {
   typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
                                      int out_size);
@@ -61,6 +69,9 @@
 const char *StripPathPrefix(const char *filepath,
                             const char *strip_file_prefix);
 
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
+                   uptr stack_top, uptr stack_bottom, bool fast);
+
 }  // namespace __sanitizer
 
 // Use this macro if you want to print stack trace with the caller
diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc
index 48874a1..95445be 100644
--- a/lib/sanitizer_common/sanitizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_win.cc
@@ -23,8 +23,9 @@
 
 #include "sanitizer_common.h"
 #include "sanitizer_libc.h"
-#include "sanitizer_placement_new.h"
 #include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_stacktrace.h"
 
 namespace __sanitizer {
 
@@ -346,6 +347,33 @@
   *tls_size = 0;
 }
 
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
+                   uptr stack_top, uptr stack_bottom, bool fast) {
+  (void)fast;
+  (void)stack_top;
+  (void)stack_bottom;
+  stack->max_size = max_s;
+  void *tmp[kStackTraceMax];
+
+  // FIXME: CaptureStackBackTrace might be too slow for us.
+  // FIXME: Compare with StackWalk64.
+  // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
+  uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
+  uptr offset = 0;
+  // Skip the RTL frames by searching for the PC in the stacktrace.
+  // FIXME: this doesn't work well for the malloc/free stacks yet.
+  for (uptr i = 0; i < cs_ret; i++) {
+    if (pc != (uptr)tmp[i])
+      continue;
+    offset = i;
+    break;
+  }
+
+  stack->size = cs_ret - offset;
+  for (uptr i = 0; i < stack->size; i++)
+    stack->trace[i] = (uptr)tmp[i + offset];
+}
+
 }  // namespace __sanitizer
 
 #endif  // _WIN32