EHABI-based stack trace on ARM.

The change removes the unused FLAG_fast_unwind, and forces EHABI-based unwind
on ARM, and fast (FP-based) unwind everywhere else.


git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@148468 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc
index ae45b82..7547b8b 100644
--- a/lib/asan/asan_linux.cc
+++ b/lib/asan/asan_linux.cc
@@ -29,6 +29,7 @@
 #include <pthread.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <unwind.h>
 
 #ifndef ANDROID
 // FIXME: where to get ucontext on Android?
@@ -338,6 +339,50 @@
   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
+
+uintptr_t Unwind_GetIP(struct _Unwind_Context *ctx) {
+#ifdef __arm__
+  uintptr_t 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 & ~(uintptr_t)1;
+#else
+  return _Unwind_GetIP(ctx);
+#endif
+}
+
+_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
+    void *param) {
+  AsanStackTrace *b = (AsanStackTrace*)param;
+  CHECK(b->size < b->max_size);
+  uintptr_t pc = Unwind_GetIP(ctx);
+  b->trace[b->size++] = pc;
+  if (b->size == b->max_size) return UNWIND_STOP;
+  return UNWIND_CONTINUE;
+}
+
+void AsanStackTrace::GetStackTrace(size_t max_s, uintptr_t pc, uintptr_t bp) {
+  size = 0;
+  trace[0] = pc;
+  if ((max_s) > 1) {
+    max_size = max_s;
+#ifdef __arm__
+    _Unwind_Backtrace(Unwind_Trace, this);
+#else
+     FastUnwindStack(pc, bp);
+#endif
+  }
+}
+
 }  // namespace __asan
 
 #endif  // __linux__