summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2012-04-05 10:54:52 +0000
committerAlexander Potapenko <glider@google.com>2012-04-05 10:54:52 +0000
commit08342aa1a19166c40abcc510cd6ac3db25e72d58 (patch)
treed4e6e307d9b42f700cbe09103204f9fb5091ed99 /compiler-rt
parent44016da83fa14a7ea0b47332ac6c0099214b1e26 (diff)
downloadbcm5719-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.h3
-rw-r--r--compiler-rt/lib/asan/asan_posix.cc36
-rw-r--r--compiler-rt/lib/asan/asan_rtl.cc5
-rw-r--r--compiler-rt/lib/asan/asan_thread.cc2
-rw-r--r--compiler-rt/lib/asan/asan_win.cc8
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.
}
OpenPOWER on IntegriCloud