diff options
| author | Kostya Serebryany <kcc@google.com> | 2013-09-10 13:16:26 +0000 |
|---|---|---|
| committer | Kostya Serebryany <kcc@google.com> | 2013-09-10 13:16:26 +0000 |
| commit | 8fc35ca008719ec050ae2694312edf6188e4732f (patch) | |
| tree | c091c5be29d6a07f38dd3be7a2167b98e141d3ac | |
| parent | 917f9e04b5ca1d0a2a331e8c2d57ef101a17fe00 (diff) | |
| download | bcm5719-llvm-8fc35ca008719ec050ae2694312edf6188e4732f.tar.gz bcm5719-llvm-8fc35ca008719ec050ae2694312edf6188e4732f.zip | |
[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
llvm-svn: 190406
| -rw-r--r-- | compiler-rt/lib/asan/asan_fake_stack.cc | 107 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_fake_stack.h | 29 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_interface_internal.h | 9 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 3 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/tests/asan_noinst_test.cc | 9 |
6 files changed, 81 insertions, 77 deletions
diff --git a/compiler-rt/lib/asan/asan_fake_stack.cc b/compiler-rt/lib/asan/asan_fake_stack.cc index 62a1982a7fc..abe10c88958 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.cc +++ b/compiler-rt/lib/asan/asan_fake_stack.cc @@ -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::AllocateStack(uptr size, uptr real_stack) { 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 real_stack) { 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) diff --git a/compiler-rt/lib/asan/asan_fake_stack.h b/compiler-rt/lib/asan/asan_fake_stack.h index 986aed7b351..fe029191e01 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.h +++ b/compiler-rt/lib/asan/asan_fake_stack.h @@ -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_; diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h index 48ff05d8893..b067b3820c1 100644 --- a/compiler-rt/lib/asan/asan_interface_internal.h +++ b/compiler-rt/lib/asan/asan_interface_internal.h @@ -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 diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index ee2128f20cd..4c3e776578e 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -305,8 +305,6 @@ static NOINLINE void force_interface_symbols() { 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); diff --git a/compiler-rt/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c b/compiler-rt/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c index baabc0598f0..d6ceda7af8b 100644 --- a/compiler-rt/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c +++ b/compiler-rt/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c @@ -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.*//" \ diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/compiler-rt/lib/asan/tests/asan_noinst_test.cc index 0ec5b55ec48..8168b3ec597 100644 --- a/compiler-rt/lib/asan/tests/asan_noinst_test.cc +++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cc @@ -789,12 +789,3 @@ TEST(AddressSanitizerInterface, CallocReturnsZeroMem) { } } } - -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); - } - } -} |

