Index: asan/asan_interceptors.cc =================================================================== --- asan/asan_interceptors.cc +++ asan/asan_interceptors.cc @@ -202,6 +202,13 @@ } 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, Index: asan/asan_internal.h =================================================================== --- asan/asan_internal.h +++ asan/asan_internal.h @@ -71,10 +71,10 @@ 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(); Index: asan/asan_posix.cc =================================================================== --- asan/asan_posix.cc +++ 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 @@ 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; Index: asan/asan_rtl.cc =================================================================== --- asan/asan_rtl.cc +++ asan/asan_rtl.cc @@ -486,7 +486,7 @@ } AsanTSDInit(PlatformTSDDtor); - InstallSignalHandlers(); + InstallDeadlySignalHandlers(AsanOnSIGSEGV); // Allocator should be initialized before starting external symbolizer, as // fork() on Mac locks the allocator. Index: asan/asan_win.cc =================================================================== --- asan/asan_win.cc +++ asan/asan_win.cc @@ -70,10 +70,6 @@ return 0; } -void InstallSignalHandlers() { - // FIXME: Decide what to do on Windows. -} - void AsanPlatformThreadInit() { // Nothing here for now. } Index: sanitizer_common/sanitizer_common.h =================================================================== --- sanitizer_common/sanitizer_common.h +++ sanitizer_common/sanitizer_common.h @@ -214,6 +214,10 @@ 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(); Index: sanitizer_common/sanitizer_libc.h =================================================================== --- sanitizer_common/sanitizer_libc.h +++ sanitizer_common/sanitizer_libc.h @@ -97,6 +97,8 @@ // 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 Index: sanitizer_common/sanitizer_linux.cc =================================================================== --- sanitizer_common/sanitizer_linux.cc +++ 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 @@ } #endif +bool IsDeadlySignal(int signum) { + return (signum == SIGSEGV) && common_flags()->handle_segv; +} + } // namespace __sanitizer #endif // SANITIZER_LINUX Index: sanitizer_common/sanitizer_linux_libcdep.cc =================================================================== --- sanitizer_common/sanitizer_linux_libcdep.cc +++ sanitizer_common/sanitizer_linux_libcdep.cc @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -39,7 +40,6 @@ __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 @@ 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) { Index: sanitizer_common/sanitizer_mac.cc =================================================================== --- sanitizer_common/sanitizer_mac.cc +++ sanitizer_common/sanitizer_mac.cc @@ -23,6 +23,7 @@ #include #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 #include #include +#include #include #include #include @@ -118,6 +120,11 @@ 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 @@ 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 Index: sanitizer_common/sanitizer_posix_libcdep.cc =================================================================== --- sanitizer_common/sanitizer_posix_libcdep.cc +++ 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 @@ -117,6 +119,29 @@ 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 Index: sanitizer_common/sanitizer_win.cc =================================================================== --- sanitizer_common/sanitizer_win.cc +++ sanitizer_common/sanitizer_win.cc @@ -421,6 +421,15 @@ // 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