[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