Index: lib/dfsan/CMakeLists.txt =================================================================== --- lib/dfsan/CMakeLists.txt +++ lib/dfsan/CMakeLists.txt @@ -25,6 +25,7 @@ add_compiler_rt_runtime(clang_rt.dfsan-libc-${arch} ${arch} STATIC SOURCES ${DFSAN_RTL_SOURCES} $ + $ CFLAGS ${DFSAN_NOLIBC_CFLAGS}) add_sanitizer_rt_symbols(clang_rt.dfsan-${arch} dfsan.syms.extra) add_dependencies(dfsan Index: lib/safestack/CMakeLists.txt =================================================================== --- lib/safestack/CMakeLists.txt +++ lib/safestack/CMakeLists.txt @@ -22,6 +22,7 @@ SOURCES ${SAFESTACK_SOURCES} $ $ + $ CFLAGS ${SAFESTACK_CFLAGS}) add_dependencies(safestack clang_rt.safestack-${arch}) endforeach() Index: lib/sanitizer_common/CMakeLists.txt =================================================================== --- lib/sanitizer_common/CMakeLists.txt +++ lib/sanitizer_common/CMakeLists.txt @@ -33,6 +33,12 @@ sanitizer_thread_registry.cc sanitizer_win.cc) +# Libc functions stubs. These sources should be linked instead of +# SANITIZER_LIBCDEP_SOURCES when sanitizer_common library must not depend on +# libc. +set(SANITIZER_NOLIBC_SOURCES + sanitizer_common_nolibc.cc) + set(SANITIZER_LIBCDEP_SOURCES sanitizer_common_libcdep.cc sanitizer_coverage_libcdep.cc @@ -145,6 +151,10 @@ ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} SOURCES ${SANITIZER_SOURCES} CFLAGS ${SANITIZER_CFLAGS} DEFS ${SANITIZER_COMMON_DEFINITIONS}) + add_compiler_rt_object_libraries(RTSanitizerCommonNoLibc + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES ${SANITIZER_NOLIBC_SOURCES} CFLAGS ${SANITIZER_CFLAGS} + DEFS ${SANITIZER_COMMON_DEFINITIONS}) add_compiler_rt_object_libraries(RTSanitizerCommonLibc ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} SOURCES ${SANITIZER_LIBCDEP_SOURCES} CFLAGS ${SANITIZER_CFLAGS} Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -628,15 +628,20 @@ ANDROID_POST_LOLLIPOP = 23 }; -#if SANITIZER_ANDROID +#if SANITIZER_POSIX // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); -void AndroidLogWrite(const char *buffer); +void WriteToSyslog(const char *buffer); +#else +INLINE void AndroidLogInit() {} +INLINE void WriteToSyslog(const char *buffer) {} +#endif + +#if SANITIZER_ANDROID void GetExtraActivationFlags(char *buf, uptr size); void SanitizerInitializeUnwinder(); AndroidApiLevel AndroidGetApiLevel(); #else -INLINE void AndroidLogInit() {} INLINE void AndroidLogWrite(const char *buffer_unused) {} INLINE void GetExtraActivationFlags(char *buf, uptr size) { *buf = '\0'; } INLINE void SanitizerInitializeUnwinder() {} Index: lib/sanitizer_common/sanitizer_common_nolibc.cc =================================================================== --- lib/sanitizer_common/sanitizer_common_nolibc.cc +++ lib/sanitizer_common/sanitizer_common_nolibc.cc @@ -0,0 +1,21 @@ +//===-- sanitizer_common_nolibc.cc ----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains stubs for libc function to facilitate optional use of +// libc in no-libcdep sources. +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" +#include "sanitizer_common.h" + +namespace __sanitizer { + +void WriteToSyslog(const char *buffer) {} + +} Index: lib/sanitizer_common/sanitizer_flags.inc =================================================================== --- lib/sanitizer_common/sanitizer_flags.inc +++ lib/sanitizer_common/sanitizer_flags.inc @@ -55,6 +55,10 @@ "Mention name of executable when reporting error and " "append executable name to logs (as in \"log_path.exe_name.pid\").") COMMON_FLAG( + bool, log_to_syslog, SANITIZER_ANDROID, + "Write all sanitizer output to syslog in addition to other means of " + "logging.") +COMMON_FLAG( int, verbosity, 0, "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).") COMMON_FLAG(bool, detect_leaks, true, "Enable memory leak detection.") Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -15,7 +15,6 @@ #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX -#include "sanitizer_allocator_internal.h" #include "sanitizer_common.h" #include "sanitizer_flags.h" #include "sanitizer_internal_defs.h" @@ -75,7 +74,6 @@ #endif #if SANITIZER_ANDROID -#include #include #endif @@ -920,33 +918,6 @@ #endif // defined(__x86_64__) && SANITIZER_LINUX #if SANITIZER_ANDROID -static atomic_uint8_t android_log_initialized; - -void AndroidLogInit() { - atomic_store(&android_log_initialized, 1, memory_order_release); -} -// This thing is not, strictly speaking, async signal safe, but it does not seem -// to cause any issues. Alternative is writing to log devices directly, but -// their location and message format might change in the future, so we'd really -// like to avoid that. -void AndroidLogWrite(const char *buffer) { - if (!atomic_load(&android_log_initialized, memory_order_acquire)) - return; - - char *copy = internal_strdup(buffer); - char *p = copy; - char *q; - // __android_log_write has an implicit message length limit. - // Print one line at a time. - do { - q = internal_strchr(p, '\n'); - if (q) *q = '\0'; - __android_log_write(ANDROID_LOG_INFO, NULL, p); - if (q) p = q + 1; - } while (q); - InternalFree(copy); -} - void GetExtraActivationFlags(char *buf, uptr size) { CHECK(size > PROP_VALUE_MAX); __system_property_get("asan.options", buf); Index: lib/sanitizer_common/sanitizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -15,6 +15,7 @@ #include "sanitizer_platform.h" #if SANITIZER_POSIX +#include "sanitizer_allocator_internal.h" #include "sanitizer_common.h" #include "sanitizer_flags.h" #include "sanitizer_platform_limits_posix.h" @@ -30,11 +31,17 @@ #include #include #include +#include #include #include -#include #include +#if SANITIZER_ANDROID && __ANDROID_API__ < 21 +#include +#else +#include +#endif + #if SANITIZER_FREEBSD // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before // that, it was never implemented. So just define it to zero. @@ -275,6 +282,49 @@ 0); } -} // namespace __sanitizer +// 64-bit Android targets don't provide the deprecated __android_log_write. +// Starting with the L release, syslog() works and is preferable to +// __android_log_write. +#if SANITIZER_ANDROID && __ANDROID_API__ < 21 +static atomic_uint8_t android_log_initialized; + +void AndroidLogInit() { + atomic_store(&android_log_initialized, 1, memory_order_release); +} + +static bool IsSyslogAvailable() { + return atomic_load(&android_log_initialized, memory_order_acquire); +} + +static void WriteOneLineToSyslog(const char *s) { + __android_log_write(ANDROID_LOG_INFO, NULL, s); +} +#else +void AndroidLogInit() {} + +static bool IsSyslogAvailable() { return true; } + +static void WriteOneLineToSyslog(const char *s) { syslog(LOG_INFO, "%s", s); } +#endif + +void WriteToSyslog(const char *buffer) { + if (!IsSyslogAvailable()) + return; + char *copy = internal_strdup(buffer); + char *p = copy; + char *q; + // syslog, at least on Android, has an implicit message length limit. + // Print one line at a time. + do { + q = internal_strchr(p, '\n'); + if (q) + *q = '\0'; + WriteOneLineToSyslog(p); + if (q) + p = q + 1; + } while (q); + InternalFree(copy); +} +} // namespace __sanitizer #endif // SANITIZER_POSIX Index: lib/sanitizer_common/sanitizer_printf.cc =================================================================== --- lib/sanitizer_common/sanitizer_printf.cc +++ lib/sanitizer_common/sanitizer_printf.cc @@ -279,7 +279,8 @@ # undef CHECK_NEEDED_LENGTH } RawWrite(buffer); - AndroidLogWrite(buffer); + if (common_flags()->log_to_syslog) + WriteToSyslog(buffer); CallPrintfAndReportCallback(buffer); // If we had mapped any memory, clean up. if (buffer != local_buffer) Index: lib/sanitizer_common/tests/CMakeLists.txt =================================================================== --- lib/sanitizer_common/tests/CMakeLists.txt +++ lib/sanitizer_common/tests/CMakeLists.txt @@ -172,7 +172,8 @@ else() if(CAN_TARGET_x86_64) add_sanitizer_common_lib("RTSanitizerCommon.test.nolibc.x86_64" - $) + $ + $) endif() foreach(arch ${SANITIZER_UNITTEST_SUPPORTED_ARCH}) add_sanitizer_common_lib("RTSanitizerCommon.test.${arch}"