[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