summaryrefslogtreecommitdiff
path: root/libsanitizer/asan
diff options
context:
space:
mode:
authorkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-13 10:46:01 +0000
committerkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-13 10:46:01 +0000
commit7da89e8076fc3bc8b0eb22721afdce421d225d71 (patch)
treec4504a71a4de65630ff00dd7aa8e062235fc5076 /libsanitizer/asan
parentc31c80df29f1ac080fd4b89965599e1b337b15a1 (diff)
downloadgcc-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')
-rw-r--r--libsanitizer/asan/asan_allocator.cc9
-rw-r--r--libsanitizer/asan/asan_allocator.h62
-rw-r--r--libsanitizer/asan/asan_allocator2.cc51
-rw-r--r--libsanitizer/asan/asan_fake_stack.cc1
-rw-r--r--libsanitizer/asan/asan_flags.h8
-rw-r--r--libsanitizer/asan/asan_globals.cc29
-rw-r--r--libsanitizer/asan/asan_intercepted_functions.h26
-rw-r--r--libsanitizer/asan/asan_interceptors.cc54
-rw-r--r--libsanitizer/asan/asan_interceptors.h3
-rw-r--r--libsanitizer/asan/asan_interface_internal.h133
-rw-r--r--libsanitizer/asan/asan_internal.h1
-rw-r--r--libsanitizer/asan/asan_mac.cc81
-rw-r--r--libsanitizer/asan/asan_malloc_linux.cc1
-rw-r--r--libsanitizer/asan/asan_mapping.h27
-rw-r--r--libsanitizer/asan/asan_new_delete.cc4
-rw-r--r--libsanitizer/asan/asan_poisoning.cc1
-rw-r--r--libsanitizer/asan/asan_report.cc104
-rw-r--r--libsanitizer/asan/asan_report.h6
-rw-r--r--libsanitizer/asan/asan_rtl.cc34
-rw-r--r--libsanitizer/asan/asan_stack.cc2
-rw-r--r--libsanitizer/asan/asan_stats.cc1
-rw-r--r--libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc5
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) }