[compiler-rt] r190406 - [asan] refactor the use-after-return API so that the size class is computed at compile time instead of at run-time. compiler-rt part

Kostya Serebryany kcc at google.com
Tue Sep 10 06:16:26 PDT 2013


Author: kcc
Date: Tue Sep 10 08:16:26 2013
New Revision: 190406

URL: http://llvm.org/viewvc/llvm-project?rev=190406&view=rev
Log:
[asan] refactor the use-after-return API so that the size class is computed at compile time instead of at run-time. compiler-rt part

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_interface_internal.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c
    compiler-rt/trunk/lib/asan/tests/asan_noinst_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=190406&r1=190405&r2=190406&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fake_stack.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_fake_stack.cc Tue Sep 10 08:16:26 2013
@@ -17,20 +17,20 @@
 
 namespace __asan {
 
-bool FakeStack::AddrIsInSizeClass(uptr addr, uptr size_class) {
-  uptr mem = allocated_size_classes_[size_class];
-  uptr size = ClassMmapSize(size_class);
+bool FakeStack::AddrIsInSizeClass(uptr addr, uptr class_id) {
+  uptr mem = allocated_size_classes_[class_id];
+  uptr size = ClassMmapSize(class_id);
   bool res = mem && addr >= mem && addr < mem + size;
   return res;
 }
 
 uptr FakeStack::AddrIsInFakeStack(uptr addr) {
-  for (uptr size_class = 0; size_class < kNumberOfSizeClasses; size_class++) {
-    if (!AddrIsInSizeClass(addr, size_class)) continue;
-    uptr size_class_first_ptr = allocated_size_classes_[size_class];
-    uptr size = ClassSize(size_class);
+  for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) {
+    if (!AddrIsInSizeClass(addr, class_id)) continue;
+    uptr size_class_first_ptr = allocated_size_classes_[class_id];
+    uptr size = ClassSize(class_id);
     CHECK_LE(size_class_first_ptr, addr);
-    CHECK_GT(size_class_first_ptr + ClassMmapSize(size_class), addr);
+    CHECK_GT(size_class_first_ptr + ClassMmapSize(class_id), addr);
     return size_class_first_ptr + ((addr - size_class_first_ptr) / size) * size;
   }
   return 0;
@@ -91,42 +91,42 @@ void FakeStack::Cleanup() {
   }
 }
 
-uptr FakeStack::ClassMmapSize(uptr size_class) {
+uptr FakeStack::ClassMmapSize(uptr class_id) {
   // Limit allocation size to ClassSize * MaxDepth when running with unlimited
   // stack.
-  return RoundUpTo(Min(ClassSize(size_class) * kMaxRecursionDepth, stack_size_),
+  return RoundUpTo(Min(ClassSize(class_id) * kMaxRecursionDepth, stack_size_),
                    GetPageSizeCached());
 }
 
-void FakeStack::AllocateOneSizeClass(uptr size_class) {
-  CHECK(ClassMmapSize(size_class) >= GetPageSizeCached());
+void FakeStack::AllocateOneSizeClass(uptr class_id) {
+  CHECK(ClassMmapSize(class_id) >= GetPageSizeCached());
   uptr new_mem = (uptr)MmapOrDie(
-      ClassMmapSize(size_class), __FUNCTION__);
+      ClassMmapSize(class_id), __FUNCTION__);
   if (0) {
     Printf("T%d new_mem[%zu]: %p-%p mmap %zu\n",
            GetCurrentThread()->tid(),
-           size_class, new_mem, new_mem + ClassMmapSize(size_class),
-           ClassMmapSize(size_class));
+           class_id, new_mem, new_mem + ClassMmapSize(class_id),
+           ClassMmapSize(class_id));
   }
   uptr i;
-  uptr size = ClassSize(size_class);
-  for (i = 0; i + size <= ClassMmapSize(size_class); i += size) {
-    size_classes_[size_class].FifoPush((FakeFrame*)(new_mem + i));
+  uptr size = ClassSize(class_id);
+  for (i = 0; i + size <= ClassMmapSize(class_id); i += size) {
+    size_classes_[class_id].FifoPush((FakeFrame*)(new_mem + i));
   }
-  CHECK_LE(i, ClassMmapSize(size_class));
-  allocated_size_classes_[size_class] = new_mem;
+  CHECK_LE(i, ClassMmapSize(class_id));
+  allocated_size_classes_[class_id] = new_mem;
 }
 
-ALWAYS_INLINE uptr FakeStack::AllocateStack(uptr size, uptr real_stack) {
-  if (!alive_) return real_stack;
+ALWAYS_INLINE uptr
+FakeStack::AllocateStack(uptr class_id, uptr size, uptr real_stack) {
   CHECK(size <= kMaxStackMallocSize && size > 1);
-  uptr size_class = ComputeSizeClass(size);
-  if (!allocated_size_classes_[size_class]) {
-    AllocateOneSizeClass(size_class);
+  if (!alive_) return real_stack;
+  if (!allocated_size_classes_[class_id]) {
+    AllocateOneSizeClass(class_id);
   }
-  FakeFrame *fake_frame = size_classes_[size_class].FifoPop();
+  FakeFrame *fake_frame = size_classes_[class_id].FifoPop();
   CHECK(fake_frame);
-  fake_frame->size_minus_one = size - 1;
+  fake_frame->class_id = class_id;
   fake_frame->real_stack = real_stack;
   while (FakeFrame *top = call_stack_.top()) {
     if (top->real_stack > real_stack) break;
@@ -141,29 +141,23 @@ ALWAYS_INLINE uptr FakeStack::AllocateSt
 
 ALWAYS_INLINE void FakeStack::DeallocateFrame(FakeFrame *fake_frame) {
   CHECK(alive_);
-  uptr size = static_cast<uptr>(fake_frame->size_minus_one + 1);
-  uptr size_class = ComputeSizeClass(size);
-  CHECK(allocated_size_classes_[size_class]);
+  uptr class_id = static_cast<uptr>(fake_frame->class_id);
+  CHECK(allocated_size_classes_[class_id]);
   uptr ptr = (uptr)fake_frame;
-  CHECK(AddrIsInSizeClass(ptr, size_class));
-  CHECK(AddrIsInSizeClass(ptr + size - 1, size_class));
-  size_classes_[size_class].FifoPush(fake_frame);
+  CHECK(AddrIsInSizeClass(ptr, class_id));
+  size_classes_[class_id].FifoPush(fake_frame);
 }
 
-ALWAYS_INLINE void FakeStack::OnFree(uptr ptr, uptr size, uptr real_stack) {
+ALWAYS_INLINE void FakeStack::OnFree(uptr ptr, uptr class_id, uptr size,
+                                     uptr real_stack) {
   FakeFrame *fake_frame = (FakeFrame*)ptr;
   CHECK_EQ(fake_frame->magic, kRetiredStackFrameMagic);
   CHECK_NE(fake_frame->descr, 0);
-  CHECK_EQ(fake_frame->size_minus_one, size - 1);
+  CHECK_EQ(fake_frame->class_id, class_id);
   PoisonShadow(ptr, size, kAsanStackAfterReturnMagic);
 }
 
-}  // namespace __asan
-
-// ---------------------- Interface ---------------- {{{1
-using namespace __asan;  // NOLINT
-
-uptr __asan_stack_malloc(uptr size, uptr real_stack) {
+ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size, uptr real_stack) {
   if (!flags()->use_fake_stack) return real_stack;
   AsanThread *t = GetCurrentThread();
   if (!t) {
@@ -171,14 +165,39 @@ uptr __asan_stack_malloc(uptr size, uptr
     return real_stack;
   }
   t->LazyInitFakeStack();
-  uptr ptr = t->fake_stack()->AllocateStack(size, real_stack);
+  uptr ptr = t->fake_stack()->AllocateStack(class_id, size, real_stack);
   // Printf("__asan_stack_malloc %p %zu %p\n", ptr, size, real_stack);
   return ptr;
 }
 
-void __asan_stack_free(uptr ptr, uptr size, uptr real_stack) {
+ALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size, uptr real_stack) {
   if (!flags()->use_fake_stack) return;
   if (ptr != real_stack) {
-    FakeStack::OnFree(ptr, size, real_stack);
+    FakeStack::OnFree(ptr, class_id, size, real_stack);
   }
 }
+
+}  // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+#define DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(class_id)                       \
+  extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr                                \
+  __asan_stack_malloc_##class_id(uptr size, uptr real_stack) {                 \
+    return __asan::OnMalloc(class_id, size, real_stack);                       \
+  }                                                                            \
+  extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_stack_free_##class_id(  \
+      uptr ptr, uptr size, uptr real_stack) {                                  \
+    __asan::OnFree(ptr, class_id, size, real_stack);                           \
+  }
+
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(0)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(1)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(2)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(3)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(4)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(5)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(6)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(7)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(8)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(9)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(10)

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=190406&r1=190405&r2=190406&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fake_stack.h (original)
+++ compiler-rt/trunk/lib/asan/asan_fake_stack.h Tue Sep 10 08:16:26 2013
@@ -23,7 +23,7 @@ struct FakeFrame {
   uptr descr;  // Modified by the instrumented code.
   uptr pc;     // Modified by the instrumented code.
   u64 real_stack     : 48;
-  u64 size_minus_one : 16;
+  u64 class_id : 16;
   // End of the first 32 bytes.
   // The rest should not be used when the frame is active.
   FakeFrame *next;
@@ -74,33 +74,36 @@ class FakeStack {
   void Init(uptr stack_size);
   void StopUsingFakeStack() { alive_ = false; }
   void Cleanup();
-  uptr AllocateStack(uptr size, uptr real_stack);
-  static void OnFree(uptr ptr, uptr size, uptr real_stack);
+  uptr AllocateStack(uptr class_id, uptr size, uptr real_stack);
+  static void OnFree(uptr ptr, uptr class_id, uptr size, uptr real_stack);
   // Return the bottom of the maped region.
   uptr AddrIsInFakeStack(uptr addr);
   uptr StackSize() const { return stack_size_; }
 
+  static uptr ComputeSizeClass(uptr alloc_size);
+
+  static uptr ClassSize(uptr class_id) {
+    return 1UL << (class_id + kMinStackFrameSizeLog);
+  }
+
  private:
-  static const uptr kMinStackFrameSizeLog = 7;  // Min frame is 128B.
+  static const uptr kMinStackFrameSizeLog = 6;  // Min frame is 64B.
   static const uptr kMaxStackFrameSizeLog = 16;  // Max stack frame is 64K.
-  static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog;
   static const uptr kNumberOfSizeClasses =
       kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
+  // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID
+  COMPILER_CHECK(kNumberOfSizeClasses == 11);
+  static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog;
   static const uptr kMaxRecursionDepth = 60000;
 
-  bool AddrIsInSizeClass(uptr addr, uptr size_class);
+  bool AddrIsInSizeClass(uptr addr, uptr class_id);
 
   // Each size class should be large enough to hold all frames.
-  uptr ClassMmapSize(uptr size_class);
-
-  uptr ClassSize(uptr size_class) {
-    return 1UL << (size_class + kMinStackFrameSizeLog);
-  }
+  uptr ClassMmapSize(uptr class_id);
 
   void DeallocateFrame(FakeFrame *fake_frame);
 
-  uptr ComputeSizeClass(uptr alloc_size);
-  void AllocateOneSizeClass(uptr size_class);
+  void AllocateOneSizeClass(uptr class_id);
 
   uptr stack_size_;
   bool   alive_;

Modified: compiler-rt/trunk/lib/asan/asan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interface_internal.h?rev=190406&r1=190405&r2=190406&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interface_internal.h Tue Sep 10 08:16:26 2013
@@ -58,15 +58,6 @@ extern "C" {
   SANITIZER_INTERFACE_ATTRIBUTE
   void __asan_after_dynamic_init();
 
-  // These two functions are used by the instrumented code in the
-  // use-after-return mode. __asan_stack_malloc allocates size bytes of
-  // fake stack and __asan_stack_free poisons it. real_stack is a pointer to
-  // the real stack region.
-  SANITIZER_INTERFACE_ATTRIBUTE
-  uptr __asan_stack_malloc(uptr size, uptr real_stack);
-  SANITIZER_INTERFACE_ATTRIBUTE
-  void __asan_stack_free(uptr ptr, uptr size, uptr real_stack);
-
   // These two functions are used by instrumented code in the
   // use-after-scope mode. They mark memory for local variables as
   // unaddressable when they leave scope and addressable before the

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=190406&r1=190405&r2=190406&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Tue Sep 10 08:16:26 2013
@@ -305,8 +305,6 @@ static NOINLINE void force_interface_sym
     case 25: __asan_poison_memory_region(0, 0); break;
     case 26: __asan_unpoison_memory_region(0, 0); break;
     case 27: __asan_set_error_exit_code(0); break;
-    case 28: __asan_stack_free(0, 0, 0); break;
-    case 29: __asan_stack_malloc(0, 0); break;
     case 30: __asan_before_dynamic_init(0); break;
     case 31: __asan_after_dynamic_init(); break;
     case 32: __asan_poison_stack_memory(0, 0); break;
@@ -375,6 +373,7 @@ static void PrintAddressSpaceLayout() {
   }
   Printf("\n");
   Printf("red_zone=%zu\n", (uptr)flags()->redzone);
+  Printf("quarantine_size=%zuM\n", (uptr)flags()->quarantine_size >> 20);
   Printf("malloc_context_size=%zu\n",
          (uptr)common_flags()->malloc_context_size);
 

Modified: compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c?rev=190406&r1=190405&r2=190406&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c Tue Sep 10 08:16:26 2013
@@ -7,6 +7,7 @@
 // RUN:    | grep -v "__asan_free_hook" \
 // RUN:    | grep -v "__asan_symbolize" \
 // RUN:    | grep -v "__asan_default_options" \
+// RUN:    | grep -v "__asan_stack_" \
 // RUN:    | grep -v "__asan_on_error" > %t.symbols
 // RUN: cat %p/../../../asan_interface_internal.h \
 // RUN:    | sed "s/\/\/.*//" | sed "s/typedef.*//" \

Modified: compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc?rev=190406&r1=190405&r2=190406&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc Tue Sep 10 08:16:26 2013
@@ -789,12 +789,3 @@ TEST(AddressSanitizerInterface, CallocRe
     }
   }
 }
-
-TEST(AddressSanitizerInterface, FakeStack) {
-  for (int iter = 0; iter < 1000; iter++) {
-    for (int size = 8; size <= (1 << 14); size += 8) {
-      uptr p = __asan_stack_malloc(size, 0x12345678);
-      CHECK(p);
-    }
-  }
-}





More information about the llvm-commits mailing list