summaryrefslogtreecommitdiff
path: root/libsanitizer/asan
diff options
context:
space:
mode:
authorkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2012-11-23 14:46:25 +0000
committerkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2012-11-23 14:46:25 +0000
commit0d996a11d9b5be7a52d77016de51910146ceaa90 (patch)
treea354102cd1c27b09eefe0b04f517d4ecac5bc566 /libsanitizer/asan
parenta46419387192ae39f45cfeca2ec0afe6f872956e (diff)
downloadgcc-0d996a11d9b5be7a52d77016de51910146ceaa90.tar.gz
[libsanitizer] merge from upstream r168514
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193756 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libsanitizer/asan')
-rw-r--r--libsanitizer/asan/asan_allocator.cc4
-rw-r--r--libsanitizer/asan/asan_intercepted_functions.h6
-rw-r--r--libsanitizer/asan/asan_interceptors.cc49
-rw-r--r--libsanitizer/asan/asan_internal.h1
-rw-r--r--libsanitizer/asan/asan_linux.cc28
-rw-r--r--libsanitizer/asan/asan_mac.cc20
-rw-r--r--libsanitizer/asan/asan_mac.h5
-rw-r--r--libsanitizer/asan/asan_malloc_mac.cc30
-rw-r--r--libsanitizer/asan/asan_mapping.h18
-rw-r--r--libsanitizer/asan/asan_new_delete.cc38
-rw-r--r--libsanitizer/asan/asan_report.cc22
-rw-r--r--libsanitizer/asan/asan_rtl.cc2
-rw-r--r--libsanitizer/asan/asan_stats.cc3
-rw-r--r--libsanitizer/asan/asan_thread.cc13
-rw-r--r--libsanitizer/asan/asan_thread_registry.cc23
-rw-r--r--libsanitizer/asan/asan_thread_registry.h4
-rw-r--r--libsanitizer/asan/asan_win.cc4
17 files changed, 191 insertions, 79 deletions
diff --git a/libsanitizer/asan/asan_allocator.cc b/libsanitizer/asan/asan_allocator.cc
index 3a92802e972..63ff607f858 100644
--- a/libsanitizer/asan/asan_allocator.cc
+++ b/libsanitizer/asan/asan_allocator.cc
@@ -56,7 +56,7 @@ static const uptr kMallocSizeClassStepLog = 26;
static const uptr kMallocSizeClassStep = 1UL << kMallocSizeClassStepLog;
static const uptr kMaxAllowedMallocSize =
- (__WORDSIZE == 32) ? 3UL << 30 : 8UL << 30;
+ (SANITIZER_WORDSIZE == 32) ? 3UL << 30 : 8UL << 30;
static inline bool IsAligned(uptr a, uptr alignment) {
return (a & (alignment - 1)) == 0;
@@ -83,7 +83,7 @@ static inline uptr RoundUpToPowerOfTwo(uptr size) {
unsigned long up; // NOLINT
#if !defined(_WIN32) || defined(__clang__)
- up = __WORDSIZE - 1 - __builtin_clzl(size);
+ up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(size);
#elif defined(_WIN64)
_BitScanReverse64(&up, size);
#else
diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h
index ceb596cd48e..62d1994130f 100644
--- a/libsanitizer/asan/asan_intercepted_functions.h
+++ b/libsanitizer/asan/asan_intercepted_functions.h
@@ -49,6 +49,12 @@ using __sanitizer::uptr;
# define ASAN_INTERCEPT_STRNLEN 0
#endif
+#if defined(__linux__) && !defined(ANDROID)
+# define ASAN_INTERCEPT_SWAPCONTEXT 1
+#else
+# define ASAN_INTERCEPT_SWAPCONTEXT 0
+#endif
+
#if !defined(ANDROID) && !defined(_WIN32)
# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
#else
diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc
index 8e15d341b8c..5b544c87fcb 100644
--- a/libsanitizer/asan/asan_interceptors.cc
+++ b/libsanitizer/asan/asan_interceptors.cc
@@ -134,6 +134,28 @@ DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
struct sigaction *oldact);
#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
+#if ASAN_INTERCEPT_SWAPCONTEXT
+INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
+ struct ucontext_t *ucp) {
+ static bool reported_warning = false;
+ if (!reported_warning) {
+ Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
+ "functions and may produce false positives in some cases!\n");
+ reported_warning = true;
+ }
+ // Clear shadow memory for new context (it may share stack
+ // with current context).
+ ClearShadowMemoryForContext(ucp);
+ int res = REAL(swapcontext)(oucp, ucp);
+ // swapcontext technically does not return, but program may swap context to
+ // "oucp" later, that would look as if swapcontext() returned 0.
+ // We need to clear shadow for ucp once again, as it may be in arbitrary
+ // state.
+ ClearShadowMemoryForContext(ucp);
+ return res;
+}
+#endif
+
INTERCEPTOR(void, longjmp, void *env, int val) {
__asan_handle_no_return();
REAL(longjmp)(env, val);
@@ -237,13 +259,17 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
ASAN_WRITE_RANGE(from, size);
ASAN_READ_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) {
-#if MAC_INTERPOSE_FUNCTIONS
- if (!asan_inited) return REAL(memmove)(to, from, size);
-#endif
+ if (!asan_inited) return internal_memmove(to, from, size);
if (asan_init_is_running) {
return REAL(memmove)(to, from, size);
}
@@ -252,7 +278,13 @@ INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
ASAN_WRITE_RANGE(from, size);
ASAN_READ_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) {
@@ -370,6 +402,14 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
#if ASAN_INTERCEPT_STRDUP
INTERCEPTOR(char*, strdup, const char *s) {
+#if MAC_INTERPOSE_FUNCTIONS
+ // 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
+ // starts using mmap() instead.
+ // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
+ if (!asan_inited) return REAL(strdup)(s);
+#endif
if (!asan_inited) return internal_strdup(s);
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
@@ -669,6 +709,9 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(sigaction);
ASAN_INTERCEPT_FUNC(signal);
#endif
+#if ASAN_INTERCEPT_SWAPCONTEXT
+ ASAN_INTERCEPT_FUNC(swapcontext);
+#endif
#if ASAN_INTERCEPT__LONGJMP
ASAN_INTERCEPT_FUNC(_longjmp);
#endif
diff --git a/libsanitizer/asan/asan_internal.h b/libsanitizer/asan/asan_internal.h
index 21368eef7c9..3a70ca44fd5 100644
--- a/libsanitizer/asan/asan_internal.h
+++ b/libsanitizer/asan/asan_internal.h
@@ -114,6 +114,7 @@ bool AsanInterceptsSignal(int signum);
void SetAlternateSignalStack();
void UnsetAlternateSignalStack();
void InstallSignalHandlers();
+void ClearShadowMemoryForContext(void *context);
void AsanPlatformThreadInit();
// Wrapper for TLS/TSD.
diff --git a/libsanitizer/asan/asan_linux.cc b/libsanitizer/asan/asan_linux.cc
index ea7ee9e7bc8..7295216b85d 100644
--- a/libsanitizer/asan/asan_linux.cc
+++ b/libsanitizer/asan/asan_linux.cc
@@ -66,6 +66,13 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
*pc = ucontext->uc_mcontext.gregs[REG_EIP];
*bp = ucontext->uc_mcontext.gregs[REG_EBP];
*sp = ucontext->uc_mcontext.gregs[REG_ESP];
+# elif defined(__powerpc__) || defined(__powerpc64__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.regs->nip;
+ *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
+ // The powerpc{,64}-linux ABIs do not specify r31 as the frame
+ // pointer, but GCC always uses r31 when we need a frame pointer.
+ *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
# elif defined(__sparc__)
ucontext_t *ucontext = (ucontext_t*)context;
uptr *stk_ptr;
@@ -149,8 +156,10 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
stack->trace[0] = pc;
if ((max_s) > 1) {
stack->max_size = max_s;
-#ifdef __arm__
+#if defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__)
_Unwind_Backtrace(Unwind_Trace, stack);
+ // Pop off the two ASAN functions from the backtrace.
+ stack->PopStackFrames(2);
#else
if (!asan_inited) return;
if (AsanThread *t = asanThreadRegistry().GetCurrent())
@@ -159,6 +168,23 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
}
}
+#if !ASAN_ANDROID
+void ClearShadowMemoryForContext(void *context) {
+ ucontext_t *ucp = (ucontext_t*)context;
+ uptr sp = (uptr)ucp->uc_stack.ss_sp;
+ uptr size = ucp->uc_stack.ss_size;
+ // Align to page size.
+ uptr bottom = sp & ~(kPageSize - 1);
+ size += sp - bottom;
+ size = RoundUpTo(size, kPageSize);
+ PoisonShadow(bottom, size, 0);
+}
+#else
+void ClearShadowMemoryForContext(void *context) {
+ UNIMPLEMENTED();
+}
+#endif
+
} // namespace __asan
#endif // __linux__
diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc
index 81e25e8ef59..ae5edd97165 100644
--- a/libsanitizer/asan/asan_mac.cc
+++ b/libsanitizer/asan/asan_mac.cc
@@ -40,7 +40,7 @@ namespace __asan {
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
ucontext_t *ucontext = (ucontext_t*)context;
-# if __WORDSIZE == 64
+# if SANITIZER_WORDSIZE == 64
*pc = ucontext->uc_mcontext->__ss.__rip;
*bp = ucontext->uc_mcontext->__ss.__rbp;
*sp = ucontext->uc_mcontext->__ss.__rsp;
@@ -48,7 +48,7 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
*pc = ucontext->uc_mcontext->__ss.__eip;
*bp = ucontext->uc_mcontext->__ss.__ebp;
*sp = ucontext->uc_mcontext->__ss.__esp;
-# endif // __WORDSIZE
+# endif // SANITIZER_WORDSIZE
}
int GetMacosVersion() {
@@ -66,6 +66,7 @@ int GetMacosVersion() {
switch (version[1]) {
case '0': return MACOS_VERSION_SNOW_LEOPARD;
case '1': return MACOS_VERSION_LION;
+ case '2': return MACOS_VERSION_MOUNTAIN_LION;
default: return MACOS_VERSION_UNKNOWN;
}
}
@@ -128,7 +129,14 @@ bool AsanInterceptsSignal(int signum) {
}
void AsanPlatformThreadInit() {
- ReplaceCFAllocator();
+ // For the first program thread, we can't replace the allocator before
+ // __CFInitialize() has been called. If it hasn't, we'll call
+ // MaybeReplaceCFAllocator() later on this thread.
+ // For other threads __CFInitialize() has been called before their creation.
+ // See also asan_malloc_mac.cc.
+ if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) {
+ MaybeReplaceCFAllocator();
+ }
}
AsanLock::AsanLock(LinkerInitialized) {
@@ -161,6 +169,10 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
}
}
+void ClearShadowMemoryForContext(void *context) {
+ 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.
@@ -169,7 +181,7 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
// kHighMemBeg or kHighMemEnd.
static void *island_allocator_pos = 0;
-#if __WORDSIZE == 32
+#if SANITIZER_WORDSIZE == 32
# define kIslandEnd (0xffdf0000 - kPageSize)
# define kIslandBeg (kIslandEnd - 256 * kPageSize)
#else
diff --git a/libsanitizer/asan/asan_mac.h b/libsanitizer/asan/asan_mac.h
index 18aca0dd84e..2c162fb0c39 100644
--- a/libsanitizer/asan/asan_mac.h
+++ b/libsanitizer/asan/asan_mac.h
@@ -38,7 +38,8 @@ enum {
MACOS_VERSION_UNKNOWN = 0,
MACOS_VERSION_LEOPARD,
MACOS_VERSION_SNOW_LEOPARD,
- MACOS_VERSION_LION
+ MACOS_VERSION_LION,
+ MACOS_VERSION_MOUNTAIN_LION
};
// Used by asan_malloc_mac.cc and asan_mac.cc
@@ -47,7 +48,7 @@ extern "C" void __CFInitialize();
namespace __asan {
int GetMacosVersion();
-void ReplaceCFAllocator();
+void MaybeReplaceCFAllocator();
} // namespace __asan
diff --git a/libsanitizer/asan/asan_malloc_mac.cc b/libsanitizer/asan/asan_malloc_mac.cc
index 2df34845f12..3f281c9cc3b 100644
--- a/libsanitizer/asan/asan_malloc_mac.cc
+++ b/libsanitizer/asan/asan_malloc_mac.cc
@@ -95,10 +95,6 @@ INTERCEPTOR(void, free, void *ptr) {
}
}
-namespace __asan {
- void ReplaceCFAllocator();
-}
-
// We can't always replace the default CFAllocator with cf_asan right in
// ReplaceSystemMalloc(), because it is sometimes called before
// __CFInitialize(), when the default allocator is invalid and replacing it may
@@ -116,7 +112,7 @@ INTERCEPTOR(void, __CFInitialize, void) {
CHECK(asan_inited);
#endif
REAL(__CFInitialize)();
- if (!cf_asan && asan_inited) ReplaceCFAllocator();
+ if (!cf_asan && asan_inited) MaybeReplaceCFAllocator();
}
namespace {
@@ -291,12 +287,10 @@ size_t mi_good_size(malloc_zone_t *zone, size_t size) {
boolean_t mi_check(malloc_zone_t *zone) {
UNIMPLEMENTED();
- return true;
}
void mi_print(malloc_zone_t *zone, boolean_t verbose) {
UNIMPLEMENTED();
- return;
}
void mi_log(malloc_zone_t *zone, void *address) {
@@ -331,7 +325,7 @@ boolean_t mi_zone_locked(malloc_zone_t *zone) {
extern int __CFRuntimeClassTableSize;
namespace __asan {
-void ReplaceCFAllocator() {
+void MaybeReplaceCFAllocator() {
static CFAllocatorContext asan_context = {
/*version*/ 0, /*info*/ &asan_zone,
/*retain*/ 0, /*release*/ 0,
@@ -342,7 +336,7 @@ void ReplaceCFAllocator() {
/*preferredSize*/ 0 };
if (!cf_asan)
cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context);
- if (CFAllocatorGetDefault() != cf_asan)
+ if (flags()->replace_cfallocator && CFAllocatorGetDefault() != cf_asan)
CFAllocatorSetDefault(cf_asan);
}
@@ -410,16 +404,14 @@ void ReplaceSystemMalloc() {
// Make sure the default allocator was replaced.
CHECK(malloc_default_zone() == &asan_zone);
- if (flags()->replace_cfallocator) {
- // If __CFInitialize() hasn't been called yet, cf_asan will be created and
- // installed as the default allocator after __CFInitialize() finishes (see
- // the interceptor for __CFInitialize() above). Otherwise install cf_asan
- // right now. On both Snow Leopard and Lion __CFInitialize() calls
- // __CFAllocatorInitialize(), which initializes the _base._cfisa field of
- // the default allocators we check here.
- if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) {
- ReplaceCFAllocator();
- }
+ // If __CFInitialize() hasn't been called yet, cf_asan will be created and
+ // installed as the default allocator after __CFInitialize() finishes (see
+ // the interceptor for __CFInitialize() above). Otherwise install cf_asan
+ // right now. On both Snow Leopard and Lion __CFInitialize() calls
+ // __CFAllocatorInitialize(), which initializes the _base._cfisa field of
+ // the default allocators we check here.
+ if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) {
+ MaybeReplaceCFAllocator();
}
}
} // namespace __asan
diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h
index 40a38db0544..c93280fdd6c 100644
--- a/libsanitizer/asan/asan_mapping.h
+++ b/libsanitizer/asan/asan_mapping.h
@@ -28,10 +28,14 @@ extern __attribute__((visibility("default"))) uptr __asan_mapping_offset;
# define SHADOW_OFFSET (0)
# else
# define SHADOW_SCALE (3)
-# if __WORDSIZE == 32
+# if SANITIZER_WORDSIZE == 32
# define SHADOW_OFFSET (1 << 29)
# else
-# define SHADOW_OFFSET (1ULL << 44)
+# if defined(__powerpc64__)
+# define SHADOW_OFFSET (1ULL << 41)
+# else
+# define SHADOW_OFFSET (1ULL << 44)
+# endif
# endif
# endif
#endif // ASAN_FLEXIBLE_MAPPING_AND_OFFSET
@@ -40,11 +44,15 @@ extern __attribute__((visibility("default"))) uptr __asan_mapping_offset;
#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) | (SHADOW_OFFSET))
#define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE)
-#if __WORDSIZE == 64
+#if SANITIZER_WORDSIZE == 64
+# if defined(__powerpc64__)
+ static const uptr kHighMemEnd = 0x00000fffffffffffUL;
+# else
static const uptr kHighMemEnd = 0x00007fffffffffffUL;
-#else // __WORDSIZE == 32
+# endif
+#else // SANITIZER_WORDSIZE == 32
static const uptr kHighMemEnd = 0xffffffff;
-#endif // __WORDSIZE
+#endif // SANITIZER_WORDSIZE
#define kLowMemBeg 0
diff --git a/libsanitizer/asan/asan_new_delete.cc b/libsanitizer/asan/asan_new_delete.cc
index a2180ae9444..8132e58b6e2 100644
--- a/libsanitizer/asan/asan_new_delete.cc
+++ b/libsanitizer/asan/asan_new_delete.cc
@@ -15,7 +15,6 @@
#include "asan_stack.h"
#include <stddef.h>
-#include <new>
namespace __asan {
// This function is a no-op. We need it to make sure that object file
@@ -26,29 +25,40 @@ void ReplaceOperatorsNewAndDelete() { }
using namespace __asan; // NOLINT
+// On Android new() goes through malloc interceptors.
+#if !ASAN_ANDROID
+
+// Fake std::nothrow_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+} // namespace std
+
#define OPERATOR_NEW_BODY \
GET_STACK_TRACE_HERE_FOR_MALLOC;\
return asan_memalign(0, size, &stack);
-#if ASAN_ANDROID
+INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY; }
+INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
-#else
-void *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
-void *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
-void *operator new(size_t size, std::nothrow_t const&) throw()
-{ OPERATOR_NEW_BODY; }
-void *operator new[](size_t size, std::nothrow_t const&) throw()
-{ OPERATOR_NEW_BODY; }
-#endif
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
#define OPERATOR_DELETE_BODY \
GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
asan_free(ptr, &stack);
-void operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
-void operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
-void operator delete(void *ptr, std::nothrow_t const&) throw()
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&)
{ OPERATOR_DELETE_BODY; }
-void operator delete[](void *ptr, std::nothrow_t const&) throw()
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&)
{ OPERATOR_DELETE_BODY; }
+
+#endif
diff --git a/libsanitizer/asan/asan_report.cc b/libsanitizer/asan/asan_report.cc
index 7e6381c2beb..c35b4ec14f7 100644
--- a/libsanitizer/asan/asan_report.cc
+++ b/libsanitizer/asan/asan_report.cc
@@ -42,7 +42,7 @@ void AppendToErrorMessageBuffer(const char *buffer) {
static void PrintBytes(const char *before, uptr *a) {
u8 *bytes = (u8*)a;
- uptr byte_num = (__WORDSIZE) / 8;
+ uptr byte_num = (SANITIZER_WORDSIZE) / 8;
Printf("%s%p:", before, (void*)a);
for (uptr i = 0; i < byte_num; i++) {
Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
@@ -178,7 +178,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
}
Printf("HINT: this may be a false positive if your program uses "
- "some custom stack unwind mechanism\n"
+ "some custom stack unwind mechanism or swapcontext\n"
" (longjmp and C++ exceptions *are* supported)\n");
DescribeThread(t->summary());
return true;
@@ -287,7 +287,9 @@ class ScopedInErrorReport {
// an error report will finish doing it.
SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
}
- Die();
+ // If we're still not dead for some reason, use raw Exit() instead of
+ // Die() to bypass any additional checks.
+ Exit(flags()->exitcode);
}
__asan_on_error();
reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
@@ -320,7 +322,7 @@ class ScopedInErrorReport {
void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
ScopedInErrorReport in_report;
- Report("ERROR: AddressSanitizer crashed on unknown address %p"
+ Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
" (pc %p sp %p bp %p T%d)\n",
(void*)addr, (void*)pc, (void*)sp, (void*)bp,
asanThreadRegistry().GetCurrentTidOrInvalid());
@@ -331,14 +333,14 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
void ReportDoubleFree(uptr addr, StackTrace *stack) {
ScopedInErrorReport in_report;
- Report("ERROR: AddressSanitizer attempting double-free on %p:\n", addr);
+ Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
PrintStack(stack);
DescribeHeapAddress(addr, 1);
}
void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
ScopedInErrorReport in_report;
- Report("ERROR: AddressSanitizer attempting free on address "
+ Report("ERROR: AddressSanitizer: attempting free on address "
"which was not malloc()-ed: %p\n", addr);
PrintStack(stack);
DescribeHeapAddress(addr, 1);
@@ -346,7 +348,7 @@ void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
ScopedInErrorReport in_report;
- Report("ERROR: AddressSanitizer attempting to call "
+ Report("ERROR: AddressSanitizer: attempting to call "
"malloc_usable_size() for pointer which is "
"not owned: %p\n", addr);
PrintStack(stack);
@@ -355,7 +357,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
ScopedInErrorReport in_report;
- Report("ERROR: AddressSanitizer attempting to call "
+ Report("ERROR: AddressSanitizer: attempting to call "
"__asan_get_allocated_size() for pointer which is "
"not owned: %p\n", addr);
PrintStack(stack);
@@ -366,7 +368,7 @@ void ReportStringFunctionMemoryRangesOverlap(
const char *function, const char *offset1, uptr length1,
const char *offset2, uptr length2, StackTrace *stack) {
ScopedInErrorReport in_report;
- Report("ERROR: AddressSanitizer %s-param-overlap: "
+ Report("ERROR: AddressSanitizer: %s-param-overlap: "
"memory ranges [%p,%p) and [%p, %p) overlap\n", \
function, offset1, offset1 + length1, offset2, offset2 + length2);
PrintStack(stack);
@@ -459,7 +461,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
}
}
- Report("ERROR: AddressSanitizer %s on address "
+ Report("ERROR: AddressSanitizer: %s on address "
"%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
bug_descr, (void*)addr, pc, bp, sp);
diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc
index 442d41c4f23..7731c17a351 100644
--- a/libsanitizer/asan/asan_rtl.cc
+++ b/libsanitizer/asan/asan_rtl.cc
@@ -132,7 +132,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->unmap_shadow_on_exit = false;
f->abort_on_error = false;
f->atexit = false;
- f->disable_core = (__WORDSIZE == 64);
+ f->disable_core = (SANITIZER_WORDSIZE == 64);
f->strip_path_prefix = "";
f->allow_reexec = true;
f->print_full_thread_history = true;
diff --git a/libsanitizer/asan/asan_stats.cc b/libsanitizer/asan/asan_stats.cc
index fa4adcb7f9a..ecdf5ffad09 100644
--- a/libsanitizer/asan/asan_stats.cc
+++ b/libsanitizer/asan/asan_stats.cc
@@ -54,7 +54,8 @@ void AsanStats::Print() {
static AsanLock print_lock(LINKER_INITIALIZED);
static void PrintAccumulatedStats() {
- AsanStats stats = asanThreadRegistry().GetAccumulatedStats();
+ AsanStats stats;
+ asanThreadRegistry().GetAccumulatedStats(&stats);
// Use lock to keep reports from mixing up.
ScopedLock lock(&print_lock);
stats.Print();
diff --git a/libsanitizer/asan/asan_thread.cc b/libsanitizer/asan/asan_thread.cc
index 9295c1570ec..4ec98e5ed22 100644
--- a/libsanitizer/asan/asan_thread.cc
+++ b/libsanitizer/asan/asan_thread.cc
@@ -116,25 +116,25 @@ void AsanThread::ClearShadowForThreadStack() {
const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
uptr bottom = 0;
- bool is_fake_stack = false;
if (AddrIsInStack(addr)) {
bottom = stack_bottom();
} else {
bottom = fake_stack().AddrIsInFakeStack(addr);
CHECK(bottom);
- is_fake_stack = true;
+ *offset = addr - bottom;
+ return (const char *)((uptr*)bottom)[1];
}
- uptr aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr.
+ uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1); // align addr.
u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
u8 *shadow_bottom = (u8*)MemToShadow(bottom);
while (shadow_ptr >= shadow_bottom &&
- *shadow_ptr != kAsanStackLeftRedzoneMagic) {
+ *shadow_ptr != kAsanStackLeftRedzoneMagic) {
shadow_ptr--;
}
while (shadow_ptr >= shadow_bottom &&
- *shadow_ptr == kAsanStackLeftRedzoneMagic) {
+ *shadow_ptr == kAsanStackLeftRedzoneMagic) {
shadow_ptr--;
}
@@ -144,8 +144,7 @@ const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
}
uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
- CHECK((ptr[0] == kCurrentStackFrameMagic) ||
- (is_fake_stack && ptr[0] == kRetiredStackFrameMagic));
+ CHECK(ptr[0] == kCurrentStackFrameMagic);
*offset = addr - (uptr)ptr;
return (const char*)ptr[1];
}
diff --git a/libsanitizer/asan/asan_thread_registry.cc b/libsanitizer/asan/asan_thread_registry.cc
index 840837e0004..9858cce22b0 100644
--- a/libsanitizer/asan/asan_thread_registry.cc
+++ b/libsanitizer/asan/asan_thread_registry.cc
@@ -102,16 +102,20 @@ AsanStats &AsanThreadRegistry::GetCurrentThreadStats() {
return (t) ? t->stats() : main_thread_.stats();
}
-AsanStats AsanThreadRegistry::GetAccumulatedStats() {
+void AsanThreadRegistry::GetAccumulatedStats(AsanStats *stats) {
ScopedLock lock(&mu_);
UpdateAccumulatedStatsUnlocked();
- return accumulated_stats_;
+ internal_memcpy(stats, &accumulated_stats_, sizeof(accumulated_stats_));
}
uptr AsanThreadRegistry::GetCurrentAllocatedBytes() {
ScopedLock lock(&mu_);
UpdateAccumulatedStatsUnlocked();
- return accumulated_stats_.malloced - accumulated_stats_.freed;
+ uptr malloced = accumulated_stats_.malloced;
+ uptr freed = accumulated_stats_.freed;
+ // Return sane value if malloced < freed due to racy
+ // way we update accumulated stats.
+ return (malloced > freed) ? malloced - freed : 1;
}
uptr AsanThreadRegistry::GetHeapSize() {
@@ -123,11 +127,14 @@ uptr AsanThreadRegistry::GetHeapSize() {
uptr AsanThreadRegistry::GetFreeBytes() {
ScopedLock lock(&mu_);
UpdateAccumulatedStatsUnlocked();
- return accumulated_stats_.mmaped
- - accumulated_stats_.malloced
- - accumulated_stats_.malloced_redzones
- + accumulated_stats_.really_freed
- + accumulated_stats_.really_freed_redzones;
+ uptr total_free = accumulated_stats_.mmaped
+ + accumulated_stats_.really_freed
+ + accumulated_stats_.really_freed_redzones;
+ uptr total_used = accumulated_stats_.malloced
+ + accumulated_stats_.malloced_redzones;
+ // Return sane value if total_free < total_used due to racy
+ // way we update accumulated stats.
+ return (total_free > total_used) ? total_free - total_used : 1;
}
// Return several stats counters with a single call to
diff --git a/libsanitizer/asan/asan_thread_registry.h b/libsanitizer/asan/asan_thread_registry.h
index 99d5cb56af0..bb6b2678faa 100644
--- a/libsanitizer/asan/asan_thread_registry.h
+++ b/libsanitizer/asan/asan_thread_registry.h
@@ -45,9 +45,9 @@ class AsanThreadRegistry {
// Returns stats for GetCurrent(), or stats for
// T0 if GetCurrent() returns 0.
AsanStats &GetCurrentThreadStats();
- // Flushes all thread-local stats to accumulated stats, and returns
+ // Flushes all thread-local stats to accumulated stats, and makes
// a copy of accumulated stats.
- AsanStats GetAccumulatedStats();
+ void GetAccumulatedStats(AsanStats *stats);
uptr GetCurrentAllocatedBytes();
uptr GetHeapSize();
uptr GetFreeBytes();
diff --git a/libsanitizer/asan/asan_win.cc b/libsanitizer/asan/asan_win.cc
index a5c0441dafa..8b7f9ef0e38 100644
--- a/libsanitizer/asan/asan_win.cc
+++ b/libsanitizer/asan/asan_win.cc
@@ -137,6 +137,10 @@ void AsanPlatformThreadInit() {
// Nothing here for now.
}
+void ClearShadowMemoryForContext(void *context) {
+ UNIMPLEMENTED();
+}
+
} // namespace __asan
// ---------------------- Interface ---------------- {{{1