summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-09-03 21:10:44 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-09-03 21:10:44 +0000
commitc8d8ca0bd67c65e209a85d16fb4b4ec6dfaab65f (patch)
tree2a08628701df200fb3ec47b0a67e82e972dd1f57
parent0e3e6155fe5b951d6b04c9f78de816d91a3a2699 (diff)
downloadbcm5719-llvm-c8d8ca0bd67c65e209a85d16fb4b4ec6dfaab65f.tar.gz
bcm5719-llvm-c8d8ca0bd67c65e209a85d16fb4b4ec6dfaab65f.zip
Fix fast stack unwind on ARM to support code generated with GCC.
http://reviews.llvm.org/D4692 Patch by Maxim Ostapenko! llvm-svn: 217079
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc30
-rw-r--r--compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc43
2 files changed, 68 insertions, 5 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
index 35396392a0f..21f710ddd83 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
@@ -36,19 +36,39 @@ uptr StackTrace::GetCurrentPc() {
return GET_CALLER_PC();
}
+// Check if given pointer points into allocated stack area.
+static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) {
+ return frame > stack_bottom && frame < stack_top - 2 * sizeof (uhwptr);
+}
+
+// In GCC on ARM bp points to saved lr, not fp, so we should check the next
+// cell in stack to be a saved frame pointer. GetCanonicFrame returns the
+// pointer to saved frame pointer in any case.
+static inline uhwptr *GetCanonicFrame(uptr bp,
+ uptr stack_top,
+ uptr stack_bottom) {
+#ifdef __arm__
+ if (!IsValidFrame(bp, stack_top, stack_bottom)) return 0;
+ uhwptr *bp_prev = (uhwptr *)bp;
+ if (IsValidFrame((uptr)bp_prev[0], stack_top, stack_bottom)) return bp_prev;
+ return bp_prev - 1;
+#else
+ return (uhwptr*)bp;
+#endif
+}
+
void StackTrace::FastUnwindStack(uptr pc, uptr bp,
uptr stack_top, uptr stack_bottom,
uptr max_depth) {
CHECK_GE(max_depth, 2);
trace[0] = pc;
size = 1;
- uhwptr *frame = (uhwptr *)bp;
- uhwptr *prev_frame = frame - 1;
if (stack_top < 4096) return; // Sanity check for stack top.
+ uhwptr *frame = GetCanonicFrame(bp, stack_top, stack_bottom);
+ uhwptr *prev_frame = 0;
// Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
while (frame > prev_frame &&
- frame < (uhwptr *)stack_top - 2 &&
- frame > (uhwptr *)stack_bottom &&
+ IsValidFrame((uptr)frame, stack_top, stack_bottom) &&
IsAligned((uptr)frame, sizeof(*frame)) &&
size < max_depth) {
uhwptr pc1 = frame[1];
@@ -56,7 +76,7 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp,
trace[size++] = (uptr) pc1;
}
prev_frame = frame;
- frame = (uhwptr *)frame[0];
+ frame = GetCanonicFrame((uptr)frame[0], stack_top, stack_bottom);
}
}
diff --git a/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc b/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc
new file mode 100644
index 00000000000..9f55485edc1
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc
@@ -0,0 +1,43 @@
+// RUN: %clangxx_asan -O0 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: arm-supported-target
+
+#include <stdlib.h>
+
+int boom() {
+ volatile int three = 3;
+ char *s = (char *)malloc(three);
+// CHECK: #1 0x{{.*}} in boom {{.*}}clang_gcc_abi.cc:[[@LINE-1]]
+ return s[three]; //BOOM
+}
+
+__attribute__((naked, noinline)) void gcc_abi() {
+// CHECK: #2 0x{{.*}} in gcc_abi {{.*}}clang_gcc_abi.cc:[[@LINE+1]]
+ asm volatile("str fp, [sp, #-8]!\n\t"
+ "str lr, [sp, #4]\n\t"
+ "add fp, sp, #4\n\t"
+ "bl boom\n\t"
+ "sub sp, fp, #4\n\t"
+ "ldr fp, [sp]\n\t"
+ "add sp, sp, #4\n\t"
+ "ldr pc, [sp], #4\n\t"
+ );
+}
+
+__attribute__((naked, noinline)) void clang_abi() {
+// CHECK: #3 0x{{.*}} in clang_abi {{.*}}clang_gcc_abi.cc:[[@LINE+1]]
+ asm volatile("push {r11, lr}\n\t"
+ "mov r11, sp\n\t"
+ "bl gcc_abi\n\t"
+ "add r0, r0, #1\n\t"
+ "pop {r11, pc}\n\t"
+ );
+}
+
+int main() {
+ clang_abi();
+// CHECK: #4 0x{{.*}} in main {{.*}}clang_gcc_abi.cc:[[@LINE-1]]
+}
OpenPOWER on IntegriCloud