forked from OSchip/llvm-project
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
This commit is contained in:
parent
44016da83f
commit
08342aa1a1
|
|
@ -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().
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue