Index: asan/asan_internal.h =================================================================== --- asan/asan_internal.h +++ asan/asan_internal.h @@ -71,6 +71,7 @@ void *AsanDoesNotSupportStaticLinkage(); void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); +void ASAN_OnSIGSEGV(int, void *siginfo, void *context); void MaybeReexec(); bool AsanInterceptsSignal(int signum); 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 ASAN_OnSIGSEGV(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(ASAN_OnSIGSEGV); // Allocator should be initialized before starting external symbolizer, as // fork() on Mac locks the allocator. Index: interception/interception.h =================================================================== --- interception/interception.h +++ interception/interception.h @@ -86,6 +86,9 @@ // As it's decided at compile time which functions are to be intercepted on Mac, // INTERCEPT_FUNCTION() is effectively a no-op on this system. +// TODO(glider): move everything but the documentation to platform-specific +// headers. + #if defined(__APPLE__) #include // For __DARWIN_ALIAS_C(). @@ -155,6 +158,7 @@ } #else // __APPLE__ # define REAL(x) x +# define GET_REAL_SLOW(x) (void*)x # define DECLARE_REAL(ret_type, func, ...) \ extern "C" ret_type func(__VA_ARGS__); #endif // __APPLE__ Index: interception/interception_linux.h =================================================================== --- interception/interception_linux.h +++ interception/interception_linux.h @@ -25,9 +25,13 @@ // returns true if a function with the given name was found. bool GetRealFunctionAddress(const char *func_name, uptr *func_addr, uptr real, uptr wrapper); +void *GetFuncAddr(const char *func_name); void *GetFuncAddrVer(const char *func_name, const char *ver); } // namespace __interception +#define GET_REAL_SLOW(func) \ + ::__interception::GetFuncAddr(#func) + #define INTERCEPT_FUNCTION_LINUX(func) \ ::__interception::GetRealFunctionAddress( \ #func, (::__interception::uptr *)&__interception::PTR_TO_REAL(func), \ Index: interception/interception_linux.cc =================================================================== --- interception/interception_linux.cc +++ interception/interception_linux.cc @@ -24,6 +24,10 @@ return real == wrapper; } +void *GetFuncAddr(const char *func_name) { + return dlsym(RTLD_NEXT, func_name); +} + #if !defined(__ANDROID__) // android does not have dlvsym void *GetFuncAddrVer(const char *func_name, const char *ver) { return dlvsym(RTLD_NEXT, func_name, ver); Index: sanitizer_common/CMakeLists.txt =================================================================== --- sanitizer_common/CMakeLists.txt +++ sanitizer_common/CMakeLists.txt @@ -73,6 +73,8 @@ sanitizer_syscall_linux_x86_64.inc sanitizer_thread_registry.h) +include_directories(..) + set(SANITIZER_COMMON_DEFINITIONS) if(ANDROID) @@ -130,11 +132,13 @@ SOURCES ${SANITIZER_LIBCDEP_SOURCES} CFLAGS ${SANITIZER_CFLAGS} DEFS ${SANITIZER_COMMON_DEFINITIONS}) add_compiler_rt_static_runtime(clang_rt.san-${arch} ${arch} - SOURCES $ + SOURCES $ + $ $ CFLAGS ${SANITIZER_CFLAGS} DEFS ${SANITIZER_COMMON_DEFINITIONS}) - list(APPEND SANITIZER_RUNTIME_LIBRARIES RTSanitizerCommon.${arch} + list(APPEND SANITIZER_RUNTIME_LIBRARIES RTInterception.${arch} + RTSanitizerCommon.${arch} RTSanitizerCommonLibc.${arch}) endforeach() endif() 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_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" @@ -661,6 +662,10 @@ } #endif +bool IsDeadlySignal(int signum) { + return (signum == SIGSEGV) && common_flags()->handle_segv; +} + } // namespace __sanitizer #endif // SANITIZER_LINUX Index: sanitizer_common/sanitizer_mac.cc =================================================================== --- sanitizer_common/sanitizer_mac.cc +++ sanitizer_common/sanitizer_mac.cc @@ -23,22 +23,24 @@ #include #include "sanitizer_common.h" +#include "sanitizer_flags.h" #include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" #include "sanitizer_placement_new.h" #include "sanitizer_procmaps.h" #include // for _NSGetEnviron +#include #include #include #include +#include #include #include #include #include #include #include -#include namespace __sanitizer { @@ -238,6 +240,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_interception.h" #include "sanitizer_stacktrace.h" #include @@ -117,6 +119,32 @@ UnmapOrDie(oldstack.ss_sp, oldstack.ss_size); } +typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); +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; + // Can't use internal_sigaction, which is Linux-only. + int (*sigaction_p)(int, void *, void *); + *(void**)&sigaction_p = GET_REAL_SLOW(sigaction); + CHECK_EQ(0, sigaction_p(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) __sanitizer::SetAlternateSignalStack(); + MaybeInstallSigaction(SIGSEGV, handler); + MaybeInstallSigaction(SIGBUS, handler); +} + } // namespace __sanitizer #endif Index: sanitizer_common/tests/CMakeLists.txt =================================================================== --- sanitizer_common/tests/CMakeLists.txt +++ sanitizer_common/tests/CMakeLists.txt @@ -120,6 +120,7 @@ else() if(CAN_TARGET_x86_64) add_sanitizer_common_lib("RTSanitizerCommon.test.x86_64" + $ $ $) add_sanitizer_common_lib("RTSanitizerCommon.test.nolibc.x86_64" @@ -127,6 +128,7 @@ endif() if(CAN_TARGET_i386) add_sanitizer_common_lib("RTSanitizerCommon.test.i386" + $ $ $) endif()