[PATCH] Test failures in GCC ASan testsuite on ARM Linux due to FP format mismatch between libsanitizer and GCC.

Maxim Ostapenko m.ostapenko at partner.samsung.com
Sun Jul 27 23:44:17 PDT 2014


Hi kcc, samsonov,

Fast unwind works wrong in GCC 4.10 on ARM Linux due to FP format mismatch between libsanitizer and GCC. This is related bug in GCC (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61771).

http://reviews.llvm.org/D4692

Files:
  lib/sanitizer_common/sanitizer_stacktrace.cc

Index: lib/sanitizer_common/sanitizer_stacktrace.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stacktrace.cc
+++ lib/sanitizer_common/sanitizer_stacktrace.cc
@@ -36,19 +36,39 @@
   return GET_CALLER_PC();
 }
 
+// Check if given pointer points into allocated stack area.
+static inline int IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) {
+  return frame > stack_bottom && frame < stack_top - 2;
+}
+
+// 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 uhwptr *GetCanonicFrame(uptr bp, uptr stack_top, uptr stack_bottom) {
+  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;
+#ifdef __arm__
+  --bp_prev;
+#endif
+  return bp_prev;
+}
+
 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;
+  stack_bottom = Max(stack_bottom, (uptr)&size);
+  uhwptr *frame = GetCanonicFrame(bp, stack_top, stack_bottom);
+  uhwptr *prev_frame = 0;
   if (stack_top < 4096) return;  // Sanity check for stack top.
   // 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 @@
       trace[size++] = (uptr) pc1;
     }
     prev_frame = frame;
-    frame = (uhwptr *)frame[0];
+    frame = GetCanonicFrame((uptr)frame[0], stack_top, stack_bottom);
   }
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4692.11933.patch
Type: text/x-patch
Size: 2078 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140728/3ae3ea1b/attachment.bin>


More information about the llvm-commits mailing list