[compiler-rt] r191510 - [asan] introduce run-time flag uar_stack_size_log to control the size of FakeStack; don't crash when the fake stack is exhausted, move some code to .cc file

Kostya Serebryany kcc at google.com
Fri Sep 27 04:37:23 PDT 2013


Author: kcc
Date: Fri Sep 27 06:37:23 2013
New Revision: 191510

URL: http://llvm.org/viewvc/llvm-project?rev=191510&view=rev
Log:
[asan] introduce run-time flag uar_stack_size_log to control the size of FakeStack; don't crash when the fake stack is exhausted, move some code to .cc file

Modified:
    compiler-rt/trunk/lib/asan/asan_fake_stack.cc
    compiler-rt/trunk/lib/asan/asan_fake_stack.h
    compiler-rt/trunk/lib/asan/asan_flags.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/asan/asan_thread.cc
    compiler-rt/trunk/lib/asan/lit_tests/TestCases/stack-use-after-return.cc
    compiler-rt/trunk/lib/asan/tests/asan_fake_stack_test.cc

Modified: compiler-rt/trunk/lib/asan/asan_fake_stack.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_fake_stack.cc?rev=191510&r1=191509&r2=191510&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fake_stack.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_fake_stack.cc Fri Sep 27 06:37:23 2013
@@ -35,6 +35,30 @@ ALWAYS_INLINE void SetShadow(uptr ptr, u
   }
 }
 
+FakeStack *FakeStack::Create(uptr stack_size_log) {
+  static uptr kMinStackSizeLog = 16;
+  static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(24, 28);
+  if (stack_size_log < kMinStackSizeLog)
+    stack_size_log = kMinStackSizeLog;
+  if (stack_size_log > kMaxStackSizeLog)
+    stack_size_log = kMaxStackSizeLog;
+  FakeStack *res = reinterpret_cast<FakeStack *>(
+      MmapOrDie(RequiredSize(stack_size_log), "FakeStack"));
+  res->stack_size_log_ = stack_size_log;
+  if (flags()->verbosity) {
+    u8 *p = reinterpret_cast<u8 *>(res);
+    Report("T%d: FakeStack created: %p -- %p stack_size_log: %zd \n",
+           GetCurrentTidOrInvalid(), p,
+           p + FakeStack::RequiredSize(stack_size_log), stack_size_log);
+  }
+  return res;
+}
+
+void FakeStack::Destroy() {
+  PoisonAll(0);
+  UnmapOrDie(this, RequiredSize(stack_size_log_));
+}
+
 void FakeStack::PoisonAll(u8 magic) {
   PoisonShadow(reinterpret_cast<uptr>(this), RequiredSize(stack_size_log()),
                magic);
@@ -66,8 +90,7 @@ FakeFrame *FakeStack::Allocate(uptr stac
     *SavedFlagPtr(reinterpret_cast<uptr>(res), class_id) = &flags[pos];
     return res;
   }
-  CHECK(0 && "Failed to allocate a fake stack frame");
-  return 0;
+  return 0; // We are out of fake stack.
 }
 
 uptr FakeStack::AddrIsInFakeStack(uptr ptr) {
@@ -143,6 +166,8 @@ ALWAYS_INLINE uptr OnMalloc(uptr class_i
   FakeStack *fs = GetFakeStackFast();
   if (!fs) return real_stack;
   FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, real_stack);
+  if (!ff)
+    return real_stack;  // Out of fake stack, return the real one.
   uptr ptr = reinterpret_cast<uptr>(ff);
   SetShadow(ptr, size, class_id, 0);
   return ptr;

Modified: compiler-rt/trunk/lib/asan/asan_fake_stack.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_fake_stack.h?rev=191510&r1=191509&r2=191510&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fake_stack.h (original)
+++ compiler-rt/trunk/lib/asan/asan_fake_stack.h Fri Sep 27 06:37:23 2013
@@ -63,23 +63,9 @@ class FakeStack {
        kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
 
   // CTOR: create the FakeStack as a single mmap-ed object.
-  static FakeStack *Create(uptr stack_size_log) {
-    static uptr kMinStackSizeLog = 16;
-    static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(23, 26);
-    if (stack_size_log < kMinStackSizeLog)
-      stack_size_log = kMinStackSizeLog;
-    if (stack_size_log > kMaxStackSizeLog)
-      stack_size_log = kMaxStackSizeLog;
-    FakeStack *res = reinterpret_cast<FakeStack *>(
-        MmapOrDie(RequiredSize(stack_size_log), "FakeStack"));
-    res->stack_size_log_ = stack_size_log;
-    return res;
-  }
+  static FakeStack *Create(uptr stack_size_log);
 
-  void Destroy() {
-    PoisonAll(0);
-    UnmapOrDie(this, RequiredSize(stack_size_log_));
-  }
+  void Destroy();
 
   // stack_size_log is at least 15 (stack_size >= 32K).
   static uptr SizeRequiredForFlags(uptr stack_size_log) {

Modified: compiler-rt/trunk/lib/asan/asan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.h?rev=191510&r1=191509&r2=191510&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.h (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.h Fri Sep 27 06:37:23 2013
@@ -54,6 +54,8 @@ struct Flags {
   bool mac_ignore_invalid_free;
   // Enables stack-use-after-return checking at run-time.
   bool detect_stack_use_after_return;
+  // The minimal fake stack size log.
+  int uar_stack_size_log;
   // ASan allocator flag. max_malloc_fill_size is the maximal amount of bytes
   // that will be filled with malloc_fill_byte on malloc.
   int max_malloc_fill_size, malloc_fill_byte;

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=191510&r1=191509&r2=191510&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Fri Sep 27 06:37:23 2013
@@ -106,6 +106,7 @@ static void ParseFlagsFromString(Flags *
   ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
   ParseFlag(str, &f->detect_stack_use_after_return,
             "detect_stack_use_after_return");
+  ParseFlag(str, &f->uar_stack_size_log, "uar_stack_size_log");
   ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
   ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte");
   ParseFlag(str, &f->exitcode, "exitcode");
@@ -154,6 +155,7 @@ void InitializeFlags(Flags *f, const cha
   f->replace_intrin = true;
   f->mac_ignore_invalid_free = false;
   f->detect_stack_use_after_return = false;  // Also needs the compiler flag.
+  f->uar_stack_size_log = 0;
   f->max_malloc_fill_size = 0x1000;  // By default, fill only the first 4K.
   f->malloc_fill_byte = 0xbe;
   f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;

Modified: compiler-rt/trunk/lib/asan/asan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread.cc?rev=191510&r1=191509&r2=191510&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_thread.cc Fri Sep 27 06:37:23 2013
@@ -124,13 +124,10 @@ FakeStack *AsanThread::AsyncSignalSafeLa
       reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
       memory_order_relaxed)) {
     uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
+    if (flags()->uar_stack_size_log)
+      stack_size_log = static_cast<uptr>(flags()->uar_stack_size_log);
     fake_stack_ = FakeStack::Create(stack_size_log);
     SetTLSFakeStack(fake_stack_);
-    if (flags()->verbosity) {
-      u8 *p = reinterpret_cast<u8 *>(fake_stack_);
-      Report("T%d: FakeStack created: %p -- %p\n", tid(), p,
-             p + FakeStack::RequiredSize(stack_size_log));
-    }
     return fake_stack_;
   }
   return 0;

Modified: compiler-rt/trunk/lib/asan/lit_tests/TestCases/stack-use-after-return.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/TestCases/stack-use-after-return.cc?rev=191510&r1=191509&r2=191510&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/TestCases/stack-use-after-return.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/TestCases/stack-use-after-return.cc Fri Sep 27 06:37:23 2013
@@ -15,6 +15,11 @@
 // Test that we can find UAR in a thread other than main:
 // RUN: %clangxx_asan  -DUseThread -O2 %s -o %t && \
 // RUN:   not %t 2>&1 | FileCheck --check-prefix=THREAD %s
+//
+// Test the uar_stack_size_log flag.
+//
+// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:uar_stack_size_log=20:verbosity=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
+// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:uar_stack_size_log=24:verbosity=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-24 %s
 
 #include <stdio.h>
 #include <pthread.h>
@@ -51,6 +56,8 @@ void Func2(char *x) {
   // THREAD:     #0{{.*}}Func2{{.*}}stack-use-after-return.cc:[[@LINE-6]]
   // THREAD: is located in stack of thread T{{[1-9]}} at offset
   // THREAD: 'local' <== Memory access at offset 32 is inside this variable
+  // CHECK-20: T0: FakeStack created:{{.*}} stack_size_log: 20
+  // CHECK-24: T0: FakeStack created:{{.*}} stack_size_log: 24
 }
 
 void *Thread(void *unused)  {

Modified: compiler-rt/trunk/lib/asan/tests/asan_fake_stack_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_fake_stack_test.cc?rev=191510&r1=191509&r2=191510&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_fake_stack_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_fake_stack_test.cc Fri Sep 27 06:37:23 2013
@@ -119,12 +119,8 @@ TEST(FakeStack, Allocate) {
         EXPECT_EQ(x, fs->AddrIsInFakeStack(x + bytes_in_class - 1));
         EXPECT_NE(x, fs->AddrIsInFakeStack(x + bytes_in_class));
       }
-      if (iter == 0 &&
-          (cid == 0 || cid == FakeStack::kNumberOfSizeClasses - 1)) {
-        // This is slow, so we do it only sometimes.
-        EXPECT_DEATH(fs->Allocate(stack_size_log, cid, 0),
-                     "Failed to allocate a fake stack frame");
-      }
+      // We are out of fake stack, so Allocate should return 0.
+      EXPECT_EQ(0UL, fs->Allocate(stack_size_log, cid, 0));
     }
     for (std::map<FakeFrame *, uptr>::iterator it = s.begin(); it != s.end();
          ++it) {





More information about the llvm-commits mailing list