diff options
| author | Kostya Serebryany <kcc@google.com> | 2013-09-27 11:37:23 +0000 |
|---|---|---|
| committer | Kostya Serebryany <kcc@google.com> | 2013-09-27 11:37:23 +0000 |
| commit | 3c42ce15166d61531500a9dacda9372028a3e27a (patch) | |
| tree | 30f92f7fcd217ab0c2074cf65f91ca47e5d608b1 | |
| parent | 56ce9c4e78a6a8db5ec651f48a4acb8cf0d16c07 (diff) | |
| download | bcm5719-llvm-3c42ce15166d61531500a9dacda9372028a3e27a.tar.gz bcm5719-llvm-3c42ce15166d61531500a9dacda9372028a3e27a.zip | |
[asan] introduce run-time flag uar_stack_size_log to control the size of FakeStack; don't crash when the fake stack is exhausted, move some code to .cc file
llvm-svn: 191510
| -rw-r--r-- | compiler-rt/lib/asan/asan_fake_stack.cc | 29 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_fake_stack.h | 18 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_flags.h | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_thread.cc | 7 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/lit_tests/TestCases/stack-use-after-return.cc | 7 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/tests/asan_fake_stack_test.cc | 8 |
7 files changed, 44 insertions, 29 deletions
diff --git a/compiler-rt/lib/asan/asan_fake_stack.cc b/compiler-rt/lib/asan/asan_fake_stack.cc index 4012a6d1a46..81091f18989 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.cc +++ b/compiler-rt/lib/asan/asan_fake_stack.cc @@ -35,6 +35,30 @@ ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { } } +FakeStack *FakeStack::Create(uptr stack_size_log) { + static uptr kMinStackSizeLog = 16; + static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(24, 28); + if (stack_size_log < kMinStackSizeLog) + stack_size_log = kMinStackSizeLog; + if (stack_size_log > kMaxStackSizeLog) + stack_size_log = kMaxStackSizeLog; + FakeStack *res = reinterpret_cast<FakeStack *>( + MmapOrDie(RequiredSize(stack_size_log), "FakeStack")); + res->stack_size_log_ = stack_size_log; + if (flags()->verbosity) { + u8 *p = reinterpret_cast<u8 *>(res); + Report("T%d: FakeStack created: %p -- %p stack_size_log: %zd \n", + GetCurrentTidOrInvalid(), p, + p + FakeStack::RequiredSize(stack_size_log), stack_size_log); + } + return res; +} + +void FakeStack::Destroy() { + PoisonAll(0); + UnmapOrDie(this, RequiredSize(stack_size_log_)); +} + void FakeStack::PoisonAll(u8 magic) { PoisonShadow(reinterpret_cast<uptr>(this), RequiredSize(stack_size_log()), magic); @@ -66,8 +90,7 @@ FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id, *SavedFlagPtr(reinterpret_cast<uptr>(res), class_id) = &flags[pos]; return res; } - CHECK(0 && "Failed to allocate a fake stack frame"); - return 0; + return 0; // We are out of fake stack. } uptr FakeStack::AddrIsInFakeStack(uptr ptr) { @@ -143,6 +166,8 @@ ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size, uptr real_stack) { FakeStack *fs = GetFakeStackFast(); if (!fs) return real_stack; FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, real_stack); + if (!ff) + return real_stack; // Out of fake stack, return the real one. uptr ptr = reinterpret_cast<uptr>(ff); SetShadow(ptr, size, class_id, 0); return ptr; diff --git a/compiler-rt/lib/asan/asan_fake_stack.h b/compiler-rt/lib/asan/asan_fake_stack.h index 3f72b8214ee..b4f74d909ad 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.h +++ b/compiler-rt/lib/asan/asan_fake_stack.h @@ -63,23 +63,9 @@ class FakeStack { kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1; // CTOR: create the FakeStack as a single mmap-ed object. - static FakeStack *Create(uptr stack_size_log) { - static uptr kMinStackSizeLog = 16; - static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(23, 26); - if (stack_size_log < kMinStackSizeLog) - stack_size_log = kMinStackSizeLog; - if (stack_size_log > kMaxStackSizeLog) - stack_size_log = kMaxStackSizeLog; - FakeStack *res = reinterpret_cast<FakeStack *>( - MmapOrDie(RequiredSize(stack_size_log), "FakeStack")); - res->stack_size_log_ = stack_size_log; - return res; - } + static FakeStack *Create(uptr stack_size_log); - void Destroy() { - PoisonAll(0); - UnmapOrDie(this, RequiredSize(stack_size_log_)); - } + void Destroy(); // stack_size_log is at least 15 (stack_size >= 32K). static uptr SizeRequiredForFlags(uptr stack_size_log) { diff --git a/compiler-rt/lib/asan/asan_flags.h b/compiler-rt/lib/asan/asan_flags.h index bed97bd3db3..7c2a1e36b67 100644 --- a/compiler-rt/lib/asan/asan_flags.h +++ b/compiler-rt/lib/asan/asan_flags.h @@ -54,6 +54,8 @@ struct Flags { bool mac_ignore_invalid_free; // Enables stack-use-after-return checking at run-time. bool detect_stack_use_after_return; + // The minimal fake stack size log. + int uar_stack_size_log; // ASan allocator flag. max_malloc_fill_size is the maximal amount of bytes // that will be filled with malloc_fill_byte on malloc. int max_malloc_fill_size, malloc_fill_byte; diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 50e16691de3..f0b31f05bd2 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -106,6 +106,7 @@ static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free"); ParseFlag(str, &f->detect_stack_use_after_return, "detect_stack_use_after_return"); + ParseFlag(str, &f->uar_stack_size_log, "uar_stack_size_log"); ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size"); ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte"); ParseFlag(str, &f->exitcode, "exitcode"); @@ -154,6 +155,7 @@ void InitializeFlags(Flags *f, const char *env) { f->replace_intrin = true; f->mac_ignore_invalid_free = false; f->detect_stack_use_after_return = false; // Also needs the compiler flag. + f->uar_stack_size_log = 0; f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K. f->malloc_fill_byte = 0xbe; f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE; diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index 16648fe7485..5a81a5e01e0 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -124,13 +124,10 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() { reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL, memory_order_relaxed)) { uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size)); + if (flags()->uar_stack_size_log) + stack_size_log = static_cast<uptr>(flags()->uar_stack_size_log); fake_stack_ = FakeStack::Create(stack_size_log); SetTLSFakeStack(fake_stack_); - if (flags()->verbosity) { - u8 *p = reinterpret_cast<u8 *>(fake_stack_); - Report("T%d: FakeStack created: %p -- %p\n", tid(), p, - p + FakeStack::RequiredSize(stack_size_log)); - } return fake_stack_; } return 0; diff --git a/compiler-rt/lib/asan/lit_tests/TestCases/stack-use-after-return.cc b/compiler-rt/lib/asan/lit_tests/TestCases/stack-use-after-return.cc index a3adda80da3..5ed42a8c0c9 100644 --- a/compiler-rt/lib/asan/lit_tests/TestCases/stack-use-after-return.cc +++ b/compiler-rt/lib/asan/lit_tests/TestCases/stack-use-after-return.cc @@ -15,6 +15,11 @@ // Test that we can find UAR in a thread other than main: // RUN: %clangxx_asan -DUseThread -O2 %s -o %t && \ // RUN: not %t 2>&1 | FileCheck --check-prefix=THREAD %s +// +// Test the uar_stack_size_log flag. +// +// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:uar_stack_size_log=20:verbosity=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s +// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:uar_stack_size_log=24:verbosity=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-24 %s #include <stdio.h> #include <pthread.h> @@ -51,6 +56,8 @@ void Func2(char *x) { // THREAD: #0{{.*}}Func2{{.*}}stack-use-after-return.cc:[[@LINE-6]] // THREAD: is located in stack of thread T{{[1-9]}} at offset // THREAD: 'local' <== Memory access at offset 32 is inside this variable + // CHECK-20: T0: FakeStack created:{{.*}} stack_size_log: 20 + // CHECK-24: T0: FakeStack created:{{.*}} stack_size_log: 24 } void *Thread(void *unused) { diff --git a/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc b/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc index 6e245a075f7..1c98125eb45 100644 --- a/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc +++ b/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc @@ -119,12 +119,8 @@ TEST(FakeStack, Allocate) { EXPECT_EQ(x, fs->AddrIsInFakeStack(x + bytes_in_class - 1)); EXPECT_NE(x, fs->AddrIsInFakeStack(x + bytes_in_class)); } - if (iter == 0 && - (cid == 0 || cid == FakeStack::kNumberOfSizeClasses - 1)) { - // This is slow, so we do it only sometimes. - EXPECT_DEATH(fs->Allocate(stack_size_log, cid, 0), - "Failed to allocate a fake stack frame"); - } + // We are out of fake stack, so Allocate should return 0. + EXPECT_EQ(0UL, fs->Allocate(stack_size_log, cid, 0)); } for (std::map<FakeFrame *, uptr>::iterator it = s.begin(); it != s.end(); ++it) { |

