diff options
author | Alexander Potapenko <glider@google.com> | 2012-04-05 10:54:52 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2012-04-05 10:54:52 +0000 |
commit | 08342aa1a19166c40abcc510cd6ac3db25e72d58 (patch) | |
tree | d4e6e307d9b42f700cbe09103204f9fb5091ed99 /compiler-rt | |
parent | 44016da83fa14a7ea0b47332ac6c0099214b1e26 (diff) | |
download | bcm5719-llvm-08342aa1a19166c40abcc510cd6ac3db25e72d58.tar.gz bcm5719-llvm-08342aa1a19166c40abcc510cd6ac3db25e72d58.zip |
Introduce the use_sigaltstack flag (off by default), which enables using alternate
per-thread stacks for signal handling. This allows to print more verbose error reports
for stack overflows.
llvm-svn: 154092
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/asan/asan_internal.h | 3 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_posix.cc | 36 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 5 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_thread.cc | 2 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_win.cc | 8 |
5 files changed, 53 insertions, 1 deletions
diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 6f03d678be1..39d3adf07a6 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -181,6 +181,8 @@ size_t AsanWrite(int fd, const void *buf, size_t count); int AsanClose(int fd); bool AsanInterceptsSignal(int signum); +void SetAlternateSignalStack(); +void UnsetAlternateSignalStack(); void InstallSignalHandlers(); int GetPid(); uintptr_t GetThreadSelf(); @@ -249,6 +251,7 @@ extern int FLAG_exitcode; extern bool FLAG_allow_user_poisoning; extern int FLAG_sleep_before_dying; extern bool FLAG_handle_segv; +extern bool FLAG_use_sigaltstack; extern int asan_inited; // Used to avoid infinite recursion in __asan_init(). diff --git a/compiler-rt/lib/asan/asan_posix.cc b/compiler-rt/lib/asan/asan_posix.cc index 15bdd932e10..0ab09e615dc 100644 --- a/compiler-rt/lib/asan/asan_posix.cc +++ b/compiler-rt/lib/asan/asan_posix.cc @@ -34,6 +34,8 @@ // since most of the stuff here is inlinable. #include <algorithm> +static const size_t kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. + namespace __asan { static void MaybeInstallSigaction(int signum, @@ -44,6 +46,7 @@ static void MaybeInstallSigaction(int signum, REAL(memset)(&sigact, 0, sizeof(sigact)); sigact.sa_sigaction = handler; sigact.sa_flags = SA_SIGINFO; + if (FLAG_use_sigaltstack) sigact.sa_flags |= SA_ONSTACK; CHECK(0 == REAL(sigaction)(signum, &sigact, 0)); } @@ -63,7 +66,40 @@ static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { ShowStatsAndAbort(); } +void SetAlternateSignalStack() { + stack_t altstack, oldstack; + CHECK(0 == sigaltstack(NULL, &oldstack)); + // If the alternate stack is already in place, do nothing. + if ((oldstack.ss_flags & SS_DISABLE) == 0) return; + // TODO(glider): the mapped stack should have the MAP_STACK flag in the + // future. It is not required by man 2 sigaltstack now (they're using + // malloc()). + void* base = AsanMmapSomewhereOrDie(kAltStackSize, __FUNCTION__); + altstack.ss_sp = base; + altstack.ss_flags = 0; + altstack.ss_size = kAltStackSize; + CHECK(0 == sigaltstack(&altstack, NULL)); + if (FLAG_v > 0) { + Report("Alternative stack for T%d set: [%p,%p)\n", + asanThreadRegistry().GetCurrentTidOrMinusOne(), + altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size); + } +} + +void UnsetAlternateSignalStack() { + stack_t altstack, oldstack; + altstack.ss_sp = NULL; + altstack.ss_flags = SS_DISABLE; + altstack.ss_size = 0; + CHECK(0 == sigaltstack(&altstack, &oldstack)); + AsanUnmapOrDie(oldstack.ss_sp, oldstack.ss_size); +} + void InstallSignalHandlers() { + // Set the alternate signal stack for the main thread. + // This will cause SetAlternateSignalStack to be called twice, but the stack + // will be actually set only once. + if (FLAG_use_sigaltstack) SetAlternateSignalStack(); MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV); MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV); } diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 3587d45145d..8f69cca2869 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -39,6 +39,7 @@ int FLAG_report_globals; size_t FLAG_malloc_context_size = kMallocContextSize; uintptr_t FLAG_large_malloc; bool FLAG_handle_segv; +bool FLAG_use_sigaltstack; bool FLAG_replace_str; bool FLAG_replace_intrin; bool FLAG_replace_cfallocator; // Used on Mac only. @@ -442,6 +443,7 @@ void __asan_init() { FLAG_poison_shadow = IntFlagValue(options, "poison_shadow=", 1); FLAG_report_globals = IntFlagValue(options, "report_globals=", 1); FLAG_handle_segv = IntFlagValue(options, "handle_segv=", ASAN_NEEDS_SEGV); + FLAG_use_sigaltstack = IntFlagValue(options, "use_sigaltstack=", 0); FLAG_symbolize = IntFlagValue(options, "symbolize=", 1); FLAG_demangle = IntFlagValue(options, "demangle=", 1); FLAG_debug = IntFlagValue(options, "debug=", 0); @@ -470,7 +472,6 @@ void __asan_init() { InitializeAsanInterceptors(); ReplaceSystemMalloc(); - InstallSignalHandlers(); if (FLAG_v) { Printf("|| `[%p, %p]` || HighMem ||\n", kHighMemBeg, kHighMemEnd); @@ -517,6 +518,8 @@ void __asan_init() { AsanDie(); } + InstallSignalHandlers(); + // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited // should be set to 1 prior to initializing the threads. asan_inited = 1; diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index b6d0965c755..315db7ef98f 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -82,6 +82,7 @@ void AsanThread::Init() { thread_return_t AsanThread::ThreadStart() { Init(); + if (FLAG_use_sigaltstack) SetAlternateSignalStack(); if (!start_routine_) { // start_routine_ == NULL if we're on the main thread or on one of the @@ -93,6 +94,7 @@ thread_return_t AsanThread::ThreadStart() { thread_return_t res = start_routine_(arg_); malloc_storage().CommitBack(); + if (FLAG_use_sigaltstack) UnsetAlternateSignalStack(); this->Destroy(); diff --git a/compiler-rt/lib/asan/asan_win.cc b/compiler-rt/lib/asan/asan_win.cc index b3a770b8276..94f4d04a18a 100644 --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -262,6 +262,14 @@ uintptr_t GetThreadSelf() { return GetCurrentThreadId(); } +void SetAlternateSignalStack() { + // FIXME: Decide what to do on Windows. +} + +void UnsetAlternateSignalStack() { + // FIXME: Decide what to do on Windows. +} + void InstallSignalHandlers() { // FIXME: Decide what to do on Windows. } |