[compiler-rt] r200908 - [asan] introduce two functions that will allow implementations of C++ garbage colection to work with asan's fake stack

Kostya Serebryany kcc at google.com
Wed Feb 5 22:56:23 PST 2014


Author: kcc
Date: Thu Feb  6 00:56:22 2014
New Revision: 200908

URL: http://llvm.org/viewvc/llvm-project?rev=200908&view=rev
Log:
[asan] introduce two functions that will allow implementations of C++ garbage colection to work with asan's fake stack

Added:
    compiler-rt/trunk/lib/asan/lit_tests/TestCases/gc-test.cc
Modified:
    compiler-rt/trunk/include/sanitizer/asan_interface.h
    compiler-rt/trunk/lib/asan/asan_fake_stack.cc
    compiler-rt/trunk/lib/asan/asan_fake_stack.h
    compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c

Modified: compiler-rt/trunk/include/sanitizer/asan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/asan_interface.h?rev=200908&r1=200907&r2=200908&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/asan_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/asan_interface.h Thu Feb  6 00:56:22 2014
@@ -122,6 +122,24 @@ extern "C" {
   //   deallocation of "ptr".
   void __asan_malloc_hook(void *ptr, size_t size);
   void __asan_free_hook(void *ptr);
+
+  // The following 2 functions facilitate garbage collection in presence of
+  // asan's fake stack.
+
+  // Returns an opaque handler to be used later in __asan_addr_is_in_fake_stack.
+  // Returns NULL if the current thread does not have a fake stack.
+  void *__asan_get_current_fake_stack();
+
+  // If fake_stack is non-NULL and addr belongs to a fake frame in
+  // fake_stack, returns the address on real stack that corresponds to
+  // the fake frame and sets beg/end to the boundaries of this fake frame.
+  // Otherwise returns NULL and does not touch beg/end.
+  // If beg/end are NULL, they are not touched.
+  // This function may be called from a thread other than the owner of
+  // fake_stack, but the owner thread need to be alive.
+  void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
+                                     void **end);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif

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=200908&r1=200907&r2=200908&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fake_stack.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_fake_stack.cc Thu Feb  6 00:56:22 2014
@@ -104,7 +104,7 @@ FakeFrame *FakeStack::Allocate(uptr stac
   return 0; // We are out of fake stack.
 }
 
-uptr FakeStack::AddrIsInFakeStack(uptr ptr) {
+uptr FakeStack::AddrIsInFakeStack(uptr ptr, uptr *frame_beg, uptr *frame_end) {
   uptr stack_size_log = this->stack_size_log();
   uptr beg = reinterpret_cast<uptr>(GetFrame(stack_size_log, 0, 0));
   uptr end = reinterpret_cast<uptr>(this) + RequiredSize(stack_size_log);
@@ -114,7 +114,10 @@ uptr FakeStack::AddrIsInFakeStack(uptr p
   CHECK_LE(base, ptr);
   CHECK_LT(ptr, base + (1UL << stack_size_log));
   uptr pos = (ptr - base) >> (kMinStackFrameSizeLog + class_id);
-  return base + pos * BytesInSizeClass(class_id);
+  uptr res = base + pos * BytesInSizeClass(class_id);
+  *frame_end = res + BytesInSizeClass(class_id);
+  *frame_beg = res + sizeof(FakeFrame);
+  return res;
 }
 
 void FakeStack::HandleNoReturn() {
@@ -208,14 +211,15 @@ ALWAYS_INLINE void OnFree(uptr ptr, uptr
 }  // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
+using namespace __asan;
 #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);                       \
+    return 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);                           \
+    OnFree(ptr, class_id, size, real_stack);                                   \
   }
 
 DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(0)
@@ -229,3 +233,23 @@ 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)
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__asan_get_current_fake_stack() { return GetFakeStackFast(); }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
+                                   void **end) {
+  FakeStack *fs = reinterpret_cast<FakeStack*>(fake_stack);
+  if (!fs) return 0;
+  uptr frame_beg, frame_end;
+  FakeFrame *frame = reinterpret_cast<FakeFrame *>(fs->AddrIsInFakeStack(
+      reinterpret_cast<uptr>(addr), &frame_beg, &frame_end));
+  if (!frame) return 0;
+  if (frame->magic != kCurrentStackFrameMagic)
+    return 0;
+  if (beg) *beg = reinterpret_cast<void*>(frame_beg);
+  if (end) *end = reinterpret_cast<void*>(frame_end);
+  return reinterpret_cast<void*>(frame->real_stack);
+}
+}  // extern "C"

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=200908&r1=200907&r2=200908&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fake_stack.h (original)
+++ compiler-rt/trunk/lib/asan/asan_fake_stack.h Thu Feb  6 00:56:22 2014
@@ -129,7 +129,11 @@ class FakeStack {
   void PoisonAll(u8 magic);
 
   // Return the beginning of the FakeFrame or 0 if the address is not ours.
-  uptr AddrIsInFakeStack(uptr addr);
+  uptr AddrIsInFakeStack(uptr addr, uptr *frame_beg, uptr *frame_end);
+  USED uptr AddrIsInFakeStack(uptr addr) {
+    uptr t1, t2;
+    return AddrIsInFakeStack(addr, &t1, &t2);
+  }
 
   // Number of bytes in a fake frame of this size class.
   static uptr BytesInSizeClass(uptr class_id) {

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=200908&r1=200907&r2=200908&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 Thu Feb  6 00:56:22 2014
@@ -25,6 +25,8 @@
 // RUN: echo __asan_report_store16 >> %t.interface
 // RUN: echo __asan_report_load_n >> %t.interface
 // RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_get_current_fake_stack >> %t.interface
+// RUN: echo __asan_addr_is_in_fake_stack >> %t.interface
 // RUN: cat %t.interface | sort -u | diff %t.symbols -
 
 // FIXME: nm -D on powerpc somewhy shows ASan interface symbols residing

Added: compiler-rt/trunk/lib/asan/lit_tests/TestCases/gc-test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/TestCases/gc-test.cc?rev=200908&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/TestCases/gc-test.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/TestCases/gc-test.cc Thu Feb  6 00:56:22 2014
@@ -0,0 +1,49 @@
+// RUN: %clangxx_asan  %s -o %t
+// RUN: ASAN_OPTIONS=detect_stack_use_after_return=1 %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: ASAN_OPTIONS=detect_stack_use_after_return=0 %t 2>&1 | FileCheck %s --check-prefix=CHECK0
+
+#include <assert.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <sanitizer/asan_interface.h>
+
+static const int kNumThreads = 2;
+
+void *Thread(void *unused)  {
+  void *fake_stack = __asan_get_current_fake_stack();
+  char var[15];
+  if (fake_stack) {
+    fprintf(stderr, "fake stack found: %p; var: %p\n", fake_stack, var);
+    // CHECK1: fake stack found
+    // CHECK1: fake stack found
+    void *beg, *end;
+    void *real_stack =
+        __asan_addr_is_in_fake_stack(fake_stack, &var[0], &beg, &end);
+    assert(real_stack);
+    assert((char*)beg <= (char*)&var[0]);
+    assert((char*)end > (char*)&var[0]);
+    for (int i = -32; i < 15; i++) {
+      void *beg1, *end1;
+      char *ptr = &var[0] + i;
+      void *real_stack1 =
+          __asan_addr_is_in_fake_stack(fake_stack, ptr, &beg1, &end1);
+      assert(real_stack == real_stack1);
+      assert(beg == beg1);
+      assert(end == end1);
+    }
+  } else {
+    fprintf(stderr, "no fake stack\n");
+    // CHECK0: no fake stack
+    // CHECK0: no fake stack
+  }
+  return NULL;
+}
+
+int main(int argc, char **argv) {
+  pthread_t t[kNumThreads];
+  for (int i = 0; i < kNumThreads; i++)
+    pthread_create(&t[i], 0, Thread, 0);
+  for (int i = 0; i < kNumThreads; i++)
+    pthread_join(t[i], 0);
+  return 0;
+}





More information about the llvm-commits mailing list