diff options
author | kcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-02-13 10:46:01 +0000 |
---|---|---|
committer | kcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-02-13 10:46:01 +0000 |
commit | 7da89e8076fc3bc8b0eb22721afdce421d225d71 (patch) | |
tree | c4504a71a4de65630ff00dd7aa8e062235fc5076 /libsanitizer/asan | |
parent | c31c80df29f1ac080fd4b89965599e1b337b15a1 (diff) | |
download | gcc-7da89e8076fc3bc8b0eb22721afdce421d225d71.tar.gz |
libsanitizer merge from upstream r175049
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196009 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libsanitizer/asan')
22 files changed, 346 insertions, 297 deletions
diff --git a/libsanitizer/asan/asan_allocator.cc b/libsanitizer/asan/asan_allocator.cc index f01d2db9dbc..4e97ff57530 100644 --- a/libsanitizer/asan/asan_allocator.cc +++ b/libsanitizer/asan/asan_allocator.cc @@ -32,7 +32,7 @@ #include "asan_report.h" #include "asan_thread.h" #include "asan_thread_registry.h" -#include "sanitizer/asan_interface.h" +#include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_mutex.h" @@ -367,7 +367,7 @@ class MallocInfo { left_chunk->chunk_state != CHUNK_AVAILABLE) return left_chunk; // Choose based on offset. - uptr l_offset = 0, r_offset = 0; + sptr l_offset = 0, r_offset = 0; CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset)); CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset)); if (l_offset < r_offset) @@ -387,7 +387,7 @@ class MallocInfo { CHECK(m->chunk_state == CHUNK_ALLOCATED || m->chunk_state == CHUNK_AVAILABLE || m->chunk_state == CHUNK_QUARANTINE); - uptr offset = 0; + sptr offset = 0; AsanChunkView m_view(m); if (m_view.AddrIsInside(addr, 1, &offset)) return m; @@ -685,6 +685,8 @@ void __asan_free_hook(void *ptr) { namespace __asan { +void InitializeAllocator() { } + void PrintInternalAllocatorStats() { } @@ -710,6 +712,7 @@ void *asan_malloc(uptr size, StackTrace *stack) { } void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) { + if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0; void *ptr = (void*)Allocate(0, nmemb * size, stack, FROM_MALLOC); if (ptr) REAL(memset)(ptr, 0, nmemb * size); diff --git a/libsanitizer/asan/asan_allocator.h b/libsanitizer/asan/asan_allocator.h index cc16ce85497..df2f520c41a 100644 --- a/libsanitizer/asan/asan_allocator.h +++ b/libsanitizer/asan/asan_allocator.h @@ -22,7 +22,7 @@ // will co-exist in the source base for a while. The actual allocator is chosen // at build time by redefining this macro. #ifndef ASAN_ALLOCATOR_VERSION -# if ASAN_LINUX && !ASAN_ANDROID +# if (ASAN_LINUX && !ASAN_ANDROID) || ASAN_MAC || ASAN_WINDOWS # define ASAN_ALLOCATOR_VERSION 2 # else # define ASAN_ALLOCATOR_VERSION 1 @@ -40,6 +40,8 @@ enum AllocType { static const uptr kNumberOfSizeClasses = 255; struct AsanChunk; +void InitializeAllocator(); + class AsanChunkView { public: explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} @@ -51,14 +53,14 @@ class AsanChunkView { uptr FreeTid(); void GetAllocStack(StackTrace *stack); void GetFreeStack(StackTrace *stack); - bool AddrIsInside(uptr addr, uptr access_size, uptr *offset) { + bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) { if (addr >= Beg() && (addr + access_size) <= End()) { *offset = addr - Beg(); return true; } return false; } - bool AddrIsAtLeft(uptr addr, uptr access_size, uptr *offset) { + bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) { (void)access_size; if (addr < Beg()) { *offset = Beg() - addr; @@ -66,12 +68,9 @@ class AsanChunkView { } return false; } - bool AddrIsAtRight(uptr addr, uptr access_size, uptr *offset) { - if (addr + access_size >= End()) { - if (addr <= End()) - *offset = 0; - else - *offset = addr - End(); + bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) { + if (addr + access_size > End()) { + *offset = addr - End(); return true; } return false; @@ -225,50 +224,5 @@ void asan_mz_force_unlock(); void PrintInternalAllocatorStats(); -// Log2 and RoundUpToPowerOfTwo should be inlined for performance. -#if defined(_WIN32) && !defined(__clang__) -extern "C" { -unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT -unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT -#if defined(_WIN64) -unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT -unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT -#endif -} -#endif - -static inline uptr Log2(uptr x) { - CHECK(IsPowerOfTwo(x)); -#if !defined(_WIN32) || defined(__clang__) - return __builtin_ctzl(x); -#elif defined(_WIN64) - unsigned long ret; // NOLINT - _BitScanForward64(&ret, x); - return ret; -#else - unsigned long ret; // NOLINT - _BitScanForward(&ret, x); - return ret; -#endif -} - -static inline uptr RoundUpToPowerOfTwo(uptr size) { - CHECK(size); - if (IsPowerOfTwo(size)) return size; - - unsigned long up; // NOLINT -#if !defined(_WIN32) || defined(__clang__) - up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(size); -#elif defined(_WIN64) - _BitScanReverse64(&up, size); -#else - _BitScanReverse(&up, size); -#endif - CHECK(size < (1ULL << (up + 1))); - CHECK(size > (1ULL << up)); - return 1UL << (up + 1); -} - - } // namespace __asan #endif // ASAN_ALLOCATOR_H diff --git a/libsanitizer/asan/asan_allocator2.cc b/libsanitizer/asan/asan_allocator2.cc index 4aa5141f2a7..1ff120e555c 100644 --- a/libsanitizer/asan/asan_allocator2.cc +++ b/libsanitizer/asan/asan_allocator2.cc @@ -20,7 +20,6 @@ #include "asan_report.h" #include "asan_thread.h" #include "asan_thread_registry.h" -#include "sanitizer/asan_interface.h" #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_list.h" @@ -55,7 +54,11 @@ struct AsanMapUnmapCallback { }; #if SANITIZER_WORDSIZE == 64 +#if defined(__powerpc64__) +const uptr kAllocatorSpace = 0xa0000000000ULL; +#else const uptr kAllocatorSpace = 0x600000000000ULL; +#endif const uptr kAllocatorSize = 0x10000000000ULL; // 1T. typedef DefaultSizeClassMap SizeClassMap; typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/, @@ -89,8 +92,6 @@ static const uptr kMaxAllowedMallocSize = static const uptr kMaxThreadLocalQuarantine = FIRST_32_SECOND_64(1 << 18, 1 << 20); -static const uptr kReturnOnZeroMalloc = 2048; // Zero page is protected. - // Every chunk of memory allocated by this allocator can be in one of 3 states: // CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated. // CHUNK_ALLOCATED: the chunk is allocated and not yet freed. @@ -112,7 +113,7 @@ static u32 RZSize2Log(u32 rz_size) { CHECK_GE(rz_size, 16); CHECK_LE(rz_size, 2048); CHECK(IsPowerOfTwo(rz_size)); - u32 res = __builtin_ctz(rz_size) - 4; + u32 res = Log2(rz_size) - 4; CHECK_EQ(rz_size, RZLog2Size(res)); return res; } @@ -289,27 +290,26 @@ struct QuarantineCallback { AllocatorCache *cache_; }; -static void Init() { - static int inited = 0; - if (inited) return; - __asan_init(); - inited = true; // this must happen before any threads are created. +void InitializeAllocator() { allocator.Init(); quarantine.Init((uptr)flags()->quarantine_size, kMaxThreadLocalQuarantine); } static void *Allocate(uptr size, uptr alignment, StackTrace *stack, AllocType alloc_type) { - Init(); + if (!asan_inited) + __asan_init(); CHECK(stack); const uptr min_alignment = SHADOW_GRANULARITY; if (alignment < min_alignment) alignment = min_alignment; if (size == 0) { - if (alignment <= kReturnOnZeroMalloc) - return reinterpret_cast<void *>(kReturnOnZeroMalloc); - else - return 0; // 0 bytes with large alignment requested. Just return 0. + // We'd be happy to avoid allocating memory for zero-size requests, but + // some programs/tests depend on this behavior and assume that malloc would + // not return NULL even for zero-size allocations. Moreover, it looks like + // operator new should never return NULL, and results of consecutive "new" + // calls must be different even if the allocated size is zero. + size = 1; } CHECK(IsPowerOfTwo(alignment)); uptr rz_log = ComputeRZLog(size); @@ -415,7 +415,8 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack, static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) { uptr p = reinterpret_cast<uptr>(ptr); - if (p == 0 || p == kReturnOnZeroMalloc) return; + if (p == 0) return; + ASAN_FREE_HOOK(ptr); uptr chunk_beg = p - kChunkHeaderSize; AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg); @@ -465,8 +466,6 @@ static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) { quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac), m, m->UsedSize()); } - - ASAN_FREE_HOOK(ptr); } static void *Reallocate(void *old_ptr, uptr new_size, StackTrace *stack) { @@ -546,7 +545,7 @@ AsanChunk *ChooseChunk(uptr addr, return right_chunk; } // Same chunk_state: choose based on offset. - uptr l_offset = 0, r_offset = 0; + sptr l_offset = 0, r_offset = 0; CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset)); CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset)); if (l_offset < r_offset) @@ -557,7 +556,7 @@ AsanChunk *ChooseChunk(uptr addr, AsanChunkView FindHeapChunkByAddress(uptr addr) { AsanChunk *m1 = GetAsanChunkByAddr(addr); if (!m1) return AsanChunkView(m1); - uptr offset = 0; + sptr offset = 0; if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) { // The address is in the chunk's left redzone, so maybe it is actually // a right buffer overflow from the other chunk to the left. @@ -601,6 +600,7 @@ void *asan_malloc(uptr size, StackTrace *stack) { } void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) { + if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0; void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC); if (ptr) REAL(memset)(ptr, 0, nmemb * size); @@ -649,16 +649,17 @@ uptr asan_malloc_usable_size(void *ptr, StackTrace *stack) { } uptr asan_mz_size(const void *ptr) { - UNIMPLEMENTED(); - return 0; + return AllocationSize(reinterpret_cast<uptr>(ptr)); } void asan_mz_force_lock() { - UNIMPLEMENTED(); + allocator.ForceLock(); + fallback_mutex.Lock(); } void asan_mz_force_unlock() { - UNIMPLEMENTED(); + fallback_mutex.Unlock(); + allocator.ForceUnlock(); } } // namespace __asan @@ -674,7 +675,7 @@ uptr __asan_get_estimated_allocated_size(uptr size) { bool __asan_get_ownership(const void *p) { uptr ptr = reinterpret_cast<uptr>(p); - return (ptr == kReturnOnZeroMalloc) || (AllocationSize(ptr) > 0); + return (AllocationSize(ptr) > 0); } uptr __asan_get_allocated_size(const void *p) { @@ -682,7 +683,7 @@ uptr __asan_get_allocated_size(const void *p) { uptr ptr = reinterpret_cast<uptr>(p); uptr allocated_size = AllocationSize(ptr); // Die if p is not malloced or if it is already freed. - if (allocated_size == 0 && ptr != kReturnOnZeroMalloc) { + if (allocated_size == 0) { GET_STACK_TRACE_FATAL_HERE; ReportAsanGetAllocatedSizeNotOwned(ptr, &stack); } diff --git a/libsanitizer/asan/asan_fake_stack.cc b/libsanitizer/asan/asan_fake_stack.cc index e8d1e78488b..1fc0415750b 100644 --- a/libsanitizer/asan/asan_fake_stack.cc +++ b/libsanitizer/asan/asan_fake_stack.cc @@ -12,7 +12,6 @@ #include "asan_allocator.h" #include "asan_thread.h" #include "asan_thread_registry.h" -#include "sanitizer/asan_interface.h" namespace __asan { diff --git a/libsanitizer/asan/asan_flags.h b/libsanitizer/asan/asan_flags.h index 49a90730084..b05fdc3acc6 100644 --- a/libsanitizer/asan/asan_flags.h +++ b/libsanitizer/asan/asan_flags.h @@ -13,7 +13,7 @@ #ifndef ASAN_FLAGS_H #define ASAN_FLAGS_H -#include "sanitizer/common_interface_defs.h" +#include "sanitizer_common/sanitizer_internal_defs.h" // ASan flag values can be defined in three ways: // 1) initialized with default values at startup. @@ -50,8 +50,6 @@ struct Flags { bool replace_str; // If set, uses custom wrappers for memset/memcpy/memmove intinsics. bool replace_intrin; - // Used on Mac only. See comments in asan_mac.cc and asan_malloc_mac.cc. - bool replace_cfallocator; // Used on Mac only. bool mac_ignore_invalid_free; // ASan allocator flag. See asan_allocator.cc. @@ -77,6 +75,10 @@ struct Flags { bool unmap_shadow_on_exit; // If set, calls abort() instead of _exit() after printing an error report. bool abort_on_error; + // Print various statistics after printing an error message or if atexit=1. + bool print_stats; + // Print the legend for the shadow bytes. + bool print_legend; // If set, prints ASan exit stats even after program terminates successfully. bool atexit; // By default, disable core dumper on 64-bit - it makes little sense diff --git a/libsanitizer/asan/asan_globals.cc b/libsanitizer/asan/asan_globals.cc index 88aeefa8fe5..7093c445588 100644 --- a/libsanitizer/asan/asan_globals.cc +++ b/libsanitizer/asan/asan_globals.cc @@ -16,7 +16,6 @@ #include "asan_stack.h" #include "asan_stats.h" #include "asan_thread.h" -#include "sanitizer/asan_interface.h" #include "sanitizer_common/sanitizer_mutex.h" namespace __asan { @@ -34,26 +33,20 @@ static ListOfGlobals *list_of_all_globals; static ListOfGlobals *list_of_dynamic_init_globals; void PoisonRedZones(const Global &g) { - uptr shadow_rz_size = kGlobalAndStackRedzone >> SHADOW_SCALE; - CHECK(shadow_rz_size == 1 || shadow_rz_size == 2 || shadow_rz_size == 4); - // full right redzone - uptr g_aligned_size = kGlobalAndStackRedzone * - ((g.size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone); - PoisonShadow(g.beg + g_aligned_size, - kGlobalAndStackRedzone, kAsanGlobalRedzoneMagic); - if ((g.size % kGlobalAndStackRedzone) != 0) { + uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY); + PoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size, + kAsanGlobalRedzoneMagic); + if (g.size != aligned_size) { // partial right redzone - u64 g_aligned_down_size = kGlobalAndStackRedzone * - (g.size / kGlobalAndStackRedzone); - CHECK(g_aligned_down_size == g_aligned_size - kGlobalAndStackRedzone); - PoisonShadowPartialRightRedzone(g.beg + g_aligned_down_size, - g.size % kGlobalAndStackRedzone, - kGlobalAndStackRedzone, - kAsanGlobalRedzoneMagic); + PoisonShadowPartialRightRedzone( + g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY), + g.size % SHADOW_GRANULARITY, + SHADOW_GRANULARITY, + kAsanGlobalRedzoneMagic); } } -bool DescribeAddressIfGlobal(uptr addr) { +bool DescribeAddressIfGlobal(uptr addr, uptr size) { if (!flags()->report_globals) return false; BlockingMutexLock lock(&mu_for_globals); bool res = false; @@ -62,7 +55,7 @@ bool DescribeAddressIfGlobal(uptr addr) { if (flags()->report_globals >= 2) Report("Search Global: beg=%p size=%zu name=%s\n", (void*)g.beg, g.size, (char*)g.name); - res |= DescribeAddressRelativeToGlobal(addr, g); + res |= DescribeAddressRelativeToGlobal(addr, size, g); } return res; } diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h index 2d678ab7000..45c913c1894 100644 --- a/libsanitizer/asan/asan_intercepted_functions.h +++ b/libsanitizer/asan/asan_intercepted_functions.h @@ -17,6 +17,7 @@ #include "sanitizer_common/sanitizer_platform_interceptors.h" #include <stdarg.h> +#include <stddef.h> using __sanitizer::uptr; @@ -64,9 +65,7 @@ using __sanitizer::uptr; # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0 #endif -// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it -// there. -#if !defined(_WIN32) && (!defined(__APPLE__) || MAC_INTERPOSE_FUNCTIONS) +#if !defined(_WIN32) # define ASAN_INTERCEPT_SIGLONGJMP 1 #else # define ASAN_INTERCEPT_SIGLONGJMP 0 @@ -169,7 +168,8 @@ DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pread64, int fd, void *buf, DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, write, int fd, void *ptr, SIZE_T count); # endif # if SANITIZER_INTERCEPT_PWRITE -DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count); +DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pwrite, + int fd, void *ptr, SIZE_T count, OFF_T offset); # endif # if ASAN_INTERCEPT_MLOCKX @@ -193,6 +193,8 @@ DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create, void *(*start_routine)(void*), void *arg); # endif +// stdio.h +# if SANITIZER_INTERCEPT_SCANF DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap); DECLARE_FUNCTION_AND_WRAPPER(int, vsscanf, const char *str, const char *format, va_list ap); @@ -203,6 +205,18 @@ 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__) typedef void* pthread_workqueue_t; @@ -231,7 +245,7 @@ DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async_f, dispatch_group_t group, dispatch_queue_t dq, void *ctxt, dispatch_function_t func); -# if MAC_INTERPOSE_FUNCTIONS && !defined(MISSING_BLOCKS_SUPPORT) +# if !defined(MISSING_BLOCKS_SUPPORT) DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async, dispatch_group_t dg, dispatch_queue_t dq, void (^work)(void)); @@ -243,7 +257,7 @@ DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_event_handler, dispatch_source_t ds, void (^work)(void)); DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_cancel_handler, dispatch_source_t ds, void (^work)(void)); -# endif // MAC_INTERPOSE_FUNCTIONS +# endif // MISSING_BLOCKS_SUPPORT typedef void malloc_zone_t; typedef size_t vm_size_t; diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc index 98329f38e61..f4c56830d8a 100644 --- a/libsanitizer/asan/asan_interceptors.cc +++ b/libsanitizer/asan/asan_interceptors.cc @@ -20,7 +20,6 @@ #include "asan_stats.h" #include "asan_thread_registry.h" #include "interception/interception.h" -#include "sanitizer/asan_interface.h" #include "sanitizer_common/sanitizer_libc.h" namespace __asan { @@ -30,12 +29,14 @@ namespace __asan { // that no extra frames are created, and stack trace contains // relevant information only. // We check all shadow bytes. -#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ - if (uptr __ptr = __asan_region_is_poisoned((uptr)(offset), size)) { \ - GET_CURRENT_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, __ptr, isWrite, /* access_size */1); \ - } \ -} while (0) +#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ + uptr __offset = (uptr)(offset); \ + uptr __size = (uptr)(size); \ + if (__asan_region_is_poisoned(__offset, __size)) { \ + GET_CURRENT_PC_BP_SP; \ + __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \ + } \ + } while (0) #define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false) #define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true); @@ -275,13 +276,9 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { ASAN_READ_RANGE(from, size); ASAN_WRITE_RANGE(to, size); } -#if MAC_INTERPOSE_FUNCTIONS // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. return internal_memcpy(to, from, size); -#else - return REAL(memcpy)(to, from, size); -#endif } INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { @@ -294,13 +291,9 @@ INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { ASAN_READ_RANGE(from, size); ASAN_WRITE_RANGE(to, size); } -#if MAC_INTERPOSE_FUNCTIONS // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. return internal_memmove(to, from, size); -#else - return REAL(memmove)(to, from, size); -#endif } INTERCEPTOR(void*, memset, void *block, int c, uptr size) { @@ -398,7 +391,7 @@ INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { } INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT -#if MAC_INTERPOSE_FUNCTIONS +#if defined(__APPLE__) if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT #endif // strcpy is called from malloc_default_purgeable_zone() @@ -418,7 +411,7 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT #if ASAN_INTERCEPT_STRDUP INTERCEPTOR(char*, strdup, const char *s) { -#if MAC_INTERPOSE_FUNCTIONS +#if defined(__APPLE__) // FIXME: because internal_strdup() uses InternalAlloc(), which currently // just calls malloc() on Mac, we can't use internal_strdup() with the // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc @@ -559,7 +552,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT } INTERCEPTOR(int, atoi, const char *nptr) { -#if MAC_INTERPOSE_FUNCTIONS +#if defined(__APPLE__) if (!asan_inited) return REAL(atoi)(nptr); #endif ENSURE_ASAN_INITED(); @@ -578,7 +571,7 @@ INTERCEPTOR(int, atoi, const char *nptr) { } INTERCEPTOR(long, atol, const char *nptr) { // NOLINT -#if MAC_INTERPOSE_FUNCTIONS +#if defined(__APPLE__) if (!asan_inited) return REAL(atol)(nptr); #endif ENSURE_ASAN_INITED(); @@ -659,10 +652,9 @@ void InitializeAsanInterceptors() { static bool was_called_once; CHECK(was_called_once == false); was_called_once = true; -#if MAC_INTERPOSE_FUNCTIONS +#if defined(__APPLE__) return; -#endif - +#else SANITIZER_COMMON_INTERCEPTORS_INIT; // Intercept mem* functions. @@ -671,12 +663,6 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(memset); if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { ASAN_INTERCEPT_FUNC(memcpy); - } else { -#if !MAC_INTERPOSE_FUNCTIONS - // If we're using dynamic interceptors on Mac, these two are just plain - // functions. - internal_memcpy(&REAL(memcpy), &REAL(memmove), sizeof(REAL(memmove))); -#endif } // Intercept str* functions. @@ -698,12 +684,8 @@ void InitializeAsanInterceptors() { #if ASAN_INTERCEPT_STRNLEN ASAN_INTERCEPT_FUNC(strnlen); #endif -#if ASAN_INTERCEPT_INDEX -# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX +#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX ASAN_INTERCEPT_FUNC(index); -# else - CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr))); -# endif #endif ASAN_INTERCEPT_FUNC(atoi); @@ -753,14 +735,10 @@ void InitializeAsanInterceptors() { InitializeWindowsInterceptors(); #endif - // Some Mac-specific interceptors. -#if defined(__APPLE__) - InitializeMacInterceptors(); -#endif - if (flags()->verbosity > 0) { Report("AddressSanitizer: libc interceptors initialized\n"); } +#endif // __APPLE__ } } // namespace __asan diff --git a/libsanitizer/asan/asan_interceptors.h b/libsanitizer/asan/asan_interceptors.h index a6ab0309bff..cae4c7f0125 100644 --- a/libsanitizer/asan/asan_interceptors.h +++ b/libsanitizer/asan/asan_interceptors.h @@ -30,9 +30,6 @@ DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act, namespace __asan { void InitializeAsanInterceptors(); -#if defined(__APPLE__) -void InitializeMacInterceptors(); -#endif // __APPLE__ } // namespace __asan diff --git a/libsanitizer/asan/asan_interface_internal.h b/libsanitizer/asan/asan_interface_internal.h new file mode 100644 index 00000000000..2fd58b856bc --- /dev/null +++ b/libsanitizer/asan/asan_interface_internal.h @@ -0,0 +1,133 @@ +//===-- asan_interface_internal.h -------------------------------*- C++ -*-===// +// +// 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. +// +// This header can be included by the instrumented program to fetch +// data (mostly allocator statistics) from ASan runtime library. +//===----------------------------------------------------------------------===// +#ifndef ASAN_INTERFACE_INTERNAL_H +#define ASAN_INTERFACE_INTERNAL_H + +#include "sanitizer_common/sanitizer_internal_defs.h" + +using __sanitizer::uptr; + +extern "C" { + // This function should be called at the very beginning of the process, + // before any instrumented code is executed and before any call to malloc. + // Everytime the asan ABI changes we also change the version number in this + // name. Objects build with incompatible asan ABI version + // will not link with run-time. + void __asan_init_v1() SANITIZER_INTERFACE_ATTRIBUTE; + #define __asan_init __asan_init_v1 + + // This structure describes an instrumented global variable. + struct __asan_global { + uptr beg; // The address of the global. + uptr size; // The original size of the global. + uptr size_with_redzone; // The size with the redzone. + const char *name; // Name as a C string. + uptr has_dynamic_init; // Non-zero if the global has dynamic initializer. + }; + + // These two functions should be called by the instrumented code. + // 'globals' is an array of structures describing 'n' globals. + void __asan_register_globals(__asan_global *globals, uptr n) + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_unregister_globals(__asan_global *globals, uptr n) + SANITIZER_INTERFACE_ATTRIBUTE; + + // These two functions should be called before and after dynamic initializers + // run, respectively. They should be called with parameters describing all + // dynamically initialized globals defined in the calling TU. + void __asan_before_dynamic_init(uptr first_addr, uptr last_addr) + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_after_dynamic_init() + SANITIZER_INTERFACE_ATTRIBUTE; + + // These two functions are used by the instrumented code in the + // use-after-return mode. __asan_stack_malloc allocates size bytes of + // fake stack and __asan_stack_free poisons it. real_stack is a pointer to + // the real stack region. + uptr __asan_stack_malloc(uptr size, uptr real_stack) + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_stack_free(uptr ptr, uptr size, uptr real_stack) + SANITIZER_INTERFACE_ATTRIBUTE; + + // These two functions are used by instrumented code in the + // use-after-scope mode. They mark memory for local variables as + // unaddressable when they leave scope and addressable before the + // function exits. + void __asan_poison_stack_memory(uptr addr, uptr size) + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_unpoison_stack_memory(uptr addr, uptr size) + SANITIZER_INTERFACE_ATTRIBUTE; + + // Performs cleanup before a NoReturn function. Must be called before things + // like _exit and execl to avoid false positives on stack. + void __asan_handle_no_return() SANITIZER_INTERFACE_ATTRIBUTE; + + void __asan_poison_memory_region(void const volatile *addr, uptr size) + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_unpoison_memory_region(void const volatile *addr, uptr size) + SANITIZER_INTERFACE_ATTRIBUTE; + + bool __asan_address_is_poisoned(void const volatile *addr) + SANITIZER_INTERFACE_ATTRIBUTE; + + uptr __asan_region_is_poisoned(uptr beg, uptr size) + SANITIZER_INTERFACE_ATTRIBUTE; + + void __asan_describe_address(uptr addr) + SANITIZER_INTERFACE_ATTRIBUTE; + + void __asan_report_error(uptr pc, uptr bp, uptr sp, + uptr addr, bool is_write, uptr access_size) + SANITIZER_INTERFACE_ATTRIBUTE; + + int __asan_set_error_exit_code(int exit_code) + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_set_death_callback(void (*callback)(void)) + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_set_error_report_callback(void (*callback)(const char*)) + SANITIZER_INTERFACE_ATTRIBUTE; + + /* OPTIONAL */ void __asan_on_error() + SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; + + /* OPTIONAL */ bool __asan_symbolize(const void *pc, char *out_buffer, + int out_size) + SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; + + uptr __asan_get_estimated_allocated_size(uptr size) + SANITIZER_INTERFACE_ATTRIBUTE; + bool __asan_get_ownership(const void *p) + SANITIZER_INTERFACE_ATTRIBUTE; + uptr __asan_get_allocated_size(const void *p) + SANITIZER_INTERFACE_ATTRIBUTE; + uptr __asan_get_current_allocated_bytes() + SANITIZER_INTERFACE_ATTRIBUTE; + uptr __asan_get_heap_size() + SANITIZER_INTERFACE_ATTRIBUTE; + uptr __asan_get_free_bytes() + SANITIZER_INTERFACE_ATTRIBUTE; + uptr __asan_get_unmapped_bytes() + SANITIZER_INTERFACE_ATTRIBUTE; + void __asan_print_accumulated_stats() + SANITIZER_INTERFACE_ATTRIBUTE; + + /* OPTIONAL */ const char* __asan_default_options() + SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; + + /* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size) + SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; + /* OPTIONAL */ void __asan_free_hook(void *ptr) + SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; +} // extern "C" + +#endif // ASAN_INTERFACE_INTERNAL_H diff --git a/libsanitizer/asan/asan_internal.h b/libsanitizer/asan/asan_internal.h index a9c6c0f9022..0fe620e2e4c 100644 --- a/libsanitizer/asan/asan_internal.h +++ b/libsanitizer/asan/asan_internal.h @@ -13,6 +13,7 @@ #define ASAN_INTERNAL_H #include "asan_flags.h" +#include "asan_interface_internal.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_stacktrace.h" diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc index a49d5c5ab8f..c5fc7de10c0 100644 --- a/libsanitizer/asan/asan_mac.cc +++ b/libsanitizer/asan/asan_mac.cc @@ -89,10 +89,9 @@ static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; void MaybeReexec() { if (!flags()->allow_reexec) return; -#if MAC_INTERPOSE_FUNCTIONS - // If the program is linked with the dynamic ASan runtime library, make sure - // the library is preloaded so that the wrappers work. If it is not, set - // DYLD_INSERT_LIBRARIES and re-exec ourselves. + // Make sure the dynamic ASan runtime library is preloaded so that the + // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec + // ourselves. Dl_info info; CHECK(dladdr((void*)((uptr)__asan_init), &info)); const char *dyld_insert_libraries = GetEnv(kDyldInsertLibraries); @@ -114,8 +113,6 @@ void MaybeReexec() { } execv(program_name, *_NSGetArgv()); } -#endif // MAC_INTERPOSE_FUNCTIONS - // If we're not using the dynamic runtime, do nothing. } // No-op. Mac does not support static linkage anyway. @@ -146,57 +143,6 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) { UNIMPLEMENTED(); } -// The range of pages to be used for escape islands. -// TODO(glider): instead of mapping a fixed range we must find a range of -// unmapped pages in vmmap and take them. -// These constants were chosen empirically and may not work if the shadow -// memory layout changes. Unfortunately they do necessarily depend on -// kHighMemBeg or kHighMemEnd. -static void *island_allocator_pos = 0; - -#if SANITIZER_WORDSIZE == 32 -# define kIslandEnd (0xffdf0000 - GetPageSizeCached()) -# define kIslandBeg (kIslandEnd - 256 * GetPageSizeCached()) -#else -# define kIslandEnd (0x7fffffdf0000 - GetPageSizeCached()) -# define kIslandBeg (kIslandEnd - 256 * GetPageSizeCached()) -#endif - -extern "C" -mach_error_t __interception_allocate_island(void **ptr, - uptr unused_size, - void *unused_hint) { - if (!island_allocator_pos) { - island_allocator_pos = - internal_mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, - -1, 0); - if (island_allocator_pos != (void*)kIslandBeg) { - return KERN_NO_SPACE; - } - if (flags()->verbosity) { - Report("Mapped pages %p--%p for branch islands.\n", - (void*)kIslandBeg, (void*)kIslandEnd); - } - // Should not be very performance-critical. - internal_memset(island_allocator_pos, 0xCC, kIslandEnd - kIslandBeg); - }; - *ptr = island_allocator_pos; - island_allocator_pos = (char*)island_allocator_pos + GetPageSizeCached(); - if (flags()->verbosity) { - Report("Branch island allocated at %p\n", *ptr); - } - return err_none; -} - -extern "C" -mach_error_t __interception_deallocate_island(void *ptr) { - // Do nothing. - // TODO(glider): allow to free and reuse the island memory. - return err_none; -} - // Support for the following functions from libdispatch on Mac OS: // dispatch_async_f() // dispatch_async() @@ -350,14 +296,7 @@ INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group, asan_dispatch_call_block_and_release); } -#if MAC_INTERPOSE_FUNCTIONS && !defined(MISSING_BLOCKS_SUPPORT) -// dispatch_async, dispatch_group_async and others tailcall the corresponding -// dispatch_*_f functions. When wrapping functions with mach_override, those -// dispatch_*_f are intercepted automatically. But with dylib interposition -// this does not work, because the calls within the same library are not -// interposed. -// Therefore we need to re-implement dispatch_async and friends. - +#if !defined(MISSING_BLOCKS_SUPPORT) extern "C" { // FIXME: consolidate these declarations with asan_intercepted_functions.h. void dispatch_async(dispatch_queue_t dq, void(^work)(void)); @@ -410,16 +349,4 @@ INTERCEPTOR(void, dispatch_source_set_event_handler, } #endif -namespace __asan { - -void InitializeMacInterceptors() { - CHECK(INTERCEPT_FUNCTION(dispatch_async_f)); - CHECK(INTERCEPT_FUNCTION(dispatch_sync_f)); - CHECK(INTERCEPT_FUNCTION(dispatch_after_f)); - CHECK(INTERCEPT_FUNCTION(dispatch_barrier_async_f)); - CHECK(INTERCEPT_FUNCTION(dispatch_group_async_f)); -} - -} // namespace __asan - #endif // __APPLE__ diff --git a/libsanitizer/asan/asan_malloc_linux.cc b/libsanitizer/asan/asan_malloc_linux.cc index e33d0c0d4d3..18e6a3be865 100644 --- a/libsanitizer/asan/asan_malloc_linux.cc +++ b/libsanitizer/asan/asan_malloc_linux.cc @@ -18,7 +18,6 @@ #include "asan_internal.h" #include "asan_stack.h" #include "asan_thread_registry.h" -#include "sanitizer/asan_interface.h" #if ASAN_ANDROID DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h index be645c4afcd..3e7fc6bd43b 100644 --- a/libsanitizer/asan/asan_mapping.h +++ b/libsanitizer/asan/asan_mapping.h @@ -1,5 +1,7 @@ //===-- 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. // @@ -34,27 +36,20 @@ 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 #endif // ASAN_FLEXIBLE_MAPPING_AND_OFFSET #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) -#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) | (SHADOW_OFFSET)) +#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET)) #define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE) -#if SANITIZER_WORDSIZE == 64 -# if defined(__powerpc64__) - static const uptr kHighMemEnd = 0x00000fffffffffffUL; -# else - static const uptr kHighMemEnd = 0x00007fffffffffffUL; -# endif -#else // SANITIZER_WORDSIZE == 32 - static const uptr kHighMemEnd = 0xffffffff; -#endif // SANITIZER_WORDSIZE - - #define kLowMemBeg 0 #define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0) @@ -74,11 +69,11 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; : kZeroBaseShadowStart) #define kShadowGapEnd (kHighShadowBeg - 1) -#define kGlobalAndStackRedzone \ - (SHADOW_GRANULARITY < 32 ? 32 : SHADOW_GRANULARITY) - namespace __asan { +SANITIZER_INTERFACE_ATTRIBUTE +extern uptr kHighMemEnd; // Initialized in __asan_init. + static inline bool AddrIsInLowMem(uptr a) { return a < kLowMemEnd; } diff --git a/libsanitizer/asan/asan_new_delete.cc b/libsanitizer/asan/asan_new_delete.cc index e41135d0e51..fd47eee4205 100644 --- a/libsanitizer/asan/asan_new_delete.cc +++ b/libsanitizer/asan/asan_new_delete.cc @@ -25,9 +25,9 @@ void ReplaceOperatorsNewAndDelete() { } using namespace __asan; // NOLINT -// On Mac and Android new() goes through malloc interceptors. +// On Android new() goes through malloc interceptors. // See also https://code.google.com/p/address-sanitizer/issues/detail?id=131. -#if !ASAN_ANDROID && !ASAN_MAC +#if !ASAN_ANDROID // Fake std::nothrow_t to avoid including <new>. namespace std { diff --git a/libsanitizer/asan/asan_poisoning.cc b/libsanitizer/asan/asan_poisoning.cc index 11edca57ae0..7e930034bef 100644 --- a/libsanitizer/asan/asan_poisoning.cc +++ b/libsanitizer/asan/asan_poisoning.cc @@ -13,7 +13,6 @@ #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_mapping.h" -#include "sanitizer/asan_interface.h" #include "sanitizer_common/sanitizer_libc.h" namespace __asan { diff --git a/libsanitizer/asan/asan_report.cc b/libsanitizer/asan/asan_report.cc index ed18ab25098..663e8f3b748 100644 --- a/libsanitizer/asan/asan_report.cc +++ b/libsanitizer/asan/asan_report.cc @@ -118,19 +118,7 @@ static void PrintShadowBytes(const char *before, u8 *bytes, Printf("\n"); } -static void PrintShadowMemoryForAddress(uptr addr) { - if (!AddrIsInMem(addr)) - return; - uptr shadow_addr = MemToShadow(addr); - const uptr n_bytes_per_row = 16; - uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1); - Printf("Shadow bytes around the buggy address:\n"); - for (int i = -5; i <= 5; i++) { - const char *prefix = (i == 0) ? "=>" : " "; - PrintShadowBytes(prefix, - (u8*)(aligned_shadow + i * n_bytes_per_row), - (u8*)shadow_addr, n_bytes_per_row); - } +static void PrintLegend() { Printf("Shadow byte legend (one shadow byte represents %d " "application bytes):\n", (int)SHADOW_GRANULARITY); PrintShadowByte(" Addressable: ", 0); @@ -153,6 +141,23 @@ static void PrintShadowMemoryForAddress(uptr addr) { PrintShadowByte(" ASan internal: ", kAsanInternalHeapMagic); } +static void PrintShadowMemoryForAddress(uptr addr) { + if (!AddrIsInMem(addr)) + return; + uptr shadow_addr = MemToShadow(addr); + const uptr n_bytes_per_row = 16; + uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1); + Printf("Shadow bytes around the buggy address:\n"); + for (int i = -5; i <= 5; i++) { + const char *prefix = (i == 0) ? "=>" : " "; + PrintShadowBytes(prefix, + (u8*)(aligned_shadow + i * n_bytes_per_row), + (u8*)shadow_addr, n_bytes_per_row); + } + if (flags()->print_legend) + PrintLegend(); +} + static void PrintZoneForPointer(uptr ptr, uptr zone_ptr, const char *zone_name) { if (zone_ptr) { @@ -183,18 +188,23 @@ static void PrintGlobalNameIfASCII(const __asan_global &g) { Printf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg); } -bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) { - if (addr < g.beg - kGlobalAndStackRedzone) return false; +bool DescribeAddressRelativeToGlobal(uptr addr, uptr size, + const __asan_global &g) { + static const uptr kMinimalDistanceFromAnotherGlobal = 64; + if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false; if (addr >= g.beg + g.size_with_redzone) return false; Decorator d; Printf("%s", d.Location()); - Printf("%p is located ", (void*)addr); if (addr < g.beg) { - Printf("%zd bytes to the left", g.beg - addr); - } else if (addr >= g.beg + g.size) { - Printf("%zd bytes to the right", addr - (g.beg + g.size)); + Printf("%p is located %zd bytes to the left", (void*)addr, g.beg - addr); + } else if (addr + size > g.beg + g.size) { + if (addr < g.beg + g.size) + addr = g.beg + g.size; + Printf("%p is located %zd bytes to the right", (void*)addr, + addr - (g.beg + g.size)); } else { - Printf("%zd bytes inside", addr - g.beg); // Can it happen? + // Can it happen? + Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg); } Printf(" of global variable '%s' (0x%zx) of size %zu\n", g.name, g.beg, g.size); @@ -280,18 +290,22 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) { static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, uptr access_size) { - uptr offset; + sptr offset; Decorator d; Printf("%s", d.Location()); - Printf("%p is located ", (void*)addr); - if (chunk.AddrIsInside(addr, access_size, &offset)) { - Printf("%zu bytes inside of", offset); - } else if (chunk.AddrIsAtLeft(addr, access_size, &offset)) { - Printf("%zu bytes to the left of", offset); + if (chunk.AddrIsAtLeft(addr, access_size, &offset)) { + Printf("%p is located %zd bytes to the left of", (void*)addr, offset); } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) { - Printf("%zu bytes to the right of", offset); + if (offset < 0) { + addr -= offset; + offset = 0; + } + Printf("%p is located %zd bytes to the right of", (void*)addr, offset); + } else if (chunk.AddrIsInside(addr, access_size, &offset)) { + Printf("%p is located %zd bytes inside of", (void*)addr, offset); } else { - Printf(" somewhere around (this is AddressSanitizer bug!)"); + Printf("%p is located somewhere around (this is AddressSanitizer bug!)", + (void*)addr); } Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(), (void*)(chunk.Beg()), (void*)(chunk.End())); @@ -364,7 +378,7 @@ void DescribeAddress(uptr addr, uptr access_size) { if (DescribeAddressIfShadow(addr)) return; CHECK(AddrIsInMem(addr)); - if (DescribeAddressIfGlobal(addr)) + if (DescribeAddressIfGlobal(addr, access_size)) return; if (DescribeAddressIfStack(addr, access_size)) return; @@ -443,7 +457,8 @@ class ScopedInErrorReport { DescribeThread(curr_thread->summary()); } // Print memory stats. - __asan_print_accumulated_stats(); + if (flags()->print_stats) + __asan_print_accumulated_stats(); if (error_report_callback) { error_report_callback(error_message_buffer); } @@ -452,6 +467,20 @@ class ScopedInErrorReport { } }; +static void ReportSummary(const char *error_type, StackTrace *stack) { + if (!stack->size) return; + if (IsSymbolizerAvailable()) { + AddressInfo ai; + // Currently, we include the first stack frame into the report summary. + // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). + SymbolizeCode(stack->trace[0], &ai, 1); + ReportErrorSummary(error_type, + StripPathPrefix(ai.file, flags()->strip_path_prefix), + ai.line, ai.function); + } + // FIXME: do we need to print anything at all if there is no symbolizer? +} + void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { ScopedInErrorReport in_report; Decorator d; @@ -464,6 +493,7 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { Printf("AddressSanitizer can not provide additional info.\n"); GET_STACK_TRACE_FATAL(pc, bp); PrintStack(&stack); + ReportSummary("SEGV", &stack); } void ReportDoubleFree(uptr addr, StackTrace *stack) { @@ -474,6 +504,7 @@ void ReportDoubleFree(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("double-free", stack); } void ReportFreeNotMalloced(uptr addr, StackTrace *stack) { @@ -485,6 +516,7 @@ void ReportFreeNotMalloced(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("bad-free", stack); } void ReportAllocTypeMismatch(uptr addr, StackTrace *stack, @@ -503,6 +535,7 @@ void ReportAllocTypeMismatch(uptr addr, StackTrace *stack, Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("alloc-dealloc-mismatch", stack); Report("HINT: if you don't care about these warnings you may set " "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); } @@ -517,6 +550,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("bad-malloc_usable_size", stack); } void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) { @@ -529,6 +563,7 @@ void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("bad-__asan_get_allocated_size", stack); } void ReportStringFunctionMemoryRangesOverlap( @@ -536,14 +571,17 @@ void ReportStringFunctionMemoryRangesOverlap( const char *offset2, uptr length2, StackTrace *stack) { ScopedInErrorReport in_report; Decorator d; + char bug_type[100]; + internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); Printf("%s", d.Warning()); - Report("ERROR: AddressSanitizer: %s-param-overlap: " + Report("ERROR: AddressSanitizer: %s: " "memory ranges [%p,%p) and [%p, %p) overlap\n", \ - function, offset1, offset1 + length1, offset2, offset2 + length2); + bug_type, offset1, offset1 + length1, offset2, offset2 + length2); Printf("%s", d.EndWarning()); PrintStack(stack); DescribeAddress((uptr)offset1, length1); DescribeAddress((uptr)offset2, length2); + ReportSummary(bug_type, stack); } // ----------------------- Mac-specific reports ----------------- {{{1 @@ -653,7 +691,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, PrintStack(&stack); DescribeAddress(addr, access_size); - + ReportSummary(bug_descr, &stack); PrintShadowMemoryForAddress(addr); } diff --git a/libsanitizer/asan/asan_report.h b/libsanitizer/asan/asan_report.h index a7e0e5816b7..13724dab9ee 100644 --- a/libsanitizer/asan/asan_report.h +++ b/libsanitizer/asan/asan_report.h @@ -13,15 +13,15 @@ #include "asan_allocator.h" #include "asan_internal.h" #include "asan_thread.h" -#include "sanitizer/asan_interface.h" namespace __asan { // The following functions prints address description depending // on the memory type (shadow/heap/stack/global). void DescribeHeapAddress(uptr addr, uptr access_size); -bool DescribeAddressIfGlobal(uptr addr); -bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g); +bool DescribeAddressIfGlobal(uptr addr, uptr access_size); +bool DescribeAddressRelativeToGlobal(uptr addr, uptr access_size, + const __asan_global &g); bool DescribeAddressIfShadow(uptr addr); bool DescribeAddressIfStack(uptr addr, uptr access_size); // Determines memory type on its own. diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc index 04d2d7af63f..175d37788c2 100644 --- a/libsanitizer/asan/asan_rtl.cc +++ b/libsanitizer/asan/asan_rtl.cc @@ -18,7 +18,6 @@ #include "asan_stats.h" #include "asan_thread.h" #include "asan_thread_registry.h" -#include "sanitizer/asan_interface.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_libc.h" @@ -83,7 +82,6 @@ static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->replace_str, "replace_str"); ParseFlag(str, &f->replace_intrin, "replace_intrin"); - ParseFlag(str, &f->replace_cfallocator, "replace_cfallocator"); ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free"); ParseFlag(str, &f->use_fake_stack, "use_fake_stack"); ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size"); @@ -95,6 +93,8 @@ static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size"); ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit"); ParseFlag(str, &f->abort_on_error, "abort_on_error"); + ParseFlag(str, &f->print_stats, "print_stats"); + ParseFlag(str, &f->print_legend, "print_legend"); ParseFlag(str, &f->atexit, "atexit"); ParseFlag(str, &f->disable_core, "disable_core"); ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix"); @@ -121,7 +121,6 @@ void InitializeFlags(Flags *f, const char *env) { f->malloc_context_size = kDeafultMallocContextSize; f->replace_str = true; f->replace_intrin = true; - f->replace_cfallocator = true; f->mac_ignore_invalid_free = false; f->use_fake_stack = true; f->max_malloc_fill_size = 0; @@ -133,6 +132,8 @@ void InitializeFlags(Flags *f, const char *env) { f->check_malloc_usable_size = true; f->unmap_shadow_on_exit = false; f->abort_on_error = false; + f->print_stats = false; + f->print_legend = true; f->atexit = false; f->disable_core = (SANITIZER_WORDSIZE == 64); f->strip_path_prefix = ""; @@ -142,9 +143,7 @@ void InitializeFlags(Flags *f, const char *env) { f->fast_unwind_on_fatal = false; f->fast_unwind_on_malloc = true; f->poison_heap = true; - // Turn off alloc/dealloc mismatch checker on Mac for now. - // TODO(glider): Fix known issues and enable this back. - f->alloc_dealloc_mismatch = (ASAN_MAC == 0); + f->alloc_dealloc_mismatch = true; f->use_stack_depot = true; // Only affects allocator2. // Override from user-specified string. @@ -162,6 +161,7 @@ void InitializeFlags(Flags *f, const char *env) { int asan_inited; bool asan_init_is_running; void (*death_callback)(void); +uptr kHighMemEnd; // -------------------------- Misc ---------------- {{{1 void ShowStatsAndAbort() { @@ -261,6 +261,24 @@ static void asan_atexit() { __asan_print_accumulated_stats(); } +static void InitializeHighMemEnd() { +#if SANITIZER_WORDSIZE == 64 +# if defined(__powerpc64__) + // FIXME: + // On PowerPC64 we have two different address space layouts: 44- and 46-bit. + // We somehow need to figure our which one we are using now and choose + // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL. + // Note that with 'ulimit -s unlimited' the stack is moved away from the top + // of the address space, so simply checking the stack address is not enough. + kHighMemEnd = (1ULL << 44) - 1; // 0x00000fffffffffffUL +# else + kHighMemEnd = (1ULL << 47) - 1; // 0x00007fffffffffffUL; +# endif +#else // SANITIZER_WORDSIZE == 32 + kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff; +#endif // SANITIZER_WORDSIZE +} + } // namespace __asan // ---------------------- Interface ---------------- {{{1 @@ -295,8 +313,10 @@ void NOINLINE __asan_set_death_callback(void (*callback)(void)) { void __asan_init() { if (asan_inited) return; + SanitizerToolName = "AddressSanitizer"; CHECK(!asan_init_is_running && "ASan init calls itself!"); asan_init_is_running = true; + InitializeHighMemEnd(); // Make sure we are not statically linked. AsanDoesNotSupportStaticLinkage(); @@ -400,6 +420,8 @@ void __asan_init() { asanThreadRegistry().GetMain()->ThreadStart(); force_interface_symbols(); // no-op. + InitializeAllocator(); + if (flags()->verbosity) { Report("AddressSanitizer Init done\n"); } diff --git a/libsanitizer/asan/asan_stack.cc b/libsanitizer/asan/asan_stack.cc index 9b6a28e8082..999cbfba757 100644 --- a/libsanitizer/asan/asan_stack.cc +++ b/libsanitizer/asan/asan_stack.cc @@ -9,9 +9,9 @@ // // Code for ASan stack trace. //===----------------------------------------------------------------------===// +#include "asan_internal.h" #include "asan_flags.h" #include "asan_stack.h" -#include "sanitizer/asan_interface.h" namespace __asan { diff --git a/libsanitizer/asan/asan_stats.cc b/libsanitizer/asan/asan_stats.cc index 1187bd92f97..935b33e20ac 100644 --- a/libsanitizer/asan/asan_stats.cc +++ b/libsanitizer/asan/asan_stats.cc @@ -13,7 +13,6 @@ #include "asan_internal.h" #include "asan_stats.h" #include "asan_thread_registry.h" -#include "sanitizer/asan_interface.h" #include "sanitizer_common/sanitizer_stackdepot.h" namespace __asan { diff --git a/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc b/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc index 757c704bd55..727edf2b43b 100644 --- a/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc +++ b/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc @@ -17,11 +17,6 @@ namespace __asan { -#if !MAC_INTERPOSE_FUNCTIONS -# error \ - Dynamic interposing library should be built with -DMAC_INTERPOSE_FUNCTIONS -#endif - #define INTERPOSE_FUNCTION(function) \ { reinterpret_cast<const uptr>(WRAP(function)), \ reinterpret_cast<const uptr>(function) } |