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__