libsanitizer merge from upstream r175733
From-SVN: r196201
This commit is contained in:
parent
22deefcbb7
commit
7df59255e1
40 changed files with 766 additions and 224 deletions
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
PR tree-optimization/56415
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
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>
|
||||
|
||||
PR bootstrap/56327
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -77,9 +77,36 @@ using __sanitizer::uptr;
|
|||
# define ASAN_INTERCEPT___CXA_THROW 0
|
||||
#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, ...) \
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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); \
|
||||
} \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<char*>(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<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 ||
|
||||
!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<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
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
uptr shadow_start = kLowShadowBeg;
|
||||
if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
|
||||
uptr shadow_end = kHighShadowEnd;
|
||||
bool full_shadow_is_available =
|
||||
MemoryRangeIsAvailable(shadow_start, shadow_end);
|
||||
|
||||
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 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
|
||||
void *prot = Mprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
|
||||
CHECK(prot == (void*)kShadowGapBeg);
|
||||
// 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 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.
|
||||
|
|
|
@ -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<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" {
|
|||
// (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) \
|
||||
|
|
|
@ -14,6 +14,11 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// GCC does not understand __has_feature.
|
||||
#if !defined(__has_feature)
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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@
|
||||
|
|
|
@ -43,7 +43,7 @@ void NORETURN Die() {
|
|||
if (DieCallback) {
|
||||
DieCallback();
|
||||
}
|
||||
Exit(1);
|
||||
internal__exit(1);
|
||||
}
|
||||
|
||||
static CheckFailedCallbackType CheckFailedCallback;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <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__
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -241,7 +241,7 @@ const char *InitializePlatform() {
|
|||
g_tls_size = (uptr)InitTlsSize();
|
||||
InitDataSeg();
|
||||
#endif
|
||||
return getenv(kTsanOptionsEnv);
|
||||
return GetEnv(kTsanOptionsEnv);
|
||||
}
|
||||
|
||||
void FinalizePlatform() {
|
||||
|
|
|
@ -80,7 +80,7 @@ const char *InitializePlatform() {
|
|||
setrlimit(RLIMIT_CORE, (rlimit*)&lim);
|
||||
}
|
||||
|
||||
return getenv(kTsanOptionsEnv);
|
||||
return GetEnv(kTsanOptionsEnv);
|
||||
}
|
||||
|
||||
void FinalizePlatform() {
|
||||
|
|
|
@ -32,7 +32,7 @@ void FlushShadowMemory() {
|
|||
}
|
||||
|
||||
const char *InitializePlatform() {
|
||||
return getenv(kTsanOptionsEnv);
|
||||
return GetEnv(kTsanOptionsEnv);
|
||||
}
|
||||
|
||||
void FinalizePlatform() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ";
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue