Commit 7df59255 by Kostya Serebryany Committed by Kostya Serebryany

libsanitizer merge from upstream r175733

From-SVN: r196201
parent 22deefcb
2013-02-23 Kostya Serebryany <kcc@google.com>
* config/i386/i386.c (ix86_asan_shadow_offset): Use 0x7fff8000 as
asan_shadow_offset on x86_64 linux.
2013-02-21 Richard Biener <rguenther@suse.de> 2013-02-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/56415 PR tree-optimization/56415
......
...@@ -5436,7 +5436,8 @@ ix86_legitimate_combined_insn (rtx insn) ...@@ -5436,7 +5436,8 @@ ix86_legitimate_combined_insn (rtx insn)
static unsigned HOST_WIDE_INT static unsigned HOST_WIDE_INT
ix86_asan_shadow_offset (void) 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); : (HOST_WIDE_INT_1 << 29);
} }
2013-02-21 Kostya Serebryany <kcc@google.com>
* 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 <hongjiu.lu@intel.com> 2013-02-14 H.J. Lu <hongjiu.lu@intel.com>
PR bootstrap/56327 PR bootstrap/56327
......
175049 175733
The first line of this file holds the svn revision number of the The first line of this file holds the svn revision number of the
last merge done from the master library sources. last merge done from the master library sources.
...@@ -15,11 +15,13 @@ ...@@ -15,11 +15,13 @@
#include "sanitizer_common/sanitizer_internal_defs.h" #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. // 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(). // __asan_default_options().
// 3) overriden from env variable ASAN_OPTIONS. // 4) overriden from env variable ASAN_OPTIONS.
namespace __asan { namespace __asan {
......
...@@ -77,9 +77,36 @@ using __sanitizer::uptr; ...@@ -77,9 +77,36 @@ using __sanitizer::uptr;
# define ASAN_INTERCEPT___CXA_THROW 0 # define ASAN_INTERCEPT___CXA_THROW 0
#endif #endif
#define INTERPOSE_FUNCTION(function) \
{ reinterpret_cast<const uptr>(WRAP(function)), \
reinterpret_cast<const uptr>(function) }
#define INTERPOSE_FUNCTION_2(function, wrapper) \
{ reinterpret_cast<const uptr>(wrapper), \
reinterpret_cast<const uptr>(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, ...) \ #define DECLARE_FUNCTION_AND_WRAPPER(ret_type, func, ...) \
ret_type func(__VA_ARGS__); \ 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 // Use extern declarations of intercepted functions on Mac and Windows
// to avoid including system headers. // to avoid including system headers.
...@@ -139,7 +166,8 @@ DECLARE_FUNCTION_AND_WRAPPER(char*, strdup, const char *s); ...@@ -139,7 +166,8 @@ DECLARE_FUNCTION_AND_WRAPPER(char*, strdup, const char *s);
DECLARE_FUNCTION_AND_WRAPPER(uptr, strnlen, const char *s, uptr maxlen); DECLARE_FUNCTION_AND_WRAPPER(uptr, strnlen, const char *s, uptr maxlen);
# endif # endif
# if ASAN_INTERCEPT_INDEX # 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 # endif
// stdlib.h // stdlib.h
...@@ -193,6 +221,20 @@ DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create, ...@@ -193,6 +221,20 @@ DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create,
void *(*start_routine)(void*), void *arg); void *(*start_routine)(void*), void *arg);
# endif # 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 // stdio.h
# if SANITIZER_INTERCEPT_SCANF # if SANITIZER_INTERCEPT_SCANF
DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap); DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap);
...@@ -205,17 +247,6 @@ DECLARE_FUNCTION_AND_WRAPPER(int, fscanf, ...@@ -205,17 +247,6 @@ DECLARE_FUNCTION_AND_WRAPPER(int, fscanf,
void* stream, const char *format, ...); void* stream, const char *format, ...);
DECLARE_FUNCTION_AND_WRAPPER(int, sscanf, // NOLINT DECLARE_FUNCTION_AND_WRAPPER(int, sscanf, // NOLINT
const char *str, const char *format, ...); 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 # endif
# if defined(__APPLE__) # if defined(__APPLE__)
...@@ -278,9 +309,11 @@ DECLARE_FUNCTION_AND_WRAPPER(void *, valloc, size_t size); ...@@ -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(size_t, malloc_good_size, size_t size);
DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign, DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign,
void **memptr, size_t alignment, size_t size); 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_prepare, void);
DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void); DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void);
DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void); DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void);
#endif
......
...@@ -24,6 +24,16 @@ ...@@ -24,6 +24,16 @@
namespace __asan { 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, // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
// and ASAN_WRITE_RANGE as macro instead of function so // and ASAN_WRITE_RANGE as macro instead of function so
// that no extra frames are created, and stack trace contains // that no extra frames are created, and stack trace contains
...@@ -32,7 +42,8 @@ namespace __asan { ...@@ -32,7 +42,8 @@ namespace __asan {
#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
uptr __offset = (uptr)(offset); \ uptr __offset = (uptr)(offset); \
uptr __size = (uptr)(size); \ 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; \ GET_CURRENT_PC_BP_SP; \
__asan_report_error(pc, bp, sp, __offset, isWrite, __size); \ __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \
} \ } \
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#define ASAN_POSIX (ASAN_LINUX || ASAN_MAC) #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" # error "The AddressSanitizer run-time should not be"
" instrumented by AddressSanitizer" " instrumented by AddressSanitizer"
#endif #endif
...@@ -89,6 +89,10 @@ ...@@ -89,6 +89,10 @@
# endif # endif
#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 // All internal functions in asan reside inside the __asan namespace
// to avoid namespace collisions with the user programs. // to avoid namespace collisions with the user programs.
// Seperate namespace also makes it simpler to distinguish the asan run-time // Seperate namespace also makes it simpler to distinguish the asan run-time
......
...@@ -86,6 +86,39 @@ extern "C" ...@@ -86,6 +86,39 @@ extern "C"
void __asan_init(); void __asan_init();
static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; 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<char*>(name_value);
} else {
// Shift the subsequent pointers back.
char **del = environ;
do {
del[0] = del[1];
} while (*del++);
}
}
}
environ++;
}
}
void MaybeReexec() { void MaybeReexec() {
if (!flags()->allow_reexec) return; if (!flags()->allow_reexec) return;
...@@ -94,7 +127,11 @@ void MaybeReexec() { ...@@ -94,7 +127,11 @@ void MaybeReexec() {
// ourselves. // ourselves.
Dl_info info; Dl_info info;
CHECK(dladdr((void*)((uptr)__asan_init), &info)); CHECK(dladdr((void*)((uptr)__asan_init), &info));
const char *dyld_insert_libraries = GetEnv(kDyldInsertLibraries); char *dyld_insert_libraries =
const_cast<char*>(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 || if (!dyld_insert_libraries ||
!REAL(strstr)(dyld_insert_libraries, info.dli_fname)) { !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) {
// DYLD_INSERT_LIBRARIES is not set or does not contain the runtime // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
...@@ -102,16 +139,79 @@ void MaybeReexec() { ...@@ -102,16 +139,79 @@ void MaybeReexec() {
char program_name[1024]; char program_name[1024];
uint32_t buf_size = sizeof(program_name); uint32_t buf_size = sizeof(program_name);
_NSGetExecutablePath(program_name, &buf_size); _NSGetExecutablePath(program_name, &buf_size);
char *new_env = const_cast<char*>(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 // Ok to use setenv() since the wrappers don't depend on the value of
// asan_inited. // 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); setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
}
if (flags()->verbosity >= 1) { if (flags()->verbosity >= 1) {
Report("exec()-ing the program with\n"); 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("to enable ASan wrappers.\n");
Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n"); Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n");
} }
execv(program_name, *_NSGetArgv()); 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);
}
} }
} }
......
//===-- asan_mapping.h ------------------------------------------*- C++ -*-===// //===-- asan_mapping.h ------------------------------------------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source // This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details. // License. See LICENSE.TXT for details.
// //
...@@ -18,6 +16,37 @@ ...@@ -18,6 +16,37 @@
// The full explanation of the memory mapping could be found here: // The full explanation of the memory mapping could be found here:
// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm // 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 #if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1
extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale; extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale;
...@@ -36,7 +65,11 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; ...@@ -36,7 +65,11 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset;
# if defined(__powerpc64__) # if defined(__powerpc64__)
# define SHADOW_OFFSET (1ULL << 41) # define SHADOW_OFFSET (1ULL << 41)
# else # else
# if ASAN_MAC
# define SHADOW_OFFSET (1ULL << 44) # define SHADOW_OFFSET (1ULL << 44)
# else
# define SHADOW_OFFSET 0x7fff8000ULL
# endif
# endif # endif
# endif # endif
# endif # endif
...@@ -57,49 +90,105 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; ...@@ -57,49 +90,105 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset;
#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) #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. // With the zero shadow base we can not actually map pages starting from 0.
// This constant is somewhat arbitrary. // This constant is somewhat arbitrary.
#define kZeroBaseShadowStart (1 << 18) #define kZeroBaseShadowStart (1 << 18)
#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \
: kZeroBaseShadowStart) : 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 { 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 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) { static inline bool AddrIsInLowMem(uptr a) {
PROFILE_ASAN_MAPPING();
return a < kLowMemEnd; return a < kLowMemEnd;
} }
static inline bool AddrIsInLowShadow(uptr a) { static inline bool AddrIsInLowShadow(uptr a) {
PROFILE_ASAN_MAPPING();
return a >= kLowShadowBeg && a <= kLowShadowEnd; return a >= kLowShadowBeg && a <= kLowShadowEnd;
} }
static inline bool AddrIsInHighMem(uptr a) { static inline bool AddrIsInHighMem(uptr a) {
PROFILE_ASAN_MAPPING();
return a >= kHighMemBeg && a <= kHighMemEnd; 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) { 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) { static inline uptr MemToShadow(uptr p) {
PROFILE_ASAN_MAPPING();
CHECK(AddrIsInMem(p)); CHECK(AddrIsInMem(p));
return MEM_TO_SHADOW(p); return MEM_TO_SHADOW(p);
} }
static inline bool AddrIsInHighShadow(uptr a) { static inline bool AddrIsInHighShadow(uptr a) {
PROFILE_ASAN_MAPPING();
return a >= kHighShadowBeg && a <= kHighMemEnd; 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) { 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) { 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 zero-based shadow mode we treat addresses near zero as addresses
// in shadow gap as well. // in shadow gap as well.
if (SHADOW_OFFSET == 0) if (SHADOW_OFFSET == 0)
...@@ -108,12 +197,14 @@ static inline bool AddrIsInShadowGap(uptr a) { ...@@ -108,12 +197,14 @@ static inline bool AddrIsInShadowGap(uptr a) {
} }
static inline bool AddrIsAlignedByGranularity(uptr a) { static inline bool AddrIsAlignedByGranularity(uptr a) {
PROFILE_ASAN_MAPPING();
return (a & (SHADOW_GRANULARITY - 1)) == 0; return (a & (SHADOW_GRANULARITY - 1)) == 0;
} }
static inline bool AddressIsPoisoned(uptr a) { static inline bool AddressIsPoisoned(uptr a) {
PROFILE_ASAN_MAPPING();
const uptr kAccessSize = 1; const uptr kAccessSize = 1;
u8 *shadow_address = (u8*)MemToShadow(a); u8 *shadow_address = (u8*)MEM_TO_SHADOW(a);
s8 shadow_value = *shadow_address; s8 shadow_value = *shadow_address;
if (shadow_value) { if (shadow_value) {
u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1)) u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1))
...@@ -123,6 +214,9 @@ static inline bool AddressIsPoisoned(uptr a) { ...@@ -123,6 +214,9 @@ static inline bool AddressIsPoisoned(uptr a) {
return false; return false;
} }
// Must be after all calls to PROFILE_ASAN_MAPPING().
static const uptr kAsanMappingProfileSize = __LINE__;
} // namespace __asan } // namespace __asan
#endif // ASAN_MAPPING_H #endif // ASAN_MAPPING_H
...@@ -433,9 +433,9 @@ class ScopedInErrorReport { ...@@ -433,9 +433,9 @@ class ScopedInErrorReport {
// an error report will finish doing it. // an error report will finish doing it.
SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); 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. // Die() to bypass any additional checks.
Exit(flags()->exitcode); internal__exit(flags()->exitcode);
} }
ASAN_ON_ERROR(); ASAN_ON_ERROR();
reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
......
//===-- 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<const uptr>(WRAP(function)), \
reinterpret_cast<const uptr>(function) }
#define INTERPOSE_FUNCTION_2(function, wrapper) \
{ reinterpret_cast<const uptr>(wrapper), \
reinterpret_cast<const uptr>(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__
...@@ -35,8 +35,8 @@ extern "C" { ...@@ -35,8 +35,8 @@ extern "C" {
// (un)poison memory in the same memory region simultaneously. // (un)poison memory in the same memory region simultaneously.
void __asan_unpoison_memory_region(void const volatile *addr, size_t size); void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
// User code should use macro instead of functions. // User code should use macros instead of functions.
#if __has_feature(address_sanitizer) #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#define ASAN_POISON_MEMORY_REGION(addr, size) \ #define ASAN_POISON_MEMORY_REGION(addr, size) \
__asan_poison_memory_region((addr), (size)) __asan_poison_memory_region((addr), (size))
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
......
...@@ -14,6 +14,11 @@ ...@@ -14,6 +14,11 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
// GCC does not understand __has_feature.
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
......
...@@ -17,6 +17,7 @@ sanitizer_common_files = \ ...@@ -17,6 +17,7 @@ sanitizer_common_files = \
sanitizer_libc.cc \ sanitizer_libc.cc \
sanitizer_linux.cc \ sanitizer_linux.cc \
sanitizer_mac.cc \ sanitizer_mac.cc \
sanitizer_platform_limits_posix.cc \
sanitizer_posix.cc \ sanitizer_posix.cc \
sanitizer_printf.cc \ sanitizer_printf.cc \
sanitizer_stackdepot.cc \ sanitizer_stackdepot.cc \
......
...@@ -57,11 +57,12 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) ...@@ -57,11 +57,12 @@ LTLIBRARIES = $(noinst_LTLIBRARIES)
libsanitizer_common_la_LIBADD = libsanitizer_common_la_LIBADD =
am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \ am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \
sanitizer_flags.lo sanitizer_libc.lo sanitizer_linux.lo \ sanitizer_flags.lo sanitizer_libc.lo sanitizer_linux.lo \
sanitizer_mac.lo sanitizer_posix.lo sanitizer_printf.lo \ sanitizer_mac.lo sanitizer_platform_limits_posix.lo \
sanitizer_stackdepot.lo sanitizer_stacktrace.lo \ sanitizer_posix.lo sanitizer_printf.lo sanitizer_stackdepot.lo \
sanitizer_symbolizer.lo sanitizer_symbolizer_itanium.lo \ sanitizer_stacktrace.lo sanitizer_symbolizer.lo \
sanitizer_symbolizer_linux.lo sanitizer_symbolizer_mac.lo \ sanitizer_symbolizer_itanium.lo sanitizer_symbolizer_linux.lo \
sanitizer_symbolizer_win.lo sanitizer_win.lo sanitizer_symbolizer_mac.lo sanitizer_symbolizer_win.lo \
sanitizer_win.lo
am_libsanitizer_common_la_OBJECTS = $(am__objects_1) am_libsanitizer_common_la_OBJECTS = $(am__objects_1)
libsanitizer_common_la_OBJECTS = $(am_libsanitizer_common_la_OBJECTS) libsanitizer_common_la_OBJECTS = $(am_libsanitizer_common_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ DEFAULT_INCLUDES = -I.@am__isrc@
...@@ -230,6 +231,7 @@ sanitizer_common_files = \ ...@@ -230,6 +231,7 @@ sanitizer_common_files = \
sanitizer_libc.cc \ sanitizer_libc.cc \
sanitizer_linux.cc \ sanitizer_linux.cc \
sanitizer_mac.cc \ sanitizer_mac.cc \
sanitizer_platform_limits_posix.cc \
sanitizer_posix.cc \ sanitizer_posix.cc \
sanitizer_printf.cc \ sanitizer_printf.cc \
sanitizer_stackdepot.cc \ sanitizer_stackdepot.cc \
...@@ -340,6 +342,7 @@ distclean-compile: ...@@ -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_libc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux.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_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_posix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_printf.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stackdepot.Plo@am__quote@
......
...@@ -43,7 +43,7 @@ void NORETURN Die() { ...@@ -43,7 +43,7 @@ void NORETURN Die() {
if (DieCallback) { if (DieCallback) {
DieCallback(); DieCallback();
} }
Exit(1); internal__exit(1);
} }
static CheckFailedCallbackType CheckFailedCallback; static CheckFailedCallbackType CheckFailedCallback;
......
...@@ -124,6 +124,7 @@ void DumpProcessMap(); ...@@ -124,6 +124,7 @@ void DumpProcessMap();
bool FileExists(const char *filename); bool FileExists(const char *filename);
const char *GetEnv(const char *name); const char *GetEnv(const char *name);
const char *GetPwd(); const char *GetPwd();
u32 GetUid();
void ReExec(); void ReExec();
bool StackSizeIsUnlimited(); bool StackSizeIsUnlimited();
void SetStackSizeLimitInBytes(uptr limit); void SetStackSizeLimitInBytes(uptr limit);
...@@ -137,7 +138,6 @@ void SortArray(uptr *array, uptr size); ...@@ -137,7 +138,6 @@ void SortArray(uptr *array, uptr size);
// Exit // Exit
void NORETURN Abort(); void NORETURN Abort();
void NORETURN Exit(int exitcode);
void NORETURN Die(); void NORETURN Die();
void NORETURN SANITIZER_INTERFACE_ATTRIBUTE void NORETURN SANITIZER_INTERFACE_ATTRIBUTE
CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
......
...@@ -124,8 +124,8 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count, ...@@ -124,8 +124,8 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
#endif #endif
#if SANITIZER_INTERCEPT_PRCTL #if SANITIZER_INTERCEPT_PRCTL
INTERCEPTOR(int, prctl, int option, unsigned long arg2, INTERCEPTOR(int, prctl, int option,
unsigned long arg3, // NOLINT unsigned long arg2, unsigned long arg3, // NOLINT
unsigned long arg4, unsigned long arg5) { // NOLINT unsigned long arg4, unsigned long arg5) { // NOLINT
void *ctx; void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5); COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
...@@ -144,6 +144,100 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, ...@@ -144,6 +144,100 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2,
#define INIT_PRCTL #define INIT_PRCTL
#endif // SANITIZER_INTERCEPT_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 #if SANITIZER_INTERCEPT_SCANF
#include "sanitizer_common_interceptors_scanf.inc" #include "sanitizer_common_interceptors_scanf.inc"
...@@ -170,6 +264,7 @@ VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap) ...@@ -170,6 +264,7 @@ VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap) INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap) VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap) INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap) VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
...@@ -179,6 +274,7 @@ VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, 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) INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap) VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
#endif // SANITIZER_INTERCEPT_ISOC99_SCANF
#define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \ #define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \
{ \ { \
...@@ -200,6 +296,7 @@ SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format) ...@@ -200,6 +296,7 @@ SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
INTERCEPTOR(int, sscanf, const char *str, const char *format, ...) INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format) SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_scanf, const char *format, ...) INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format) SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
...@@ -208,6 +305,7 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format) ...@@ -208,6 +305,7 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...) INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
#endif
#define INIT_SCANF \ #define INIT_SCANF \
INTERCEPT_FUNCTION(scanf); \ INTERCEPT_FUNCTION(scanf); \
...@@ -235,4 +333,5 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) ...@@ -235,4 +333,5 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
INIT_WRITE; \ INIT_WRITE; \
INIT_PWRITE; \ INIT_PWRITE; \
INIT_PWRITE64; \ INIT_PWRITE64; \
INIT_LOCALTIME_AND_FRIENDS; \
INIT_SCANF; INIT_SCANF;
...@@ -36,7 +36,8 @@ static bool GetFlagValue(const char *env, const char *name, ...@@ -36,7 +36,8 @@ static bool GetFlagValue(const char *env, const char *name,
pos += 1; pos += 1;
end = internal_strchr(pos, '\''); end = internal_strchr(pos, '\'');
} else { } else {
end = internal_strchr(pos, ' '); // Read until the next space or colon.
end = pos + internal_strcspn(pos, " :");
} }
if (end == 0) if (end == 0)
end = pos + internal_strlen(pos); end = pos + internal_strlen(pos);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
# define SANITIZER_SUPPORTS_WEAK_HOOKS 0 # define SANITIZER_SUPPORTS_WEAK_HOOKS 0
#endif #endif
// __has_feature // GCC does not understand __has_feature
#if !defined(__has_feature) #if !defined(__has_feature)
# define __has_feature(x) 0 # define __has_feature(x) 0
#endif #endif
......
...@@ -43,6 +43,7 @@ char *internal_strrchr(const char *s, int c); ...@@ -43,6 +43,7 @@ char *internal_strrchr(const char *s, int c);
char *internal_strstr(const char *haystack, const char *needle); char *internal_strstr(const char *haystack, const char *needle);
// Works only for base=10 and doesn't set errno. // Works only for base=10 and doesn't set errno.
s64 internal_simple_strtoll(const char *nptr, char **endptr, int base); 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. // Return true if all bytes in [mem, mem+size) are zero.
// Optimized for the case when the result is true. // Optimized for the case when the result is true.
...@@ -68,14 +69,15 @@ fd_t internal_open(const char *filename, int flags, u32 mode); ...@@ -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_read(fd_t fd, void *buf, uptr count);
uptr internal_write(fd_t fd, const 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. uptr internal_filesize(fd_t fd); // -1 on error.
int internal_stat(const char *path, void *buf); int internal_stat(const char *path, void *buf);
int internal_lstat(const char *path, void *buf); int internal_lstat(const char *path, void *buf);
int internal_fstat(fd_t fd, void *buf); int internal_fstat(fd_t fd, void *buf);
int internal_dup2(int oldfd, int newfd); int internal_dup2(int oldfd, int newfd);
uptr internal_readlink(const char *path, char *buf, uptr bufsize); 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 // Threading
int internal_sched_yield(); int internal_sched_yield();
......
...@@ -138,6 +138,11 @@ int internal_sched_yield() { ...@@ -138,6 +138,11 @@ int internal_sched_yield() {
return syscall(__NR_sched_yield); return syscall(__NR_sched_yield);
} }
void internal__exit(int exitcode) {
syscall(__NR_exit_group, exitcode);
Die(); // Unreachable.
}
// ----------------- sanitizer_common.h // ----------------- sanitizer_common.h
bool FileExists(const char *filename) { bool FileExists(const char *filename) {
#if SANITIZER_LINUX_USES_64BIT_SYSCALLS #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
...@@ -232,6 +237,21 @@ const char *GetEnv(const char *name) { ...@@ -232,6 +237,21 @@ const char *GetEnv(const char *name) {
return 0; // Not found. 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, static void ReadNullSepFileToArray(const char *path, char ***arr,
int arr_size) { int arr_size) {
char *buff; char *buff;
...@@ -251,12 +271,20 @@ static void ReadNullSepFileToArray(const char *path, char ***arr, ...@@ -251,12 +271,20 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
(*arr)[count] = 0; (*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() { void ReExec() {
static const int kMaxArgv = 100, kMaxEnvp = 1000;
char **argv, **envp; char **argv, **envp;
ReadNullSepFileToArray("/proc/self/cmdline", &argv, kMaxArgv); GetArgsAndEnv(&argv, &envp);
ReadNullSepFileToArray("/proc/self/environ", &envp, kMaxEnvp); execve("/proc/self/exe", argv, envp);
execve(argv[0], argv, envp); Printf("execve failed, errno %d\n", errno);
Die();
} }
void PrepareForSandboxing() { void PrepareForSandboxing() {
......
...@@ -104,6 +104,10 @@ int internal_sched_yield() { ...@@ -104,6 +104,10 @@ int internal_sched_yield() {
return sched_yield(); return sched_yield();
} }
void internal__exit(int exitcode) {
_exit(exitcode);
}
// ----------------- sanitizer_common.h // ----------------- sanitizer_common.h
bool FileExists(const char *filename) { bool FileExists(const char *filename) {
struct stat st; struct stat st;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#if !defined(_WIN32) #if !defined(_WIN32)
# define SI_NOT_WINDOWS 1 # define SI_NOT_WINDOWS 1
# include "sanitizer_platform_limits_posix.h"
#else #else
# define SI_NOT_WINDOWS 0 # define SI_NOT_WINDOWS 0
#endif #endif
...@@ -24,6 +25,12 @@ ...@@ -24,6 +25,12 @@
# define SI_LINUX_NOT_ANDROID 0 # define SI_LINUX_NOT_ANDROID 0
#endif #endif
#if defined(__linux__)
# define SI_LINUX 1
#else
# define SI_LINUX 0
#endif
# define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS
...@@ -33,4 +40,7 @@ ...@@ -33,4 +40,7 @@
# define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID # define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID
# define SANITIZER_INTERCEPT_PRCTL 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_SCANF SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX
//===-- 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 <dirent.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <time.h>
#if defined(__linux__)
#include <sys/vfs.h>
#include <sys/epoll.h>
#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__
//===-- 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
...@@ -42,6 +42,10 @@ int GetPid() { ...@@ -42,6 +42,10 @@ int GetPid() {
return getpid(); return getpid();
} }
u32 GetUid() {
return getuid();
}
uptr GetThreadSelf() { uptr GetThreadSelf() {
return (uptr)pthread_self(); return (uptr)pthread_self();
} }
...@@ -203,10 +207,6 @@ void SleepForMillis(int millis) { ...@@ -203,10 +207,6 @@ void SleepForMillis(int millis) {
usleep(millis * 1000); usleep(millis * 1000);
} }
void Exit(int exitcode) {
_exit(exitcode);
}
void Abort() { void Abort() {
abort(); abort();
} }
......
...@@ -129,8 +129,9 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp, ...@@ -129,8 +129,9 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp,
CHECK(size == 0 && trace[0] == pc); CHECK(size == 0 && trace[0] == pc);
size = 1; size = 1;
uhwptr *frame = (uhwptr *)bp; uhwptr *frame = (uhwptr *)bp;
uhwptr *prev_frame = frame; uhwptr *prev_frame = frame - 1;
while (frame >= prev_frame && // Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
while (frame > prev_frame &&
frame < (uhwptr *)stack_top - 2 && frame < (uhwptr *)stack_top - 2 &&
frame > (uhwptr *)stack_bottom && frame > (uhwptr *)stack_bottom &&
size < max_size) { size < max_size) {
......
...@@ -97,7 +97,7 @@ bool StartSymbolizerSubprocess(const char *path_to_symbolizer, ...@@ -97,7 +97,7 @@ bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
for (int fd = getdtablesize(); fd > 2; fd--) for (int fd = getdtablesize(); fd > 2; fd--)
internal_close(fd); internal_close(fd);
execl(path_to_symbolizer, path_to_symbolizer, (char*)0); execl(path_to_symbolizer, path_to_symbolizer, (char*)0);
Exit(1); internal__exit(1);
} }
// Continue execution in parent process. // Continue execution in parent process.
......
...@@ -129,6 +129,10 @@ const char *GetPwd() { ...@@ -129,6 +129,10 @@ const char *GetPwd() {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
u32 GetUid() {
UNIMPLEMENTED();
}
void DumpProcessMap() { void DumpProcessMap() {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -161,10 +165,6 @@ void SleepForMillis(int millis) { ...@@ -161,10 +165,6 @@ void SleepForMillis(int millis) {
Sleep(millis); Sleep(millis);
} }
void Exit(int exitcode) {
_exit(exitcode);
}
void Abort() { void Abort() {
abort(); abort();
_exit(-1); // abort is not NORETURN on Windows. _exit(-1); // abort is not NORETURN on Windows.
...@@ -251,6 +251,10 @@ int internal_sched_yield() { ...@@ -251,6 +251,10 @@ int internal_sched_yield() {
return 0; return 0;
} }
void internal__exit(int exitcode) {
_exit(exitcode);
}
// ---------------------- BlockingMutex ---------------- {{{1 // ---------------------- BlockingMutex ---------------- {{{1
const uptr LOCK_UNINITIALIZED = 0; const uptr LOCK_UNINITIALIZED = 0;
const uptr LOCK_READY = (uptr)-1; const uptr LOCK_READY = (uptr)-1;
......
...@@ -241,7 +241,7 @@ const char *InitializePlatform() { ...@@ -241,7 +241,7 @@ const char *InitializePlatform() {
g_tls_size = (uptr)InitTlsSize(); g_tls_size = (uptr)InitTlsSize();
InitDataSeg(); InitDataSeg();
#endif #endif
return getenv(kTsanOptionsEnv); return GetEnv(kTsanOptionsEnv);
} }
void FinalizePlatform() { void FinalizePlatform() {
......
...@@ -80,7 +80,7 @@ const char *InitializePlatform() { ...@@ -80,7 +80,7 @@ const char *InitializePlatform() {
setrlimit(RLIMIT_CORE, (rlimit*)&lim); setrlimit(RLIMIT_CORE, (rlimit*)&lim);
} }
return getenv(kTsanOptionsEnv); return GetEnv(kTsanOptionsEnv);
} }
void FinalizePlatform() { void FinalizePlatform() {
......
...@@ -32,7 +32,7 @@ void FlushShadowMemory() { ...@@ -32,7 +32,7 @@ void FlushShadowMemory() {
} }
const char *InitializePlatform() { const char *InitializePlatform() {
return getenv(kTsanOptionsEnv); return GetEnv(kTsanOptionsEnv);
} }
void FinalizePlatform() { void FinalizePlatform() {
......
...@@ -590,6 +590,8 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr, ...@@ -590,6 +590,8 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr,
u64 *shadow_mem, Shadow cur); u64 *shadow_mem, Shadow cur);
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
uptr size, bool is_write); 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 kSizeLog1 = 0;
const int kSizeLog2 = 1; const int kSizeLog2 = 1;
......
...@@ -420,4 +420,26 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, ...@@ -420,4 +420,26 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
shadow_mem, cur); 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 } // namespace __tsan
...@@ -263,6 +263,14 @@ void StatOutput(u64 *stat) { ...@@ -263,6 +263,14 @@ void StatOutput(u64 *stat) {
name[StatInt___isoc99_fscanf] = " fscanf "; name[StatInt___isoc99_fscanf] = " fscanf ";
name[StatInt_on_exit] = " on_exit "; name[StatInt_on_exit] = " on_exit ";
name[StatInt___cxa_atexit] = " __cxa_atexit "; 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[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore "; name[StatAnnotateHappensBefore] = " HappensBefore ";
......
...@@ -262,6 +262,14 @@ enum StatType { ...@@ -262,6 +262,14 @@ enum StatType {
StatInt___isoc99_fscanf, StatInt___isoc99_fscanf,
StatInt_on_exit, StatInt_on_exit,
StatInt___cxa_atexit, 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. // Dynamic annotations.
StatAnnotation, StatAnnotation,
......
...@@ -138,7 +138,7 @@ void InitializeSuppressions() { ...@@ -138,7 +138,7 @@ void InitializeSuppressions() {
g_suppressions = SuppressionParse(0, supp); g_suppressions = SuppressionParse(0, supp);
#ifndef TSAN_GO #ifndef TSAN_GO
supp = __tsan_default_suppressions(); supp = __tsan_default_suppressions();
g_suppressions = SuppressionParse(0, supp); g_suppressions = SuppressionParse(g_suppressions, supp);
#endif #endif
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment