[compiler-rt] r217079 - Fix fast stack unwind on ARM to support code generated with GCC.

Alexey Samsonov vonosmas at gmail.com
Wed Sep 3 14:10:44 PDT 2014


Author: samsonov
Date: Wed Sep  3 16:10:44 2014
New Revision: 217079

URL: http://llvm.org/viewvc/llvm-project?rev=217079&view=rev
Log:
Fix fast stack unwind on ARM to support code generated with GCC.

http://reviews.llvm.org/D4692

Patch by Maxim Ostapenko!

Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/clang_gcc_abi.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc?rev=217079&r1=217078&r2=217079&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc Wed Sep  3 16:10:44 2014
@@ -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
       trace[size++] = (uptr) pc1;
     }
     prev_frame = frame;
-    frame = (uhwptr *)frame[0];
+    frame = GetCanonicFrame((uptr)frame[0], stack_top, stack_bottom);
   }
 }
 

Added: compiler-rt/trunk/test/asan/TestCases/Linux/clang_gcc_abi.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/clang_gcc_abi.cc?rev=217079&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/clang_gcc_abi.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/clang_gcc_abi.cc Wed Sep  3 16:10:44 2014
@@ -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]]
+}





More information about the llvm-commits mailing list