diff options
author | Alexander Potapenko <glider@google.com> | 2014-01-31 13:10:07 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2014-01-31 13:10:07 +0000 |
commit | 4c26afdb206b13ae5cdc5e2a074a6cadc0d969a5 (patch) | |
tree | ec3f7f602ad4f68a2bef7b9765cf07d507f536fe | |
parent | 7c8ecc28166e5f23cc8479ebcf69effe9a006dad (diff) |
[ASan] Move the SIGSEGV/SIGBUS handling to sanitizer_common
This change is a part of refactoring intended to have common signal handling behavior in all tools.
This particular CL moves InstallSignalHandlers() into sanitizer_common (making it InstallDeadlySignalHandlers()), but doesn't enable default signal handlers for any tool other than ASan.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@200542 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/asan/asan_interceptors.cc | 7 | ||||
-rw-r--r-- | lib/asan/asan_internal.h | 2 | ||||
-rw-r--r-- | lib/asan/asan_posix.cc | 26 | ||||
-rw-r--r-- | lib/asan/asan_rtl.cc | 2 | ||||
-rw-r--r-- | lib/asan/asan_win.cc | 4 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 4 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_libc.h | 2 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux.cc | 5 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux_libcdep.cc | 11 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_mac.cc | 11 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_posix_libcdep.cc | 25 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_win.cc | 9 |
12 files changed, 77 insertions, 31 deletions
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index c63de35c3..f5efbd3f6 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -202,6 +202,13 @@ INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, } return 0; } + +extern "C" +int __sanitizer_sigaction_f(int signum, const void *act, void *oldact) { + return REAL(sigaction)(signum, + (struct sigaction *)act, (struct sigaction *)oldact); +} + #elif SANITIZER_POSIX // We need to have defined REAL(sigaction) on posix systems. DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h index f0c9a49a6..3914fbbd1 100644 --- a/lib/asan/asan_internal.h +++ b/lib/asan/asan_internal.h @@ -71,10 +71,10 @@ void ReplaceSystemMalloc(); void *AsanDoesNotSupportStaticLinkage(); void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); +void AsanOnSIGSEGV(int, void *siginfo, void *context); void MaybeReexec(); bool AsanInterceptsSignal(int signum); -void InstallSignalHandlers(); void ReadContextStack(void *context, uptr *stack, uptr *ssize); void AsanPlatformThreadInit(); void StopInitOrderChecking(); diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc index 9a306309a..d4bf84f8e 100644 --- a/lib/asan/asan_posix.cc +++ b/lib/asan/asan_posix.cc @@ -32,21 +32,8 @@ namespace __asan { -static void MaybeInstallSigaction(int signum, - void (*handler)(int, siginfo_t *, void *)) { - if (!AsanInterceptsSignal(signum)) - return; - struct sigaction sigact; - REAL(memset)(&sigact, 0, sizeof(sigact)); - sigact.sa_sigaction = handler; - sigact.sa_flags = SA_SIGINFO; - if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK; - CHECK_EQ(0, REAL(sigaction)(signum, &sigact, 0)); - VReport(1, "Installed the sigaction for signal %d\n", signum); -} - -static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { - uptr addr = (uptr)siginfo->si_addr; +void AsanOnSIGSEGV(int, void *siginfo, void *context) { + uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr; // Write the first message using the bullet-proof write. if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); uptr pc, sp, bp; @@ -54,15 +41,6 @@ static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { ReportSIGSEGV(pc, sp, bp, addr); } -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 (common_flags()->use_sigaltstack) SetAlternateSignalStack(); - MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV); - MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV); -} - // ---------------------- TSD ---------------- {{{1 static pthread_key_t tsd_key; diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index 3d8ed9f84..2a97ed595 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -486,7 +486,7 @@ static void AsanInitInternal() { } AsanTSDInit(PlatformTSDDtor); - InstallSignalHandlers(); + InstallDeadlySignalHandlers(AsanOnSIGSEGV); // Allocator should be initialized before starting external symbolizer, as // fork() on Mac locks the allocator. diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index f06e74030..80d70b9c0 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -70,10 +70,6 @@ void *AsanDoesNotSupportStaticLinkage() { return 0; } -void InstallSignalHandlers() { - // FIXME: Decide what to do on Windows. -} - void AsanPlatformThreadInit() { // Nothing here for now. } diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 1398f75a6..a5c8df0c3 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -214,6 +214,10 @@ typedef void (*CheckFailedCallbackType)(const char *, int, const char *, void SetCheckFailedCallback(CheckFailedCallbackType callback); // Functions related to signal handling. +typedef void (*SignalHandlerType)(int, void *, void *); +bool IsDeadlySignal(int signum); +void InstallDeadlySignalHandlers(SignalHandlerType handler); +// Alternative signal stack (POSIX-only). void SetAlternateSignalStack(); void UnsetAlternateSignalStack(); diff --git a/lib/sanitizer_common/sanitizer_libc.h b/lib/sanitizer_common/sanitizer_libc.h index 9a1b4b539..0768ae16e 100644 --- a/lib/sanitizer_common/sanitizer_libc.h +++ b/lib/sanitizer_common/sanitizer_libc.h @@ -97,6 +97,8 @@ uptr internal_sched_yield(); // Error handling bool internal_iserror(uptr retval, int *rverrno = 0); +int internal_sigaction(int signum, const void *act, void *oldact); + } // namespace __sanitizer #endif // SANITIZER_LIBC_H diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 03d3dc5d6..2a954772b 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -16,6 +16,7 @@ #if SANITIZER_LINUX #include "sanitizer_common.h" +#include "sanitizer_flags.h" #include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" #include "sanitizer_linux.h" @@ -698,6 +699,10 @@ void AndroidLogWrite(const char *buffer) { } #endif +bool IsDeadlySignal(int signum) { + return (signum == SIGSEGV) && common_flags()->handle_segv; +} + } // namespace __sanitizer #endif // SANITIZER_LINUX diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 0b951bd3e..d64a89293 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -24,6 +24,7 @@ #include <dlfcn.h> #include <pthread.h> +#include <signal.h> #include <sys/prctl.h> #include <sys/resource.h> #include <unwind.h> @@ -39,7 +40,6 @@ extern "C" SANITIZER_WEAK_ATTRIBUTE int __sanitizer_pthread_attr_getstack(void *attr, void **addr, size_t *size); static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { -# if (__sanitizer_pthread_attr_getstack) return __sanitizer_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); @@ -50,6 +50,15 @@ static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { namespace __sanitizer { +extern "C" SANITIZER_WEAK_ATTRIBUTE int +__sanitizer_sigaction_f(int signum, const void *act, void *oldact); + +int internal_sigaction(int signum, const void *act, void *oldact) { + if (__sanitizer_sigaction_f) + return __sanitizer_sigaction_f(signum, act, oldact); + return sigaction(signum, (struct sigaction *)act, (struct sigaction *)oldact); +} + #ifndef SANITIZER_GO void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, uptr *stack_bottom) { diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 3cc3a6b5b..e6c95bb69 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -23,6 +23,7 @@ #include <stdio.h> #include "sanitizer_common.h" +#include "sanitizer_flags.h" #include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" #include "sanitizer_placement_new.h" @@ -32,6 +33,7 @@ #include <fcntl.h> #include <pthread.h> #include <sched.h> +#include <signal.h> #include <sys/mman.h> #include <sys/resource.h> #include <sys/stat.h> @@ -118,6 +120,11 @@ uptr internal_getpid() { return getpid(); } +int internal_sigaction(int signum, const void *act, void *oldact) { + return sigaction(signum, + (struct sigaction *)act, (struct sigaction *)oldact); +} + // ----------------- sanitizer_common.h bool FileExists(const char *filename) { struct stat st; @@ -238,6 +245,10 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules, return memory_mapping.DumpListOfModules(modules, max_modules, filter); } +bool IsDeadlySignal(int signum) { + return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv; +} + } // namespace __sanitizer #endif // SANITIZER_MAC diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 73b7886c2..feabc6096 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -16,6 +16,8 @@ #if SANITIZER_LINUX || SANITIZER_MAC #include "sanitizer_common.h" +#include "sanitizer_flags.h" +#include "sanitizer_platform_limits_posix.h" #include "sanitizer_stacktrace.h" #include <errno.h> @@ -117,6 +119,29 @@ void UnsetAlternateSignalStack() { UnmapOrDie(oldstack.ss_sp, oldstack.ss_size); } +typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); +static void MaybeInstallSigaction(int signum, + SignalHandlerType handler) { + if (!IsDeadlySignal(signum)) + return; + struct sigaction sigact; + internal_memset(&sigact, 0, sizeof(sigact)); + sigact.sa_sigaction = (sa_sigaction_t)handler; + sigact.sa_flags = SA_SIGINFO; + if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK; + CHECK_EQ(0, internal_sigaction(signum, &sigact, 0)); + VReport(1, "Installed the sigaction for signal %d\n", signum); +} + +void InstallDeadlySignalHandlers(SignalHandlerType handler) { + // 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 (common_flags()->use_sigaltstack) SetAlternateSignalStack(); + MaybeInstallSigaction(SIGSEGV, handler); + MaybeInstallSigaction(SIGBUS, handler); +} + } // namespace __sanitizer #endif diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index e3ef578a8..0424e97ee 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -421,6 +421,15 @@ void UnsetAlternateSignalStack() { // FIXME: Decide what to do on Windows. } +void InstallDeadlySignalHandlers() { + // FIXME: Decide what to do on Windows. +} + +bool IsDeadlySignal(int signum) { + // FIXME: Decide what to do on Windows. + return false; +} + } // namespace __sanitizer #endif // _WIN32 |