From 5a59af672d2dc6fb5e5076afe633f4af10211201 Mon Sep 17 00:00:00 2001 From: kcc Date: Thu, 21 Feb 2013 10:57:10 +0000 Subject: [PATCH] libsanitizer merge from upstream r175733 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196201 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 + gcc/config/i386/i386.c | 3 +- libsanitizer/ChangeLog | 6 + libsanitizer/MERGE | 2 +- libsanitizer/asan/asan_flags.h | 8 +- libsanitizer/asan/asan_intercepted_functions.h | 59 +++++-- libsanitizer/asan/asan_interceptors.cc | 13 +- libsanitizer/asan/asan_internal.h | 6 +- libsanitizer/asan/asan_mac.cc | 110 ++++++++++++- libsanitizer/asan/asan_mapping.h | 112 +++++++++++-- libsanitizer/asan/asan_report.cc | 4 +- libsanitizer/asan/asan_rtl.cc | 175 ++++++++++++++++----- .../asan/dynamic/asan_interceptors_dynamic.cc | 114 -------------- libsanitizer/include/sanitizer/asan_interface.h | 4 +- .../include/sanitizer/common_interface_defs.h | 5 + libsanitizer/sanitizer_common/Makefile.am | 1 + libsanitizer/sanitizer_common/Makefile.in | 13 +- libsanitizer/sanitizer_common/sanitizer_common.cc | 2 +- libsanitizer/sanitizer_common/sanitizer_common.h | 2 +- .../sanitizer_common_interceptors.inc | 103 +++++++++++- libsanitizer/sanitizer_common/sanitizer_flags.cc | 3 +- .../sanitizer_common/sanitizer_internal_defs.h | 2 +- libsanitizer/sanitizer_common/sanitizer_libc.h | 6 +- libsanitizer/sanitizer_common/sanitizer_linux.cc | 36 ++++- libsanitizer/sanitizer_common/sanitizer_mac.cc | 4 + .../sanitizer_platform_interceptors.h | 10 ++ .../sanitizer_platform_limits_posix.cc | 68 ++++++++ .../sanitizer_platform_limits_posix.h | 41 +++++ libsanitizer/sanitizer_common/sanitizer_posix.cc | 8 +- .../sanitizer_common/sanitizer_stacktrace.cc | 5 +- .../sanitizer_common/sanitizer_symbolizer_linux.cc | 2 +- libsanitizer/sanitizer_common/sanitizer_win.cc | 12 +- libsanitizer/tsan/tsan_platform_linux.cc | 2 +- libsanitizer/tsan/tsan_platform_mac.cc | 2 +- libsanitizer/tsan/tsan_platform_windows.cc | 2 +- libsanitizer/tsan/tsan_rtl.h | 2 + libsanitizer/tsan/tsan_rtl_thread.cc | 22 +++ libsanitizer/tsan/tsan_stat.cc | 8 + libsanitizer/tsan/tsan_stat.h | 8 + libsanitizer/tsan/tsan_suppressions.cc | 2 +- 40 files changed, 767 insertions(+), 225 deletions(-) delete mode 100644 libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc create mode 100644 libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc create mode 100644 libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 067a61f7f0b..ca184f2ecbf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2013-02-23 Kostya Serebryany + + * config/i386/i386.c (ix86_asan_shadow_offset): Use 0x7fff8000 as + asan_shadow_offset on x86_64 linux. + 2013-02-21 Richard Biener PR tree-optimization/56415 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f9f266a3dc6..b835c5da2ab 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5436,7 +5436,8 @@ ix86_legitimate_combined_insn (rtx insn) static unsigned HOST_WIDE_INT ix86_asan_shadow_offset (void) { - return TARGET_LP64 ? (HOST_WIDE_INT_1 << 44) + return TARGET_LP64 ? (TARGET_MACHO ? (HOST_WIDE_INT_1 << 44) + : HOST_WIDE_INT_C (0x7fff8000)) : (HOST_WIDE_INT_1 << 29); } diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index eb6a3456e47..ed857384853 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,9 @@ +2013-02-21 Kostya Serebryany + + * All source files: Merge from upstream r175733. + * sanitizer_common/Makefile.am: Added a new file. + * sanitizer_common/Makefile.in: Regenerated. + 2013-02-14 H.J. Lu PR bootstrap/56327 diff --git a/libsanitizer/MERGE b/libsanitizer/MERGE index 02d2bfcf512..28d1e49ab77 100644 --- a/libsanitizer/MERGE +++ b/libsanitizer/MERGE @@ -1,4 +1,4 @@ -175049 +175733 The first line of this file holds the svn revision number of the last merge done from the master library sources. diff --git a/libsanitizer/asan/asan_flags.h b/libsanitizer/asan/asan_flags.h index b05fdc3acc6..b880896c7a3 100644 --- a/libsanitizer/asan/asan_flags.h +++ b/libsanitizer/asan/asan_flags.h @@ -15,11 +15,13 @@ #include "sanitizer_common/sanitizer_internal_defs.h" -// ASan flag values can be defined in three ways: +// ASan flag values can be defined in four ways: // 1) initialized with default values at startup. -// 2) overriden from string returned by user-specified function +// 2) overriden during compilation of ASan runtime by providing +// compile definition ASAN_DEFAULT_OPTIONS. +// 3) overriden from string returned by user-specified function // __asan_default_options(). -// 3) overriden from env variable ASAN_OPTIONS. +// 4) overriden from env variable ASAN_OPTIONS. namespace __asan { diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h index 45c913c1894..ed75c428439 100644 --- a/libsanitizer/asan/asan_intercepted_functions.h +++ b/libsanitizer/asan/asan_intercepted_functions.h @@ -77,9 +77,36 @@ using __sanitizer::uptr; # define ASAN_INTERCEPT___CXA_THROW 0 #endif +#define INTERPOSE_FUNCTION(function) \ + { reinterpret_cast(WRAP(function)), \ + reinterpret_cast(function) } + +#define INTERPOSE_FUNCTION_2(function, wrapper) \ + { reinterpret_cast(wrapper), \ + reinterpret_cast(function) } + +struct interpose_substitution { + const uptr replacement; + const uptr original; +}; + +#define INTERPOSER(func) __attribute__((used)) \ +const interpose_substitution substitution_##func[] \ + __attribute__((section("__DATA, __interpose"))) = { \ + INTERPOSE_FUNCTION(func), \ +} + +#define INTERPOSER_2(func, wrapper) __attribute__((used)) \ +const interpose_substitution substitution_##func[] \ + __attribute__((section("__DATA, __interpose"))) = { \ + INTERPOSE_FUNCTION_2(func, wrapper), \ +} + + #define DECLARE_FUNCTION_AND_WRAPPER(ret_type, func, ...) \ ret_type func(__VA_ARGS__); \ - ret_type WRAP(func)(__VA_ARGS__) + ret_type WRAP(func)(__VA_ARGS__); \ + INTERPOSER(func) // Use extern declarations of intercepted functions on Mac and Windows // to avoid including system headers. @@ -139,7 +166,8 @@ DECLARE_FUNCTION_AND_WRAPPER(char*, strdup, const char *s); DECLARE_FUNCTION_AND_WRAPPER(uptr, strnlen, const char *s, uptr maxlen); # endif # if ASAN_INTERCEPT_INDEX -DECLARE_FUNCTION_AND_WRAPPER(char*, index, const char *string, int c); +char* index(const char *string, int c); +INTERPOSER_2(index, WRAP(strchr)); # endif // stdlib.h @@ -193,6 +221,20 @@ DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create, void *(*start_routine)(void*), void *arg); # endif +# if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS +DECLARE_FUNCTION_AND_WRAPPER(void *, localtime, unsigned long *timep); +DECLARE_FUNCTION_AND_WRAPPER(void *, localtime_r, unsigned long *timep, + void *result); +DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime, unsigned long *timep); +DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime_r, unsigned long *timep, + void *result); +DECLARE_FUNCTION_AND_WRAPPER(char *, ctime, unsigned long *timep); +DECLARE_FUNCTION_AND_WRAPPER(char *, ctime_r, unsigned long *timep, + char *result); +DECLARE_FUNCTION_AND_WRAPPER(char *, asctime, void *tm); +DECLARE_FUNCTION_AND_WRAPPER(char *, asctime_r, void *tm, char *result); +# endif + // stdio.h # if SANITIZER_INTERCEPT_SCANF DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap); @@ -205,17 +247,6 @@ DECLARE_FUNCTION_AND_WRAPPER(int, fscanf, void* stream, const char *format, ...); DECLARE_FUNCTION_AND_WRAPPER(int, sscanf, // NOLINT const char *str, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vscanf, const char *format, - va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vsscanf, const char *str, - const char *format, va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vfscanf, void *stream, - const char *format, va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_scanf, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_fscanf, - void* stream, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_sscanf, // NOLINT - const char *str, const char *format, ...); # endif # if defined(__APPLE__) @@ -278,9 +309,11 @@ DECLARE_FUNCTION_AND_WRAPPER(void *, valloc, size_t size); DECLARE_FUNCTION_AND_WRAPPER(size_t, malloc_good_size, size_t size); DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign, void **memptr, size_t alignment, size_t size); +#if 0 DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_prepare, void); DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void); DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void); +#endif diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc index f4c56830d8a..064fc6261b0 100644 --- a/libsanitizer/asan/asan_interceptors.cc +++ b/libsanitizer/asan/asan_interceptors.cc @@ -24,6 +24,16 @@ namespace __asan { +// Return true if we can quickly decide that the region is unpoisoned. +static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { + if (size == 0) return true; + if (size <= 32) + return !AddressIsPoisoned(beg) && + !AddressIsPoisoned(beg + size - 1) && + !AddressIsPoisoned(beg + size / 2); + return false; +} + // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, // and ASAN_WRITE_RANGE as macro instead of function so // that no extra frames are created, and stack trace contains @@ -32,7 +42,8 @@ namespace __asan { #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ uptr __offset = (uptr)(offset); \ uptr __size = (uptr)(size); \ - if (__asan_region_is_poisoned(__offset, __size)) { \ + if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ + __asan_region_is_poisoned(__offset, __size)) { \ GET_CURRENT_PC_BP_SP; \ __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \ } \ diff --git a/libsanitizer/asan/asan_internal.h b/libsanitizer/asan/asan_internal.h index 0fe620e2e4c..1ccbf108647 100644 --- a/libsanitizer/asan/asan_internal.h +++ b/libsanitizer/asan/asan_internal.h @@ -52,7 +52,7 @@ #define ASAN_POSIX (ASAN_LINUX || ASAN_MAC) -#if __has_feature(address_sanitizer) +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # error "The AddressSanitizer run-time should not be" " instrumented by AddressSanitizer" #endif @@ -89,6 +89,10 @@ # endif #endif +#ifndef ASAN_USE_PREINIT_ARRAY +# define ASAN_USE_PREINIT_ARRAY (ASAN_LINUX && !ASAN_ANDROID) +#endif + // All internal functions in asan reside inside the __asan namespace // to avoid namespace collisions with the user programs. // Seperate namespace also makes it simpler to distinguish the asan run-time diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc index c5fc7de10c0..dd2657df1e2 100644 --- a/libsanitizer/asan/asan_mac.cc +++ b/libsanitizer/asan/asan_mac.cc @@ -86,6 +86,39 @@ extern "C" void __asan_init(); static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; +LowLevelAllocator allocator_for_env; + +// Change the value of the env var |name|, leaking the original value. +// If |name_value| is NULL, the variable is deleted from the environment, +// otherwise the corresponding "NAME=value" string is replaced with +// |name_value|. +void LeakyResetEnv(const char *name, const char *name_value) { + char ***env_ptr = _NSGetEnviron(); + CHECK(env_ptr); + char **environ = *env_ptr; + CHECK(environ); + uptr name_len = internal_strlen(name); + while (*environ != 0) { + uptr len = internal_strlen(*environ); + if (len > name_len) { + const char *p = *environ; + if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { + // Match. + if (name_value) { + // Replace the old value with the new one. + *environ = const_cast(name_value); + } else { + // Shift the subsequent pointers back. + char **del = environ; + do { + del[0] = del[1]; + } while (*del++); + } + } + } + environ++; + } +} void MaybeReexec() { if (!flags()->allow_reexec) return; @@ -94,7 +127,11 @@ void MaybeReexec() { // ourselves. Dl_info info; CHECK(dladdr((void*)((uptr)__asan_init), &info)); - const char *dyld_insert_libraries = GetEnv(kDyldInsertLibraries); + char *dyld_insert_libraries = + const_cast(GetEnv(kDyldInsertLibraries)); + uptr old_env_len = dyld_insert_libraries ? + internal_strlen(dyld_insert_libraries) : 0; + uptr fname_len = internal_strlen(info.dli_fname); if (!dyld_insert_libraries || !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) { // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime @@ -102,16 +139,79 @@ void MaybeReexec() { char program_name[1024]; uint32_t buf_size = sizeof(program_name); _NSGetExecutablePath(program_name, &buf_size); - // Ok to use setenv() since the wrappers don't depend on the value of - // asan_inited. - setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + char *new_env = const_cast(info.dli_fname); + if (dyld_insert_libraries) { + // Append the runtime dylib name to the existing value of + // DYLD_INSERT_LIBRARIES. + new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); + internal_strncpy(new_env, dyld_insert_libraries, old_env_len); + new_env[old_env_len] = ':'; + // Copy fname_len and add a trailing zero. + internal_strncpy(new_env + old_env_len + 1, info.dli_fname, + fname_len + 1); + // Ok to use setenv() since the wrappers don't depend on the value of + // asan_inited. + setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); + } else { + // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. + setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + } if (flags()->verbosity >= 1) { Report("exec()-ing the program with\n"); - Report("%s=%s\n", kDyldInsertLibraries, info.dli_fname); + Report("%s=%s\n", kDyldInsertLibraries, new_env); Report("to enable ASan wrappers.\n"); Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n"); } execv(program_name, *_NSGetArgv()); + } else { + // DYLD_INSERT_LIBRARIES is set and contains the runtime library. + if (old_env_len == fname_len) { + // It's just the runtime library name - fine to unset the variable. + LeakyResetEnv(kDyldInsertLibraries, NULL); + } else { + uptr env_name_len = internal_strlen(kDyldInsertLibraries); + // Allocate memory to hold the previous env var name, its value, the '=' + // sign and the '\0' char. + char *new_env = (char*)allocator_for_env.Allocate( + old_env_len + 2 + env_name_len); + CHECK(new_env); + internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); + internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); + new_env[env_name_len] = '='; + char *new_env_pos = new_env + env_name_len + 1; + + // Iterate over colon-separated pieces of |dyld_insert_libraries|. + char *piece_start = dyld_insert_libraries; + char *piece_end = NULL; + char *old_env_end = dyld_insert_libraries + old_env_len; + do { + if (piece_start[0] == ':') piece_start++; + piece_end = REAL(strchr)(piece_start, ':'); + if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; + if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; + uptr piece_len = piece_end - piece_start; + + // If the current piece isn't the runtime library name, + // append it to new_env. + if ((piece_len != fname_len) || + (internal_strncmp(piece_start, info.dli_fname, fname_len) != 0)) { + if (new_env_pos != new_env + env_name_len + 1) { + new_env_pos[0] = ':'; + new_env_pos++; + } + internal_strncpy(new_env_pos, piece_start, piece_len); + } + // Move on to the next piece. + new_env_pos += piece_len; + piece_start = piece_end; + } while (piece_start < old_env_end); + + // Can't use setenv() here, because it requires the allocator to be + // initialized. + // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in + // a separate function called after InitializeAllocator(). + LeakyResetEnv(kDyldInsertLibraries, new_env); + } } } diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h index 48b24545b99..df952363893 100644 --- a/libsanitizer/asan/asan_mapping.h +++ b/libsanitizer/asan/asan_mapping.h @@ -1,7 +1,5 @@ //===-- asan_mapping.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // @@ -18,6 +16,37 @@ // The full explanation of the memory mapping could be found here: // http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm +// +// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: +// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || +// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || +// || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap || +// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || +// || `[0x000000000000, 0x00007fff7fff]` || LowMem || +// +// When SHADOW_OFFSET is zero (-pie): +// || `[0x100000000000, 0x7fffffffffff]` || HighMem || +// || `[0x020000000000, 0x0fffffffffff]` || HighShadow || +// || `[0x000000040000, 0x01ffffffffff]` || ShadowGap || +// +// Special case when something is already mapped between +// 0x003000000000 and 0x004000000000 (e.g. when prelink is installed): +// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || +// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || +// || `[0x004000000000, 0x02008fff6fff]` || ShadowGap3 || +// || `[0x003000000000, 0x003fffffffff]` || MidMem || +// || `[0x00087fff8000, 0x002fffffffff]` || ShadowGap2 || +// || `[0x00067fff8000, 0x00087fff7fff]` || MidShadow || +// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap || +// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || +// || `[0x000000000000, 0x00007fff7fff]` || LowMem || +// +// Default Linux/i386 mapping: +// || `[0x40000000, 0xffffffff]` || HighMem || +// || `[0x28000000, 0x3fffffff]` || HighShadow || +// || `[0x24000000, 0x27ffffff]` || ShadowGap || +// || `[0x20000000, 0x23ffffff]` || LowShadow || +// || `[0x00000000, 0x1fffffff]` || LowMem || #if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1 extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale; @@ -36,7 +65,11 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; # if defined(__powerpc64__) # define SHADOW_OFFSET (1ULL << 41) # else -# define SHADOW_OFFSET (1ULL << 44) +# if ASAN_MAC +# define SHADOW_OFFSET (1ULL << 44) +# else +# define SHADOW_OFFSET 0x7fff8000ULL +# endif # endif # endif # endif @@ -57,49 +90,105 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) #define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) +# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) +# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) + // With the zero shadow base we can not actually map pages starting from 0. // This constant is somewhat arbitrary. #define kZeroBaseShadowStart (1 << 18) #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ : kZeroBaseShadowStart) -#define kShadowGapEnd (kHighShadowBeg - 1) +#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) + +#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) +#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) + +#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) +#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) + +#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. + +#if DO_ASAN_MAPPING_PROFILE +# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; +#else +# define PROFILE_ASAN_MAPPING() +#endif + +// If 1, all shadow boundaries are constants. +// Don't set to 1 other than for testing. +#define ASAN_FIXED_MAPPING 0 namespace __asan { +extern uptr AsanMappingProfile[]; + +#if ASAN_FIXED_MAPPING +// Fixed mapping for 64-bit Linux. Mostly used for performance comparison +// with non-fixed mapping. As of r175253 (Feb 2013) the performance +// difference between fixed and non-fixed mapping is below the noise level. +static uptr kHighMemEnd = 0x7fffffffffffULL; +static uptr kMidMemBeg = 0x3000000000ULL; +static uptr kMidMemEnd = 0x3fffffffffULL; +#else SANITIZER_INTERFACE_ATTRIBUTE -extern uptr kHighMemEnd; // Initialized in __asan_init. +extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. +#endif static inline bool AddrIsInLowMem(uptr a) { + PROFILE_ASAN_MAPPING(); return a < kLowMemEnd; } static inline bool AddrIsInLowShadow(uptr a) { + PROFILE_ASAN_MAPPING(); return a >= kLowShadowBeg && a <= kLowShadowEnd; } static inline bool AddrIsInHighMem(uptr a) { + PROFILE_ASAN_MAPPING(); return a >= kHighMemBeg && a <= kHighMemEnd; } +static inline bool AddrIsInMidMem(uptr a) { + PROFILE_ASAN_MAPPING(); + return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; +} + static inline bool AddrIsInMem(uptr a) { - return AddrIsInLowMem(a) || AddrIsInHighMem(a); + PROFILE_ASAN_MAPPING(); + return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); } static inline uptr MemToShadow(uptr p) { + PROFILE_ASAN_MAPPING(); CHECK(AddrIsInMem(p)); return MEM_TO_SHADOW(p); } static inline bool AddrIsInHighShadow(uptr a) { - return a >= kHighShadowBeg && a <= kHighMemEnd; + PROFILE_ASAN_MAPPING(); + return a >= kHighShadowBeg && a <= kHighMemEnd; +} + +static inline bool AddrIsInMidShadow(uptr a) { + PROFILE_ASAN_MAPPING(); + return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd; } static inline bool AddrIsInShadow(uptr a) { - return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); + PROFILE_ASAN_MAPPING(); + return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); } static inline bool AddrIsInShadowGap(uptr a) { + PROFILE_ASAN_MAPPING(); + if (kMidMemBeg) { + if (a <= kShadowGapEnd) + return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; + return (a >= kShadowGap2Beg && a <= kShadowGap2End) || + (a >= kShadowGap3Beg && a <= kShadowGap3End); + } // In zero-based shadow mode we treat addresses near zero as addresses // in shadow gap as well. if (SHADOW_OFFSET == 0) @@ -108,12 +197,14 @@ static inline bool AddrIsInShadowGap(uptr a) { } static inline bool AddrIsAlignedByGranularity(uptr a) { + PROFILE_ASAN_MAPPING(); return (a & (SHADOW_GRANULARITY - 1)) == 0; } static inline bool AddressIsPoisoned(uptr a) { + PROFILE_ASAN_MAPPING(); const uptr kAccessSize = 1; - u8 *shadow_address = (u8*)MemToShadow(a); + u8 *shadow_address = (u8*)MEM_TO_SHADOW(a); s8 shadow_value = *shadow_address; if (shadow_value) { u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1)) @@ -123,6 +214,9 @@ static inline bool AddressIsPoisoned(uptr a) { return false; } +// Must be after all calls to PROFILE_ASAN_MAPPING(). +static const uptr kAsanMappingProfileSize = __LINE__; + } // namespace __asan #endif // ASAN_MAPPING_H diff --git a/libsanitizer/asan/asan_report.cc b/libsanitizer/asan/asan_report.cc index 663e8f3b748..13e94c421b5 100644 --- a/libsanitizer/asan/asan_report.cc +++ b/libsanitizer/asan/asan_report.cc @@ -433,9 +433,9 @@ class ScopedInErrorReport { // an error report will finish doing it. SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); } - // If we're still not dead for some reason, use raw Exit() instead of + // If we're still not dead for some reason, use raw _exit() instead of // Die() to bypass any additional checks. - Exit(flags()->exitcode); + internal__exit(flags()->exitcode); } ASAN_ON_ERROR(); reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc index 175d37788c2..e22fcd34fb1 100644 --- a/libsanitizer/asan/asan_rtl.cc +++ b/libsanitizer/asan/asan_rtl.cc @@ -25,6 +25,8 @@ namespace __asan { +uptr AsanMappingProfile[kAsanMappingProfileSize]; + static void AsanDie() { static atomic_uint32_t num_calls; if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { @@ -35,13 +37,19 @@ static void AsanDie() { Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); SleepForSeconds(flags()->sleep_before_dying); } - if (flags()->unmap_shadow_on_exit) - UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + if (flags()->unmap_shadow_on_exit) { + if (kMidMemBeg) { + UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); + UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); + } else { + UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + } + } if (death_callback) death_callback(); if (flags()->abort_on_error) Abort(); - Exit(flags()->exitcode); + internal__exit(flags()->exitcode); } static void AsanCheckFailed(const char *file, int line, const char *cond, @@ -66,6 +74,17 @@ static const char *MaybeCallAsanDefaultOptions() { return (&__asan_default_options) ? __asan_default_options() : ""; } +static const char *MaybeUseAsanDefaultOptionsCompileDefiniton() { +#ifdef ASAN_DEFAULT_OPTIONS +// Stringize the macro value. +# define ASAN_STRINGIZE(x) #x +# define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options) + return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS); +#else + return ""; +#endif +} + static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->quarantine_size, "quarantine_size"); ParseFlag(str, &f->symbolize, "symbolize"); @@ -146,6 +165,9 @@ void InitializeFlags(Flags *f, const char *env) { f->alloc_dealloc_mismatch = true; f->use_stack_depot = true; // Only affects allocator2. + // Override from compile definition. + ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton()); + // Override from user-specified string. ParseFlagsFromString(f, MaybeCallAsanDefaultOptions()); if (flags()->verbosity) { @@ -161,7 +183,10 @@ void InitializeFlags(Flags *f, const char *env) { int asan_inited; bool asan_init_is_running; void (*death_callback)(void); -uptr kHighMemEnd; + +#if !ASAN_FIXED_MAPPING +uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; +#endif // -------------------------- Misc ---------------- {{{1 void ShowStatsAndAbort() { @@ -209,6 +234,17 @@ ASAN_REPORT_ERROR(store, true, 4) ASAN_REPORT_ERROR(store, true, 8) ASAN_REPORT_ERROR(store, true, 16) +#define ASAN_REPORT_ERROR_N(type, is_write) \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## _n(uptr addr, uptr size); \ +void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ + GET_CALLER_PC_BP_SP; \ + __asan_report_error(pc, bp, sp, addr, is_write, size); \ +} + +ASAN_REPORT_ERROR_N(load, false) +ASAN_REPORT_ERROR_N(store, true) + // Force the linker to keep the symbols for various ASan interface functions. // We want to keep those in the executable in order to let the instrumented // dynamic libraries access the symbol even if it is not used by the executable @@ -259,9 +295,15 @@ static NOINLINE void force_interface_symbols() { static void asan_atexit() { Printf("AddressSanitizer exit stats:\n"); __asan_print_accumulated_stats(); + // Print AsanMappingProfile. + for (uptr i = 0; i < kAsanMappingProfileSize; i++) { + if (AsanMappingProfile[i] == 0) continue; + Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); + } } static void InitializeHighMemEnd() { +#if !ASAN_FIXED_MAPPING #if SANITIZER_WORDSIZE == 64 # if defined(__powerpc64__) // FIXME: @@ -277,6 +319,58 @@ static void InitializeHighMemEnd() { #else // SANITIZER_WORDSIZE == 32 kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff; #endif // SANITIZER_WORDSIZE +#endif // !ASAN_FIXED_MAPPING +} + +static void ProtectGap(uptr a, uptr size) { + CHECK_EQ(a, (uptr)Mprotect(a, size)); +} + +static void PrintAddressSpaceLayout() { + Printf("|| `[%p, %p]` || HighMem ||\n", + (void*)kHighMemBeg, (void*)kHighMemEnd); + Printf("|| `[%p, %p]` || HighShadow ||\n", + (void*)kHighShadowBeg, (void*)kHighShadowEnd); + if (kMidMemBeg) { + Printf("|| `[%p, %p]` || ShadowGap3 ||\n", + (void*)kShadowGap3Beg, (void*)kShadowGap3End); + Printf("|| `[%p, %p]` || MidMem ||\n", + (void*)kMidMemBeg, (void*)kMidMemEnd); + Printf("|| `[%p, %p]` || ShadowGap2 ||\n", + (void*)kShadowGap2Beg, (void*)kShadowGap2End); + Printf("|| `[%p, %p]` || MidShadow ||\n", + (void*)kMidShadowBeg, (void*)kMidShadowEnd); + } + Printf("|| `[%p, %p]` || ShadowGap ||\n", + (void*)kShadowGapBeg, (void*)kShadowGapEnd); + if (kLowShadowBeg) { + Printf("|| `[%p, %p]` || LowShadow ||\n", + (void*)kLowShadowBeg, (void*)kLowShadowEnd); + Printf("|| `[%p, %p]` || LowMem ||\n", + (void*)kLowMemBeg, (void*)kLowMemEnd); + } + Printf("MemToShadow(shadow): %p %p %p %p", + (void*)MEM_TO_SHADOW(kLowShadowBeg), + (void*)MEM_TO_SHADOW(kLowShadowEnd), + (void*)MEM_TO_SHADOW(kHighShadowBeg), + (void*)MEM_TO_SHADOW(kHighShadowEnd)); + if (kMidMemBeg) { + Printf(" %p %p", + (void*)MEM_TO_SHADOW(kMidShadowBeg), + (void*)MEM_TO_SHADOW(kMidShadowEnd)); + } + Printf("\n"); + Printf("red_zone=%zu\n", (uptr)flags()->redzone); + Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size); + + Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE); + Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); + Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); + CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + if (kMidMemBeg) + CHECK(kMidShadowBeg > kLowShadowEnd && + kMidMemBeg > kMidShadowEnd && + kHighShadowBeg > kMidMemEnd); } } // namespace __asan @@ -352,49 +446,48 @@ void __asan_init() { ReplaceSystemMalloc(); ReplaceOperatorsNewAndDelete(); - if (flags()->verbosity) { - Printf("|| `[%p, %p]` || HighMem ||\n", - (void*)kHighMemBeg, (void*)kHighMemEnd); - Printf("|| `[%p, %p]` || HighShadow ||\n", - (void*)kHighShadowBeg, (void*)kHighShadowEnd); - Printf("|| `[%p, %p]` || ShadowGap ||\n", - (void*)kShadowGapBeg, (void*)kShadowGapEnd); - Printf("|| `[%p, %p]` || LowShadow ||\n", - (void*)kLowShadowBeg, (void*)kLowShadowEnd); - Printf("|| `[%p, %p]` || LowMem ||\n", - (void*)kLowMemBeg, (void*)kLowMemEnd); - Printf("MemToShadow(shadow): %p %p %p %p\n", - (void*)MEM_TO_SHADOW(kLowShadowBeg), - (void*)MEM_TO_SHADOW(kLowShadowEnd), - (void*)MEM_TO_SHADOW(kHighShadowBeg), - (void*)MEM_TO_SHADOW(kHighShadowEnd)); - Printf("red_zone=%zu\n", (uptr)flags()->redzone); - Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size); - - Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE); - Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); - Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); - CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + uptr shadow_start = kLowShadowBeg; + if (kLowShadowBeg) shadow_start -= GetMmapGranularity(); + uptr shadow_end = kHighShadowEnd; + bool full_shadow_is_available = + MemoryRangeIsAvailable(shadow_start, shadow_end); + +#if ASAN_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING + if (!full_shadow_is_available) { + kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0; + kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x3fffffffffULL : 0; } +#endif + + if (flags()->verbosity) + PrintAddressSpaceLayout(); if (flags()->disable_core) { DisableCoreDumper(); } - uptr shadow_start = kLowShadowBeg; - if (kLowShadowBeg > 0) shadow_start -= GetMmapGranularity(); - uptr shadow_end = kHighShadowEnd; - if (MemoryRangeIsAvailable(shadow_start, shadow_end)) { - if (kLowShadowBeg != kLowShadowEnd) { - // mmap the low shadow plus at least one page. - ReserveShadowMemoryRange(kLowShadowBeg - GetMmapGranularity(), - kLowShadowEnd); - } + if (full_shadow_is_available) { + // mmap the low shadow plus at least one page at the left. + if (kLowShadowBeg) + ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); + // mmap the high shadow. + ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); + // protect the gap. + ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); + } else if (kMidMemBeg && + MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && + MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) { + CHECK(kLowShadowBeg != kLowShadowEnd); + // mmap the low shadow plus at least one page at the left. + ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); + // mmap the mid shadow. + ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd); // mmap the high shadow. ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); - // protect the gap - void *prot = Mprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); - CHECK(prot == (void*)kShadowGapBeg); + // protect the gaps. + ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); + ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); + ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); } else { Report("Shadow memory range interleaves with an existing memory mapping. " "ASan cannot proceed correctly. ABORTING.\n"); @@ -427,12 +520,12 @@ void __asan_init() { } } -#if defined(ASAN_USE_PREINIT_ARRAY) +#if ASAN_USE_PREINIT_ARRAY // On Linux, we force __asan_init to be called before anyone else // by placing it into .preinit_array section. // FIXME: do we have anything like this on Mac? __attribute__((section(".preinit_array"))) - typeof(__asan_init) *__asan_preinit =__asan_init; + void (*__asan_preinit)(void) =__asan_init; #elif defined(_WIN32) && defined(_DLL) // On Windows, when using dynamic CRT (/MD), we can put a pointer // to __asan_init into the global list of C initializers. diff --git a/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc b/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc deleted file mode 100644 index 727edf2b43b..00000000000 --- a/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc +++ /dev/null @@ -1,114 +0,0 @@ -//===-- asan_interceptors_dynamic.cc --------------------------------------===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// __DATA,__interpose section of the dynamic runtime library for Mac OS. -//===----------------------------------------------------------------------===// - -#if defined(__APPLE__) - -#include "../asan_interceptors.h" -#include "../asan_intercepted_functions.h" - -namespace __asan { - -#define INTERPOSE_FUNCTION(function) \ - { reinterpret_cast(WRAP(function)), \ - reinterpret_cast(function) } - -#define INTERPOSE_FUNCTION_2(function, wrapper) \ - { reinterpret_cast(wrapper), \ - reinterpret_cast(function) } - -struct interpose_substitution { - const uptr replacement; - const uptr original; -}; - -__attribute__((used)) -const interpose_substitution substitutions[] - __attribute__((section("__DATA, __interpose"))) = { - INTERPOSE_FUNCTION(strlen), - INTERPOSE_FUNCTION(memcmp), - INTERPOSE_FUNCTION(memcpy), - INTERPOSE_FUNCTION(memmove), - INTERPOSE_FUNCTION(memset), - INTERPOSE_FUNCTION(strchr), - INTERPOSE_FUNCTION(strcat), - INTERPOSE_FUNCTION(strncat), - INTERPOSE_FUNCTION(strcpy), - INTERPOSE_FUNCTION(strncpy), - INTERPOSE_FUNCTION(pthread_create), - INTERPOSE_FUNCTION(longjmp), -#if ASAN_INTERCEPT__LONGJMP - INTERPOSE_FUNCTION(_longjmp), -#endif -#if ASAN_INTERCEPT_SIGLONGJMP - INTERPOSE_FUNCTION(siglongjmp), -#endif -#if ASAN_INTERCEPT_STRDUP - INTERPOSE_FUNCTION(strdup), -#endif -#if ASAN_INTERCEPT_STRNLEN - INTERPOSE_FUNCTION(strnlen), -#endif -#if ASAN_INTERCEPT_INDEX - INTERPOSE_FUNCTION_2(index, WRAP(strchr)), -#endif - INTERPOSE_FUNCTION(strcmp), - INTERPOSE_FUNCTION(strncmp), -#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP - INTERPOSE_FUNCTION(strcasecmp), - INTERPOSE_FUNCTION(strncasecmp), -#endif - INTERPOSE_FUNCTION(atoi), - INTERPOSE_FUNCTION(atol), - INTERPOSE_FUNCTION(strtol), -#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL - INTERPOSE_FUNCTION(atoll), - INTERPOSE_FUNCTION(strtoll), -#endif -#if ASAN_INTERCEPT_MLOCKX - INTERPOSE_FUNCTION(mlock), - INTERPOSE_FUNCTION(munlock), - INTERPOSE_FUNCTION(mlockall), - INTERPOSE_FUNCTION(munlockall), -#endif - INTERPOSE_FUNCTION(dispatch_async_f), - INTERPOSE_FUNCTION(dispatch_sync_f), - INTERPOSE_FUNCTION(dispatch_after_f), - INTERPOSE_FUNCTION(dispatch_barrier_async_f), - INTERPOSE_FUNCTION(dispatch_group_async_f), -#ifndef MISSING_BLOCKS_SUPPORT - INTERPOSE_FUNCTION(dispatch_group_async), - INTERPOSE_FUNCTION(dispatch_async), - INTERPOSE_FUNCTION(dispatch_after), - INTERPOSE_FUNCTION(dispatch_source_set_event_handler), - INTERPOSE_FUNCTION(dispatch_source_set_cancel_handler), -#endif - INTERPOSE_FUNCTION(signal), - INTERPOSE_FUNCTION(sigaction), - - INTERPOSE_FUNCTION(malloc_create_zone), - INTERPOSE_FUNCTION(malloc_default_zone), - INTERPOSE_FUNCTION(malloc_default_purgeable_zone), - INTERPOSE_FUNCTION(malloc_make_purgeable), - INTERPOSE_FUNCTION(malloc_make_nonpurgeable), - INTERPOSE_FUNCTION(malloc_set_zone_name), - INTERPOSE_FUNCTION(malloc), - INTERPOSE_FUNCTION(free), - INTERPOSE_FUNCTION(realloc), - INTERPOSE_FUNCTION(calloc), - INTERPOSE_FUNCTION(valloc), - INTERPOSE_FUNCTION(malloc_good_size), - INTERPOSE_FUNCTION(posix_memalign), -}; - -} // namespace __asan - -#endif // __APPLE__ diff --git a/libsanitizer/include/sanitizer/asan_interface.h b/libsanitizer/include/sanitizer/asan_interface.h index 18696a681ed..0016339e486 100644 --- a/libsanitizer/include/sanitizer/asan_interface.h +++ b/libsanitizer/include/sanitizer/asan_interface.h @@ -35,8 +35,8 @@ extern "C" { // (un)poison memory in the same memory region simultaneously. void __asan_unpoison_memory_region(void const volatile *addr, size_t size); - // User code should use macro instead of functions. -#if __has_feature(address_sanitizer) +// User code should use macros instead of functions. +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) #define ASAN_POISON_MEMORY_REGION(addr, size) \ __asan_poison_memory_region((addr), (size)) #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h b/libsanitizer/include/sanitizer/common_interface_defs.h index b61b8a1a636..c218b5b5654 100644 --- a/libsanitizer/include/sanitizer/common_interface_defs.h +++ b/libsanitizer/include/sanitizer/common_interface_defs.h @@ -14,6 +14,11 @@ #include #include +// GCC does not understand __has_feature. +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am index 79585e48ed2..c53a3c6bfc5 100644 --- a/libsanitizer/sanitizer_common/Makefile.am +++ b/libsanitizer/sanitizer_common/Makefile.am @@ -17,6 +17,7 @@ sanitizer_common_files = \ sanitizer_libc.cc \ sanitizer_linux.cc \ sanitizer_mac.cc \ + sanitizer_platform_limits_posix.cc \ sanitizer_posix.cc \ sanitizer_printf.cc \ sanitizer_stackdepot.cc \ diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in index 7876acdf4d0..8e292432765 100644 --- a/libsanitizer/sanitizer_common/Makefile.in +++ b/libsanitizer/sanitizer_common/Makefile.in @@ -57,11 +57,12 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) libsanitizer_common_la_LIBADD = am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \ sanitizer_flags.lo sanitizer_libc.lo sanitizer_linux.lo \ - sanitizer_mac.lo sanitizer_posix.lo sanitizer_printf.lo \ - sanitizer_stackdepot.lo sanitizer_stacktrace.lo \ - sanitizer_symbolizer.lo sanitizer_symbolizer_itanium.lo \ - sanitizer_symbolizer_linux.lo sanitizer_symbolizer_mac.lo \ - sanitizer_symbolizer_win.lo sanitizer_win.lo + sanitizer_mac.lo sanitizer_platform_limits_posix.lo \ + sanitizer_posix.lo sanitizer_printf.lo sanitizer_stackdepot.lo \ + sanitizer_stacktrace.lo sanitizer_symbolizer.lo \ + sanitizer_symbolizer_itanium.lo sanitizer_symbolizer_linux.lo \ + sanitizer_symbolizer_mac.lo sanitizer_symbolizer_win.lo \ + sanitizer_win.lo am_libsanitizer_common_la_OBJECTS = $(am__objects_1) libsanitizer_common_la_OBJECTS = $(am_libsanitizer_common_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ @@ -230,6 +231,7 @@ sanitizer_common_files = \ sanitizer_libc.cc \ sanitizer_linux.cc \ sanitizer_mac.cc \ + sanitizer_platform_limits_posix.cc \ sanitizer_posix.cc \ sanitizer_printf.cc \ sanitizer_stackdepot.cc \ @@ -340,6 +342,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_libc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_mac.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_platform_limits_posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_printf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stackdepot.Plo@am__quote@ diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cc b/libsanitizer/sanitizer_common/sanitizer_common.cc index 4447c346eba..f8d2d0e3fe5 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common.cc +++ b/libsanitizer/sanitizer_common/sanitizer_common.cc @@ -43,7 +43,7 @@ void NORETURN Die() { if (DieCallback) { DieCallback(); } - Exit(1); + internal__exit(1); } static CheckFailedCallbackType CheckFailedCallback; diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h index 109966ba360..302dc742769 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common.h +++ b/libsanitizer/sanitizer_common/sanitizer_common.h @@ -124,6 +124,7 @@ void DumpProcessMap(); bool FileExists(const char *filename); const char *GetEnv(const char *name); const char *GetPwd(); +u32 GetUid(); void ReExec(); bool StackSizeIsUnlimited(); void SetStackSizeLimitInBytes(uptr limit); @@ -137,7 +138,6 @@ void SortArray(uptr *array, uptr size); // Exit void NORETURN Abort(); -void NORETURN Exit(int exitcode); void NORETURN Die(); void NORETURN SANITIZER_INTERFACE_ATTRIBUTE CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc index 4ba7b8fee9f..af27603ebdd 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc @@ -124,8 +124,8 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count, #endif #if SANITIZER_INTERCEPT_PRCTL -INTERCEPTOR(int, prctl, int option, unsigned long arg2, - unsigned long arg3, // NOLINT +INTERCEPTOR(int, prctl, int option, + unsigned long arg2, unsigned long arg3, // NOLINT unsigned long arg4, unsigned long arg5) { // NOLINT void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5); @@ -144,6 +144,100 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, #define INIT_PRCTL #endif // SANITIZER_INTERCEPT_PRCTL +#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS +INTERCEPTOR(void *, localtime, unsigned long *timep) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep); + void *res = REAL(localtime)(timep); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result); + void *res = REAL(localtime_r)(timep, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(void *, gmtime, unsigned long *timep) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep); + void *res = REAL(gmtime)(timep); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result); + void *res = REAL(gmtime_r)(timep, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(char *, ctime, unsigned long *timep) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep); + char *res = REAL(ctime)(timep); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result); + char *res = REAL(ctime_r)(timep, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +INTERCEPTOR(char *, asctime, void *tm) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm); + char *res = REAL(asctime)(tm); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +INTERCEPTOR(char *, asctime_r, void *tm, char *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result); + char *res = REAL(asctime_r)(tm, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +#define INIT_LOCALTIME_AND_FRIENDS \ + INTERCEPT_FUNCTION(localtime); \ + INTERCEPT_FUNCTION(localtime_r); \ + INTERCEPT_FUNCTION(gmtime); \ + INTERCEPT_FUNCTION(gmtime_r); \ + INTERCEPT_FUNCTION(ctime); \ + INTERCEPT_FUNCTION(ctime_r); \ + INTERCEPT_FUNCTION(asctime); \ + INTERCEPT_FUNCTION(asctime_r); +#else +#define INIT_LOCALTIME_AND_FRIENDS +#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS + #if SANITIZER_INTERCEPT_SCANF #include "sanitizer_common_interceptors_scanf.inc" @@ -170,6 +264,7 @@ VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap) INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap) VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap) +#if SANITIZER_INTERCEPT_ISOC99_SCANF INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap) VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap) @@ -179,6 +274,7 @@ VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap) INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap) VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap) +#endif // SANITIZER_INTERCEPT_ISOC99_SCANF #define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \ { \ @@ -200,6 +296,7 @@ SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format) INTERCEPTOR(int, sscanf, const char *str, const char *format, ...) SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format) +#if SANITIZER_INTERCEPT_ISOC99_SCANF INTERCEPTOR(int, __isoc99_scanf, const char *format, ...) SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format) @@ -208,6 +305,7 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format) INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...) SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) +#endif #define INIT_SCANF \ INTERCEPT_FUNCTION(scanf); \ @@ -235,4 +333,5 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) INIT_WRITE; \ INIT_PWRITE; \ INIT_PWRITE64; \ + INIT_LOCALTIME_AND_FRIENDS; \ INIT_SCANF; diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.cc b/libsanitizer/sanitizer_common/sanitizer_flags.cc index 837738ceb81..2152c7bdff4 100644 --- a/libsanitizer/sanitizer_common/sanitizer_flags.cc +++ b/libsanitizer/sanitizer_common/sanitizer_flags.cc @@ -36,7 +36,8 @@ static bool GetFlagValue(const char *env, const char *name, pos += 1; end = internal_strchr(pos, '\''); } else { - end = internal_strchr(pos, ' '); + // Read until the next space or colon. + end = pos + internal_strcspn(pos, " :"); } if (end == 0) end = pos + internal_strlen(pos); diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h index 1a25b70c23e..577c9a9c17f 100644 --- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h +++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h @@ -29,7 +29,7 @@ # define SANITIZER_SUPPORTS_WEAK_HOOKS 0 #endif -// __has_feature +// GCC does not understand __has_feature #if !defined(__has_feature) # define __has_feature(x) 0 #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h b/libsanitizer/sanitizer_common/sanitizer_libc.h index 7a9774406fa..16239413356 100644 --- a/libsanitizer/sanitizer_common/sanitizer_libc.h +++ b/libsanitizer/sanitizer_common/sanitizer_libc.h @@ -43,6 +43,7 @@ char *internal_strrchr(const char *s, int c); char *internal_strstr(const char *haystack, const char *needle); // Works only for base=10 and doesn't set errno. s64 internal_simple_strtoll(const char *nptr, char **endptr, int base); +int internal_snprintf(char *buffer, uptr length, const char *format, ...); // Return true if all bytes in [mem, mem+size) are zero. // Optimized for the case when the result is true. @@ -68,14 +69,15 @@ fd_t internal_open(const char *filename, int flags, u32 mode); uptr internal_read(fd_t fd, void *buf, uptr count); uptr internal_write(fd_t fd, const void *buf, uptr count); + +// OS uptr internal_filesize(fd_t fd); // -1 on error. int internal_stat(const char *path, void *buf); int internal_lstat(const char *path, void *buf); int internal_fstat(fd_t fd, void *buf); - int internal_dup2(int oldfd, int newfd); uptr internal_readlink(const char *path, char *buf, uptr bufsize); -int internal_snprintf(char *buffer, uptr length, const char *format, ...); +void NORETURN internal__exit(int exitcode); // Threading int internal_sched_yield(); diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc index 3d3aa0b00bd..06e5a0a6441 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux.cc +++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc @@ -138,6 +138,11 @@ int internal_sched_yield() { return syscall(__NR_sched_yield); } +void internal__exit(int exitcode) { + syscall(__NR_exit_group, exitcode); + Die(); // Unreachable. +} + // ----------------- sanitizer_common.h bool FileExists(const char *filename) { #if SANITIZER_LINUX_USES_64BIT_SYSCALLS @@ -232,6 +237,21 @@ const char *GetEnv(const char *name) { return 0; // Not found. } +#ifdef __GLIBC__ + +extern "C" { + extern void *__libc_stack_end; +} + +static void GetArgsAndEnv(char ***argv, char ***envp) { + uptr *stack_end = (uptr *)__libc_stack_end; + int argc = *stack_end; + *argv = (char**)(stack_end + 1); + *envp = (char**)(stack_end + argc + 2); +} + +#else // __GLIBC__ + static void ReadNullSepFileToArray(const char *path, char ***arr, int arr_size) { char *buff; @@ -251,12 +271,20 @@ static void ReadNullSepFileToArray(const char *path, char ***arr, (*arr)[count] = 0; } +static void GetArgsAndEnv(char ***argv, char ***envp) { + static const int kMaxArgv = 2000, kMaxEnvp = 2000; + ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); + ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); +} + +#endif // __GLIBC__ + void ReExec() { - static const int kMaxArgv = 100, kMaxEnvp = 1000; char **argv, **envp; - ReadNullSepFileToArray("/proc/self/cmdline", &argv, kMaxArgv); - ReadNullSepFileToArray("/proc/self/environ", &envp, kMaxEnvp); - execve(argv[0], argv, envp); + GetArgsAndEnv(&argv, &envp); + execve("/proc/self/exe", argv, envp); + Printf("execve failed, errno %d\n", errno); + Die(); } void PrepareForSandboxing() { diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc index 309b5a94005..d7885bb3509 100644 --- a/libsanitizer/sanitizer_common/sanitizer_mac.cc +++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc @@ -104,6 +104,10 @@ int internal_sched_yield() { return sched_yield(); } +void internal__exit(int exitcode) { + _exit(exitcode); +} + // ----------------- sanitizer_common.h bool FileExists(const char *filename) { struct stat st; diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h index 2c60253c533..9b40c0cc523 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h @@ -14,6 +14,7 @@ #if !defined(_WIN32) # define SI_NOT_WINDOWS 1 +# include "sanitizer_platform_limits_posix.h" #else # define SI_NOT_WINDOWS 0 #endif @@ -24,6 +25,12 @@ # define SI_LINUX_NOT_ANDROID 0 #endif +#if defined(__linux__) +# define SI_LINUX 1 +#else +# define SI_LINUX 0 +#endif + # define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS @@ -33,4 +40,7 @@ # define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID # define SANITIZER_INTERCEPT_PRCTL SI_LINUX_NOT_ANDROID +# define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_NOT_WINDOWS + # define SANITIZER_INTERCEPT_SCANF SI_NOT_WINDOWS +# define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc new file mode 100644 index 00000000000..c4be1aa42da --- /dev/null +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -0,0 +1,68 @@ +//===-- sanitizer_platform_limits_posix.cc --------------------------------===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of Sanitizer common code. +// +// Sizes and layouts of platform-specific POSIX data structures. +//===----------------------------------------------------------------------===// + +#if defined(__linux__) || defined(__APPLE__) + +#include "sanitizer_internal_defs.h" +#include "sanitizer_platform_limits_posix.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +#include +#include +#endif // __linux__ + +namespace __sanitizer { + unsigned struct_utsname_sz = sizeof(struct utsname); + unsigned struct_stat_sz = sizeof(struct stat); + unsigned struct_stat64_sz = sizeof(struct stat64); + unsigned struct_rusage_sz = sizeof(struct rusage); + unsigned struct_tm_sz = sizeof(struct tm); + +#if defined(__linux__) + unsigned struct_rlimit_sz = sizeof(struct rlimit); + unsigned struct_dirent_sz = sizeof(struct dirent); + unsigned struct_statfs_sz = sizeof(struct statfs); + unsigned struct_epoll_event_sz = sizeof(struct epoll_event); +#endif // __linux__ + +#if defined(__linux__) && !defined(__ANDROID__) + unsigned struct_rlimit64_sz = sizeof(struct rlimit64); + unsigned struct_statfs64_sz = sizeof(struct statfs64); +#endif // __linux__ && !__ANDROID__ + + void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx) { + return ((struct msghdr *)msg)->msg_iov[idx].iov_base; + } + + uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx) { + return ((struct msghdr *)msg)->msg_iov[idx].iov_len; + } + + uptr __sanitizer_get_msghdr_iovlen(void* msg) { + return ((struct msghdr *)msg)->msg_iovlen; + } + + uptr __sanitizer_get_socklen_t(void* socklen_ptr) { + return *(socklen_t*)socklen_ptr; + } +} // namespace __sanitizer + +#endif // __linux__ || __APPLE__ diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h new file mode 100644 index 00000000000..dd53da94be6 --- /dev/null +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h @@ -0,0 +1,41 @@ +//===-- sanitizer_platform_limits_posix.h ---------------------------------===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of Sanitizer common code. +// +// Sizes and layouts of platform-specific POSIX data structures. +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H +#define SANITIZER_PLATFORM_LIMITS_POSIX_H + +namespace __sanitizer { + extern unsigned struct_utsname_sz; + extern unsigned struct_stat_sz; + extern unsigned struct_stat64_sz; + extern unsigned struct_rusage_sz; + extern unsigned struct_tm_sz; + +#if defined(__linux__) + extern unsigned struct_rlimit_sz; + extern unsigned struct_dirent_sz; + extern unsigned struct_statfs_sz; + extern unsigned struct_epoll_event_sz; +#endif // __linux__ + +#if defined(__linux__) && !defined(__ANDROID__) + extern unsigned struct_rlimit64_sz; + extern unsigned struct_statfs64_sz; +#endif // __linux__ && !__ANDROID__ + + void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx); + uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx); + uptr __sanitizer_get_msghdr_iovlen(void* msg); + uptr __sanitizer_get_socklen_t(void* socklen_ptr); +} // namespace __sanitizer + +#endif diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cc b/libsanitizer/sanitizer_common/sanitizer_posix.cc index 48c5ebaef3e..1c6ff0a2ebb 100644 --- a/libsanitizer/sanitizer_common/sanitizer_posix.cc +++ b/libsanitizer/sanitizer_common/sanitizer_posix.cc @@ -42,6 +42,10 @@ int GetPid() { return getpid(); } +u32 GetUid() { + return getuid(); +} + uptr GetThreadSelf() { return (uptr)pthread_self(); } @@ -203,10 +207,6 @@ void SleepForMillis(int millis) { usleep(millis * 1000); } -void Exit(int exitcode) { - _exit(exitcode); -} - void Abort() { abort(); } diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc index 259da0082e3..e14ea447264 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc @@ -129,8 +129,9 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp, CHECK(size == 0 && trace[0] == pc); size = 1; uhwptr *frame = (uhwptr *)bp; - uhwptr *prev_frame = frame; - while (frame >= prev_frame && + uhwptr *prev_frame = frame - 1; + // Avoid infinite loop when frame == frame[0] by using frame > prev_frame. + while (frame > prev_frame && frame < (uhwptr *)stack_top - 2 && frame > (uhwptr *)stack_bottom && size < max_size) { diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc index bb1c40f9613..01f1e4588da 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc @@ -97,7 +97,7 @@ bool StartSymbolizerSubprocess(const char *path_to_symbolizer, for (int fd = getdtablesize(); fd > 2; fd--) internal_close(fd); execl(path_to_symbolizer, path_to_symbolizer, (char*)0); - Exit(1); + internal__exit(1); } // Continue execution in parent process. diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc index 3d5cde11cf8..695265594b3 100644 --- a/libsanitizer/sanitizer_common/sanitizer_win.cc +++ b/libsanitizer/sanitizer_common/sanitizer_win.cc @@ -129,6 +129,10 @@ const char *GetPwd() { UNIMPLEMENTED(); } +u32 GetUid() { + UNIMPLEMENTED(); +} + void DumpProcessMap() { UNIMPLEMENTED(); } @@ -161,10 +165,6 @@ void SleepForMillis(int millis) { Sleep(millis); } -void Exit(int exitcode) { - _exit(exitcode); -} - void Abort() { abort(); _exit(-1); // abort is not NORETURN on Windows. @@ -251,6 +251,10 @@ int internal_sched_yield() { return 0; } +void internal__exit(int exitcode) { + _exit(exitcode); +} + // ---------------------- BlockingMutex ---------------- {{{1 const uptr LOCK_UNINITIALIZED = 0; const uptr LOCK_READY = (uptr)-1; diff --git a/libsanitizer/tsan/tsan_platform_linux.cc b/libsanitizer/tsan/tsan_platform_linux.cc index def91559d5e..f7b05f2bf8f 100644 --- a/libsanitizer/tsan/tsan_platform_linux.cc +++ b/libsanitizer/tsan/tsan_platform_linux.cc @@ -241,7 +241,7 @@ const char *InitializePlatform() { g_tls_size = (uptr)InitTlsSize(); InitDataSeg(); #endif - return getenv(kTsanOptionsEnv); + return GetEnv(kTsanOptionsEnv); } void FinalizePlatform() { diff --git a/libsanitizer/tsan/tsan_platform_mac.cc b/libsanitizer/tsan/tsan_platform_mac.cc index 808d99c0207..b247468c829 100644 --- a/libsanitizer/tsan/tsan_platform_mac.cc +++ b/libsanitizer/tsan/tsan_platform_mac.cc @@ -80,7 +80,7 @@ const char *InitializePlatform() { setrlimit(RLIMIT_CORE, (rlimit*)&lim); } - return getenv(kTsanOptionsEnv); + return GetEnv(kTsanOptionsEnv); } void FinalizePlatform() { diff --git a/libsanitizer/tsan/tsan_platform_windows.cc b/libsanitizer/tsan/tsan_platform_windows.cc index 74b9020d077..376dc08688b 100644 --- a/libsanitizer/tsan/tsan_platform_windows.cc +++ b/libsanitizer/tsan/tsan_platform_windows.cc @@ -32,7 +32,7 @@ void FlushShadowMemory() { } const char *InitializePlatform() { - return getenv(kTsanOptionsEnv); + return GetEnv(kTsanOptionsEnv); } void FinalizePlatform() { diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h index 717f4599705..e939921049a 100644 --- a/libsanitizer/tsan/tsan_rtl.h +++ b/libsanitizer/tsan/tsan_rtl.h @@ -590,6 +590,8 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr, u64 *shadow_mem, Shadow cur); void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size, bool is_write); +void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr, + uptr size, uptr step, bool is_write); const int kSizeLog1 = 0; const int kSizeLog2 = 1; diff --git a/libsanitizer/tsan/tsan_rtl_thread.cc b/libsanitizer/tsan/tsan_rtl_thread.cc index 9c89417ad68..e30916dc627 100644 --- a/libsanitizer/tsan/tsan_rtl_thread.cc +++ b/libsanitizer/tsan/tsan_rtl_thread.cc @@ -420,4 +420,26 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, shadow_mem, cur); } } + +void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr, + uptr size, uptr step, bool is_write) { + if (size == 0) + return; + FastState fast_state = thr->fast_state; + if (fast_state.GetIgnoreBit()) + return; + StatInc(thr, StatMopRange); + fast_state.IncrementEpoch(); + thr->fast_state = fast_state; + TraceAddEvent(thr, fast_state, EventTypeMop, pc); + + for (uptr addr_end = addr + size; addr < addr_end; addr += step) { + u64 *shadow_mem = (u64*)MemToShadow(addr); + Shadow cur(fast_state); + cur.SetWrite(is_write); + cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kSizeLog1); + MemoryAccessImpl(thr, addr, kSizeLog1, is_write, false, + shadow_mem, cur); + } +} } // namespace __tsan diff --git a/libsanitizer/tsan/tsan_stat.cc b/libsanitizer/tsan/tsan_stat.cc index cd88d2df928..fbec4225d9c 100644 --- a/libsanitizer/tsan/tsan_stat.cc +++ b/libsanitizer/tsan/tsan_stat.cc @@ -263,6 +263,14 @@ void StatOutput(u64 *stat) { name[StatInt___isoc99_fscanf] = " fscanf "; name[StatInt_on_exit] = " on_exit "; name[StatInt___cxa_atexit] = " __cxa_atexit "; + name[StatInt_localtime] = " localtime "; + name[StatInt_localtime_r] = " localtime_r "; + name[StatInt_gmtime] = " gmtime "; + name[StatInt_gmtime_r] = " gmtime_r "; + name[StatInt_ctime] = " ctime "; + name[StatInt_ctime_r] = " ctime_r "; + name[StatInt_asctime] = " asctime "; + name[StatInt_asctime_r] = " asctime_r "; name[StatAnnotation] = "Dynamic annotations "; name[StatAnnotateHappensBefore] = " HappensBefore "; diff --git a/libsanitizer/tsan/tsan_stat.h b/libsanitizer/tsan/tsan_stat.h index 1d6c54cdd4f..8b08a024be2 100644 --- a/libsanitizer/tsan/tsan_stat.h +++ b/libsanitizer/tsan/tsan_stat.h @@ -262,6 +262,14 @@ enum StatType { StatInt___isoc99_fscanf, StatInt_on_exit, StatInt___cxa_atexit, + StatInt_localtime, + StatInt_localtime_r, + StatInt_gmtime, + StatInt_gmtime_r, + StatInt_ctime, + StatInt_ctime_r, + StatInt_asctime, + StatInt_asctime_r, // Dynamic annotations. StatAnnotation, diff --git a/libsanitizer/tsan/tsan_suppressions.cc b/libsanitizer/tsan/tsan_suppressions.cc index b6c54db2c51..8ee8de7c278 100644 --- a/libsanitizer/tsan/tsan_suppressions.cc +++ b/libsanitizer/tsan/tsan_suppressions.cc @@ -138,7 +138,7 @@ void InitializeSuppressions() { g_suppressions = SuppressionParse(0, supp); #ifndef TSAN_GO supp = __tsan_default_suppressions(); - g_suppressions = SuppressionParse(0, supp); + g_suppressions = SuppressionParse(g_suppressions, supp); #endif } -- 2.11.4.GIT